14#include "ruby/internal/config.h"
24#include "debug_counter.h"
28#include "internal/array.h"
29#include "internal/compar.h"
30#include "internal/compilers.h"
31#include "internal/concurrent_set.h"
32#include "internal/encoding.h"
33#include "internal/error.h"
34#include "internal/gc.h"
35#include "internal/hash.h"
36#include "internal/numeric.h"
37#include "internal/object.h"
38#include "internal/proc.h"
39#include "internal/re.h"
40#include "internal/sanitizers.h"
41#include "internal/string.h"
42#include "internal/transcode.h"
49#include "ruby_assert.h"
54#if defined HAVE_CRYPT_R
55# if defined HAVE_CRYPT_H
58#elif !defined HAVE_CRYPT
59# include "missing/crypt.h"
60# define HAVE_CRYPT_R 1
63#define BEG(no) (regs->beg[(no)])
64#define END(no) (regs->end[(no)])
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
131#define RUBY_MAX_CHAR_LEN 16
132#define STR_PRECOMPUTED_HASH FL_USER4
133#define STR_SHARED_ROOT FL_USER5
134#define STR_BORROWED FL_USER6
135#define STR_TMPLOCK FL_USER7
136#define STR_NOFREE FL_USER18
137#define STR_FAKESTR FL_USER19
139#define STR_SET_NOEMBED(str) do {\
140 FL_SET((str), STR_NOEMBED);\
141 FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\
143#define STR_SET_EMBED(str) FL_UNSET((str), STR_NOEMBED | STR_SHARED | STR_NOFREE)
145#define STR_SET_LEN(str, n) do { \
146 RSTRING(str)->len = (n); \
150str_encindex_fastpath(
int encindex)
154 case ENCINDEX_ASCII_8BIT:
156 case ENCINDEX_US_ASCII:
164str_enc_fastpath(
VALUE str)
169#define TERM_LEN(str) (str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
170#define TERM_FILL(ptr, termlen) do {\
171 char *const term_fill_ptr = (ptr);\
172 const int term_fill_len = (termlen);\
173 *term_fill_ptr = '\0';\
174 if (UNLIKELY(term_fill_len > 1))\
175 memset(term_fill_ptr, 0, term_fill_len);\
178#define RESIZE_CAPA(str,capacity) do {\
179 const int termlen = TERM_LEN(str);\
180 RESIZE_CAPA_TERM(str,capacity,termlen);\
182#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
183 if (STR_EMBED_P(str)) {\
184 if (str_embed_capa(str) < capacity + termlen) {\
185 char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
186 const long tlen = RSTRING_LEN(str);\
187 memcpy(tmp, RSTRING_PTR(str), tlen);\
188 RSTRING(str)->as.heap.ptr = tmp;\
189 RSTRING(str)->len = tlen;\
190 STR_SET_NOEMBED(str);\
191 RSTRING(str)->as.heap.aux.capa = (capacity);\
195 RUBY_ASSERT(!FL_TEST((str), STR_SHARED)); \
196 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
197 (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
198 RSTRING(str)->as.heap.aux.capa = (capacity);\
202#define STR_SET_SHARED(str, shared_str) do { \
203 if (!FL_TEST(str, STR_FAKESTR)) { \
204 RUBY_ASSERT(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \
205 RUBY_ASSERT(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \
206 RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
207 FL_SET((str), STR_SHARED); \
208 FL_SET((shared_str), STR_SHARED_ROOT); \
209 if (RBASIC_CLASS((shared_str)) == 0) \
210 FL_SET_RAW((shared_str), STR_BORROWED); \
214#define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr)
215#define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str))
218#define STR_ENC_GET(str) get_encoding(str)
220#if !defined SHARABLE_MIDDLE_SUBSTRING
221# define SHARABLE_MIDDLE_SUBSTRING 0
223#if !SHARABLE_MIDDLE_SUBSTRING
224#define SHARABLE_SUBSTRING_P(beg, len, end) ((beg) + (len) == (end))
226#define SHARABLE_SUBSTRING_P(beg, len, end) 1
231str_embed_capa(
VALUE str)
233 return rb_gc_obj_slot_size(str) - offsetof(
struct RString, as.embed.ary);
237rb_str_reembeddable_p(
VALUE str)
239 return !
FL_TEST(str, STR_NOFREE|STR_SHARED_ROOT|STR_SHARED);
243rb_str_embed_size(
long capa,
long termlen)
245 size_t size = offsetof(
struct RString, as.embed.ary) +
capa + 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));
283static VALUE str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding);
284static VALUE str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex);
286static void str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen);
287static inline void str_modifiable(
VALUE str);
292str_make_independent(
VALUE str)
294 long len = RSTRING_LEN(str);
295 int termlen = TERM_LEN(str);
296 str_make_independent_expand((str),
len, 0L, termlen);
299static inline int str_dependent_p(
VALUE str);
302rb_str_make_independent(
VALUE str)
304 if (str_dependent_p(str)) {
305 str_make_independent(str);
310rb_str_make_embedded(
VALUE str)
315 char *buf =
RSTRING(str)->as.heap.ptr;
319 STR_SET_LEN(str,
len);
322 memcpy(RSTRING_PTR(str), buf,
len);
326 TERM_FILL(
RSTRING(str)->as.embed.ary +
len, TERM_LEN(str));
330rb_debug_rstring_null_ptr(
const char *func)
332 fprintf(stderr,
"%s is returning NULL!! "
333 "SIGSEGV is highly expected to follow immediately.\n"
334 "If you could reproduce, attach your debugger here, "
335 "and look at the passed string.\n",
340static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
343get_encoding(
VALUE str)
349mustnot_broken(
VALUE str)
351 if (is_broken_string(str)) {
352 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
357mustnot_wchar(
VALUE str)
359 rb_encoding *enc = STR_ENC_GET(str);
360 if (rb_enc_mbminlen(enc) > 1) {
361 rb_raise(rb_eArgError,
"wide char encoding: %s", rb_enc_name(enc));
365static VALUE register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash);
367#if SIZEOF_LONG == SIZEOF_VOIDP
368#define PRECOMPUTED_FAKESTR_HASH 1
373BARE_STRING_P(
VALUE str)
375 return RBASIC_CLASS(str) ==
rb_cString && !rb_shape_obj_has_ivars(str);
378static inline st_index_t
379str_do_hash(
VALUE str)
381 st_index_t h =
rb_memhash((
const void *)RSTRING_PTR(str), RSTRING_LEN(str));
383 if (e && !is_ascii_string(str)) {
390str_store_precomputed_hash(
VALUE str, st_index_t hash)
396 size_t used_bytes = (RSTRING_LEN(str) + TERM_LEN(str));
397 size_t free_bytes = str_embed_capa(str) - used_bytes;
401 memcpy(RSTRING_END(str) + TERM_LEN(str), &hash,
sizeof(hash));
403 FL_SET(str, STR_PRECOMPUTED_HASH);
416 if (
FL_TEST(str, RSTRING_FSTR))
419 bare = BARE_STRING_P(str);
421 if (STR_EMBED_P(str)) {
426 if (
FL_TEST_RAW(str, STR_SHARED_ROOT | STR_SHARED) == STR_SHARED_ROOT) {
433 rb_str_resize(str, RSTRING_LEN(str));
435 fstr = register_fstring(str,
false,
false);
438 str_replace_shared_without_enc(str, fstr);
445static VALUE fstring_table_obj;
448fstring_concurrent_set_hash(
VALUE str)
450#ifdef PRECOMPUTED_FAKESTR_HASH
454 h = (st_index_t)
RSTRING(str)->as.heap.aux.capa;
471 const char *aptr, *bptr;
478 return (alen == blen &&
480 memcmp(aptr, bptr, alen) == 0);
485 bool force_precompute_hash;
489fstring_concurrent_set_create(
VALUE str,
void *data)
499 long len = RSTRING_LEN(str);
500 long capa =
len +
sizeof(st_index_t);
501 int term_len = TERM_LEN(str);
503 if (arg->force_precompute_hash && STR_EMBEDDABLE_P(
capa, term_len)) {
505 memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str),
len);
506 STR_SET_LEN(new_str, RSTRING_LEN(str));
507 TERM_FILL(RSTRING_END(new_str), TERM_LEN(str));
508 rb_enc_copy(new_str, str);
509 str_store_precomputed_hash(new_str, str_do_hash(str));
513 rb_enc_copy(new_str, str);
514#ifdef PRECOMPUTED_FAKESTR_HASH
515 if (
rb_str_capacity(new_str) >= RSTRING_LEN(str) + term_len +
sizeof(st_index_t)) {
516 str_store_precomputed_hash(new_str, (st_index_t)
RSTRING(str)->as.heap.aux.capa);
530 if (!
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
533 if (STR_SHARED_P(str)) {
535 str_make_independent(str);
538 if (!BARE_STRING_P(str)) {
544 RBASIC(str)->flags |= RSTRING_FSTR;
546 RB_OBJ_SET_SHAREABLE(str);
560 .hash = fstring_concurrent_set_hash,
561 .cmp = fstring_concurrent_set_cmp,
562 .create = fstring_concurrent_set_create,
567Init_fstring_table(
void)
569 fstring_table_obj = rb_concurrent_set_new(&fstring_concurrent_set_funcs, 8192);
570 rb_gc_register_address(&fstring_table_obj);
574register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash)
578 .force_precompute_hash = force_precompute_hash
581#if SIZEOF_VOIDP == SIZEOF_LONG
585 RSTRING(str)->as.heap.aux.capa = (long)str_do_hash(str);
589 VALUE result = rb_concurrent_set_find_or_insert(&fstring_table_obj, str, &args);
591 RUBY_ASSERT(!rb_objspace_garbage_object_p(result));
603rb_obj_is_fstring_table(
VALUE obj)
607 return obj == fstring_table_obj;
611rb_gc_free_fstring(
VALUE obj)
613 ASSERT_vm_locking_with_barrier();
619 rb_concurrent_set_delete_by_identity(fstring_table_obj, obj);
621 RB_DEBUG_COUNTER_INC(obj_str_fstr);
627rb_fstring_foreach_with_replace(
int (*callback)(
VALUE *str,
void *data),
void *data)
629 if (fstring_table_obj) {
630 rb_concurrent_set_foreach_with_replace(fstring_table_obj, callback, data);
635setup_fake_str(
struct RString *fake_str,
const char *name,
long len,
int encidx)
638 RBASIC_SET_SHAPE_ID((
VALUE)fake_str, ROOT_SHAPE_ID);
649 fake_str->as.heap.ptr = (
char *)name;
650 fake_str->as.heap.aux.capa =
len;
651 return (
VALUE)fake_str;
658rb_setup_fake_str(
struct RString *fake_str,
const char *name,
long len, rb_encoding *enc)
660 return setup_fake_str(fake_str, name,
len, rb_enc_to_index(enc));
669rb_fstring_new(
const char *
ptr,
long len)
671 struct RString fake_str = {RBASIC_INIT};
672 return register_fstring(setup_fake_str(&fake_str,
ptr,
len, ENCINDEX_US_ASCII),
false,
false);
676rb_fstring_enc_new(
const char *
ptr,
long len, rb_encoding *enc)
678 struct RString fake_str = {RBASIC_INIT};
679 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
false,
false);
683rb_fstring_cstr(
const char *
ptr)
685 return rb_fstring_new(
ptr, strlen(
ptr));
689single_byte_optimizable(
VALUE str)
693 case ENCINDEX_ASCII_8BIT:
694 case ENCINDEX_US_ASCII:
705 if (rb_enc_mbmaxlen(rb_enc_from_index(encindex)) == 1) {
716static inline const char *
717search_nonascii(
const char *p,
const char *e)
721#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
722# if SIZEOF_UINTPTR_T == 8
723# define NONASCII_MASK UINT64_C(0x8080808080808080)
724# elif SIZEOF_UINTPTR_T == 4
725# define NONASCII_MASK UINT32_C(0x80808080)
727# error "don't know what to do."
730# if SIZEOF_UINTPTR_T == 8
731# define NONASCII_MASK ((uintptr_t)0x80808080UL << 32 | (uintptr_t)0x80808080UL)
732# elif SIZEOF_UINTPTR_T == 4
733# define NONASCII_MASK 0x80808080UL
735# error "don't know what to do."
739 if (UNALIGNED_WORD_ACCESS || e - p >= SIZEOF_VOIDP) {
740#if !UNALIGNED_WORD_ACCESS
741 if ((uintptr_t)p % SIZEOF_VOIDP) {
742 int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
747 case 7:
if (p[-7]&0x80)
return p-7;
748 case 6:
if (p[-6]&0x80)
return p-6;
749 case 5:
if (p[-5]&0x80)
return p-5;
750 case 4:
if (p[-4]&0x80)
return p-4;
752 case 3:
if (p[-3]&0x80)
return p-3;
753 case 2:
if (p[-2]&0x80)
return p-2;
754 case 1:
if (p[-1]&0x80)
return p-1;
759#if defined(HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED) &&! UNALIGNED_WORD_ACCESS
760#define aligned_ptr(value) \
761 __builtin_assume_aligned((value), sizeof(uintptr_t))
763#define aligned_ptr(value) (value)
766 t = (e - (SIZEOF_VOIDP-1));
768 for (;s < t; s +=
sizeof(uintptr_t)) {
770 memcpy(&word, s,
sizeof(word));
771 if (word & NONASCII_MASK) {
772#ifdef WORDS_BIGENDIAN
773 return (
const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
775 return (
const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
785 case 7:
if (e[-7]&0x80)
return e-7;
786 case 6:
if (e[-6]&0x80)
return e-6;
787 case 5:
if (e[-5]&0x80)
return e-5;
788 case 4:
if (e[-4]&0x80)
return e-4;
790 case 3:
if (e[-3]&0x80)
return e-3;
791 case 2:
if (e[-2]&0x80)
return e-2;
792 case 1:
if (e[-1]&0x80)
return e-1;
798coderange_scan(
const char *p,
long len, rb_encoding *enc)
800 const char *e = p +
len;
802 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
804 p = search_nonascii(p, e);
808 if (rb_enc_asciicompat(enc)) {
809 p = search_nonascii(p, e);
812 int ret = rb_enc_precise_mbclen(p, e, enc);
816 p = search_nonascii(p, e);
822 int ret = rb_enc_precise_mbclen(p, e, enc);
838 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
841 p = search_nonascii(p, e);
845 else if (rb_enc_asciicompat(enc)) {
846 p = search_nonascii(p, e);
852 int ret = rb_enc_precise_mbclen(p, e, enc);
859 p = search_nonascii(p, e);
865 int ret = rb_enc_precise_mbclen(p, e, enc);
888 int inlined_encoding = RB_ENCODING_GET_INLINED(str2);
890 rb_enc_set_index(str1, rb_enc_get_index(str2));
898rb_enc_cr_str_copy_for_substr(
VALUE dest,
VALUE src)
903 str_enc_copy(dest, src);
904 if (RSTRING_LEN(dest) == 0) {
905 if (!rb_enc_asciicompat(STR_ENC_GET(src)))
916 if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
917 search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest)))
928rb_enc_cr_str_exact_copy(
VALUE dest,
VALUE src)
930 str_enc_copy(dest, src);
935enc_coderange_scan(
VALUE str, rb_encoding *enc)
937 return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc);
941rb_enc_str_coderange_scan(
VALUE str, rb_encoding *enc)
943 return enc_coderange_scan(str, enc);
952 cr = enc_coderange_scan(str, get_encoding(str));
959rb_enc_str_asciicompat(
VALUE str)
962 return str_encindex_fastpath(encindex) || rb_enc_asciicompat(rb_enc_get_from_index(encindex));
970 return rb_enc_str_asciicompat(str) && is_ascii_string(str);
979str_mod_check(
VALUE s,
const char *p,
long len)
981 if (RSTRING_PTR(s) != p || RSTRING_LEN(s) !=
len){
987str_capacity(
VALUE str,
const int termlen)
989 if (STR_EMBED_P(str)) {
990 return str_embed_capa(str) - termlen;
992 else if (
FL_ANY_RAW(str, STR_SHARED|STR_NOFREE)) {
996 return RSTRING(str)->as.heap.aux.capa;
1003 return str_capacity(str, TERM_LEN(str));
1007must_not_null(
const char *
ptr)
1010 rb_raise(rb_eArgError,
"NULL pointer given");
1015str_alloc_embed(
VALUE klass,
size_t capa)
1017 size_t size = rb_str_embed_size(
capa, 0);
1021 NEWOBJ_OF(str,
struct RString, klass,
1025 str->as.embed.ary[0] = 0;
1031str_alloc_heap(
VALUE klass)
1033 NEWOBJ_OF(str,
struct RString, klass,
1037 str->as.heap.aux.capa = 0;
1038 str->as.heap.ptr = NULL;
1044empty_str_alloc(
VALUE klass)
1046 RUBY_DTRACE_CREATE_HOOK(STRING, 0);
1047 VALUE str = str_alloc_embed(klass, 0);
1048 memset(
RSTRING(str)->as.embed.ary, 0, str_embed_capa(str));
1054str_enc_new(
VALUE klass,
const char *
ptr,
long len, rb_encoding *enc)
1059 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1063 enc = rb_ascii8bit_encoding();
1066 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1068 int termlen = rb_enc_mbminlen(enc);
1070 if (STR_EMBEDDABLE_P(
len, termlen)) {
1071 str = str_alloc_embed(klass,
len + termlen);
1077 str = str_alloc_heap(klass);
1083 rb_xmalloc_mul_add_mul(
sizeof(
char),
len,
sizeof(
char), termlen);
1086 rb_enc_raw_set(str, enc);
1089 memcpy(RSTRING_PTR(str),
ptr,
len);
1092 memset(RSTRING_PTR(str), 0,
len);
1095 STR_SET_LEN(str,
len);
1096 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
1103 return str_enc_new(klass,
ptr,
len, rb_ascii8bit_encoding());
1125rb_enc_str_new(
const char *
ptr,
long len, rb_encoding *enc)
1138 __msan_unpoison_string(
ptr);
1158 if (rb_enc_mbminlen(enc) != 1) {
1159 rb_raise(rb_eArgError,
"wchar encoding given");
1161 return rb_enc_str_new(
ptr, strlen(
ptr), enc);
1165str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex)
1170 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1174 str = str_enc_new(klass,
ptr,
len, rb_enc_from_index(encindex));
1177 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1178 str = str_alloc_heap(klass);
1182 RBASIC(str)->flags |= STR_NOFREE;
1183 rb_enc_associate_index(str, encindex);
1212static VALUE str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1213 rb_encoding *from, rb_encoding *to,
1214 int ecflags,
VALUE ecopts);
1217is_enc_ascii_string(
VALUE str, rb_encoding *enc)
1219 int encidx = rb_enc_to_index(enc);
1220 if (rb_enc_get_index(str) == encidx)
1221 return is_ascii_string(str);
1232 if (!to)
return str;
1233 if (!from) from = rb_enc_get(str);
1234 if (from == to)
return str;
1235 if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) ||
1236 rb_is_ascii8bit_enc(to)) {
1237 if (STR_ENC_GET(str) != to) {
1239 rb_enc_associate(str, to);
1246 from, to, ecflags, ecopts);
1247 if (
NIL_P(newstr)) {
1255rb_str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1256 rb_encoding *from,
int ecflags,
VALUE ecopts)
1260 olen = RSTRING_LEN(newstr);
1261 if (ofs < -olen || olen < ofs)
1263 if (ofs < 0) ofs += olen;
1265 STR_SET_LEN(newstr, ofs);
1269 rb_str_modify(newstr);
1270 return str_cat_conv_enc_opts(newstr, ofs,
ptr,
len, from,
1276rb_str_initialize(
VALUE str,
const char *
ptr,
long len, rb_encoding *enc)
1278 STR_SET_LEN(str, 0);
1279 rb_enc_associate(str, enc);
1285str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1286 rb_encoding *from, rb_encoding *to,
1287 int ecflags,
VALUE ecopts)
1292 VALUE econv_wrapper;
1293 const unsigned char *start, *sp;
1294 unsigned char *dest, *dp;
1295 size_t converted_output = (size_t)ofs;
1300 RBASIC_CLEAR_CLASS(econv_wrapper);
1302 if (!ec)
return Qnil;
1305 sp = (
unsigned char*)
ptr;
1307 while ((dest = (
unsigned char*)RSTRING_PTR(newstr)),
1308 (dp = dest + converted_output),
1312 size_t converted_input = sp - start;
1313 size_t rest =
len - converted_input;
1314 converted_output = dp - dest;
1316 if (converted_input && converted_output &&
1317 rest < (LONG_MAX / converted_output)) {
1318 rest = (rest * converted_output) / converted_input;
1323 olen += rest < 2 ? 2 : rest;
1324 rb_str_resize(newstr, olen);
1331 len = dp - (
unsigned char*)RSTRING_PTR(newstr);
1333 rb_enc_associate(newstr, to);
1352 const int eidx = rb_enc_to_index(eenc);
1355 return rb_enc_str_new(
ptr,
len, eenc);
1359 if ((eidx == rb_ascii8bit_encindex()) ||
1360 (eidx == rb_usascii_encindex() && search_nonascii(
ptr,
ptr +
len))) {
1364 ienc = rb_default_internal_encoding();
1365 if (!ienc || eenc == ienc) {
1366 return rb_enc_str_new(
ptr,
len, eenc);
1370 if ((eidx == rb_ascii8bit_encindex()) ||
1371 (eidx == rb_usascii_encindex()) ||
1372 (rb_enc_asciicompat(eenc) && !search_nonascii(
ptr,
ptr +
len))) {
1373 return rb_enc_str_new(
ptr,
len, ienc);
1376 str = rb_enc_str_new(NULL, 0, ienc);
1379 if (
NIL_P(rb_str_cat_conv_enc_opts(str, 0,
ptr,
len, eenc, 0,
Qnil))) {
1380 rb_str_initialize(str,
ptr,
len, eenc);
1386rb_external_str_with_enc(
VALUE str, rb_encoding *eenc)
1388 int eidx = rb_enc_to_index(eenc);
1389 if (eidx == rb_usascii_encindex() &&
1390 !is_ascii_string(str)) {
1391 rb_enc_associate_index(str, rb_ascii8bit_encindex());
1394 rb_enc_associate_index(str, eidx);
1453str_replace_shared_without_enc(
VALUE str2,
VALUE str)
1455 const int termlen = TERM_LEN(str);
1460 if (str_embed_capa(str2) >=
len + termlen) {
1461 char *ptr2 =
RSTRING(str2)->as.embed.ary;
1462 STR_SET_EMBED(str2);
1463 memcpy(ptr2, RSTRING_PTR(str),
len);
1464 TERM_FILL(ptr2+
len, termlen);
1468 if (STR_SHARED_P(str)) {
1469 root =
RSTRING(str)->as.heap.aux.shared;
1478 if (!STR_EMBED_P(str2) && !
FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) {
1480 rb_fatal(
"about to free a possible shared root");
1482 char *ptr2 = STR_HEAP_PTR(str2);
1484 ruby_sized_xfree(ptr2, STR_HEAP_SIZE(str2));
1487 FL_SET(str2, STR_NOEMBED);
1489 STR_SET_SHARED(str2, root);
1492 STR_SET_LEN(str2,
len);
1500 str_replace_shared_without_enc(str2, str);
1501 rb_enc_cr_str_exact_copy(str2, str);
1508 return str_replace_shared(str_alloc_heap(klass), str);
1525rb_str_new_frozen_String(
VALUE orig)
1533rb_str_frozen_bare_string(
VALUE orig)
1535 if (RB_LIKELY(BARE_STRING_P(orig) &&
OBJ_FROZEN_RAW(orig)))
return orig;
1540rb_str_tmp_frozen_acquire(
VALUE orig)
1543 return str_new_frozen_buffer(0, orig, FALSE);
1547rb_str_tmp_frozen_no_embed_acquire(
VALUE orig)
1549 if (
OBJ_FROZEN_RAW(orig) && !STR_EMBED_P(orig) && !rb_str_reembeddable_p(orig))
return orig;
1550 if (STR_SHARED_P(orig) && !STR_EMBED_P(
RSTRING(orig)->as.heap.aux.shared))
return rb_str_tmp_frozen_acquire(orig);
1552 VALUE str = str_alloc_heap(0);
1555 FL_SET(str, STR_SHARED_ROOT);
1557 size_t capa = str_capacity(orig, TERM_LEN(orig));
1563 if (STR_EMBED_P(orig) ||
FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
1564 RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(
sizeof(
char),
capa,
sizeof(
char), TERM_LEN(orig));
1565 memcpy(
RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig),
capa);
1571 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1572 RBASIC(orig)->flags &= ~STR_NOFREE;
1573 STR_SET_SHARED(orig, str);
1575 RB_OBJ_SET_SHAREABLE(str);
1587rb_str_tmp_frozen_release(
VALUE orig,
VALUE tmp)
1589 if (RBASIC_CLASS(tmp) != 0)
1592 if (STR_EMBED_P(tmp)) {
1595 else if (
FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_SHARED &&
1599 if (shared == tmp && !
FL_TEST_RAW(tmp, STR_BORROWED)) {
1601 RUBY_ASSERT(RSTRING_LEN(orig) == RSTRING_LEN(tmp));
1605 RSTRING(orig)->as.heap.aux.capa =
RSTRING(tmp)->as.heap.aux.capa;
1606 RBASIC(orig)->flags |=
RBASIC(tmp)->flags & STR_NOFREE;
1611 STR_SET_LEN(tmp, 0);
1619 return str_new_frozen_buffer(klass, orig, TRUE);
1629 VALUE str = str_alloc_heap(klass);
1630 STR_SET_LEN(str, RSTRING_LEN(orig));
1631 RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
1632 RSTRING(str)->as.heap.aux.capa =
RSTRING(orig)->as.heap.aux.capa;
1633 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1634 RBASIC(orig)->flags &= ~STR_NOFREE;
1635 STR_SET_SHARED(orig, str);
1642str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding)
1646 long len = RSTRING_LEN(orig);
1647 rb_encoding *enc = copy_encoding ? STR_ENC_GET(orig) : rb_ascii8bit_encoding();
1648 int termlen = copy_encoding ? TERM_LEN(orig) : 1;
1650 if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(
len, termlen)) {
1651 str = str_enc_new(klass, RSTRING_PTR(orig),
len, enc);
1657 long ofs =
RSTRING(orig)->as.heap.ptr - RSTRING_PTR(shared);
1658 long rest = RSTRING_LEN(shared) - ofs - RSTRING_LEN(orig);
1664 if ((ofs > 0) || (rest > 0) ||
1665 (klass !=
RBASIC(shared)->klass) ||
1667 str = str_new_shared(klass, shared);
1669 RSTRING(str)->as.heap.ptr += ofs;
1670 STR_SET_LEN(str, RSTRING_LEN(str) - (ofs + rest));
1673 if (RBASIC_CLASS(shared) == 0)
1678 else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
1679 str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig));
1681 memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
1682 STR_SET_LEN(str, RSTRING_LEN(orig));
1684 TERM_FILL(RSTRING_END(str), TERM_LEN(orig));
1688 str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
1691 str = heap_str_make_shared(klass, orig);
1696 if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
1708str_new_empty_String(
VALUE str)
1711 rb_enc_copy(v, str);
1715#define STR_BUF_MIN_SIZE 63
1720 if (STR_EMBEDDABLE_P(
capa, 1)) {
1728 RSTRING(str)->as.heap.ptr[0] =
'\0';
1748 return str_new(0, 0,
len);
1754 if (STR_EMBED_P(str)) {
1755 RB_DEBUG_COUNTER_INC(obj_str_embed);
1757 else if (
FL_TEST(str, STR_SHARED | STR_NOFREE)) {
1758 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_SHARED));
1759 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_NOFREE));
1762 RB_DEBUG_COUNTER_INC(obj_str_ptr);
1763 ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
1768rb_str_memsize(
VALUE str)
1770 if (
FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
1771 return STR_HEAP_SIZE(str);
1781 return rb_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
1784static inline void str_discard(
VALUE str);
1785static void str_shared_replace(
VALUE str,
VALUE str2);
1790 if (str != str2) str_shared_replace(str, str2);
1801 enc = STR_ENC_GET(str2);
1804 termlen = rb_enc_mbminlen(enc);
1806 STR_SET_LEN(str, RSTRING_LEN(str2));
1808 if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) {
1810 memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (
size_t)RSTRING_LEN(str2) + termlen);
1813 if (STR_EMBED_P(str2)) {
1815 long len = RSTRING_LEN(str2);
1818 char *new_ptr =
ALLOC_N(
char,
len + termlen);
1819 memcpy(new_ptr,
RSTRING(str2)->as.embed.ary,
len + termlen);
1820 RSTRING(str2)->as.heap.ptr = new_ptr;
1821 STR_SET_LEN(str2,
len);
1823 STR_SET_NOEMBED(str2);
1826 STR_SET_NOEMBED(str);
1828 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1830 if (
FL_TEST(str2, STR_SHARED)) {
1832 STR_SET_SHARED(str, shared);
1835 RSTRING(str)->as.heap.aux.capa =
RSTRING(str2)->as.heap.aux.capa;
1839 STR_SET_EMBED(str2);
1840 RSTRING_PTR(str2)[0] = 0;
1841 STR_SET_LEN(str2, 0);
1846 rb_enc_raw_set(str, enc);
1859 return rb_obj_as_string_result(str, obj);
1875 len = RSTRING_LEN(str2);
1876 if (STR_SHARED_P(str2)) {
1879 STR_SET_NOEMBED(str);
1880 STR_SET_LEN(str,
len);
1881 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1882 STR_SET_SHARED(str, shared);
1883 rb_enc_cr_str_exact_copy(str, str2);
1886 str_replace_shared(str, str2);
1895 size_t size = rb_str_embed_size(
capa, 0);
1899 NEWOBJ_OF(str,
struct RString, klass,
1910 NEWOBJ_OF(str,
struct RString, klass,
1913 str->as.heap.aux.capa = 0;
1914 str->as.heap.ptr = NULL;
1924 encidx = rb_enc_get_index(str);
1928 if (encidx) rb_enc_associate_index(dup, encidx);
1938 long len = RSTRING_LEN(str);
1943 STR_SET_LEN(dup, RSTRING_LEN(str));
1944 return str_duplicate_setup_encoding(str, dup, flags);
1953 root =
RSTRING(str)->as.heap.aux.shared;
1956 root = str = str_new_frozen(klass, str);
1962 RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
1963 FL_SET(root, STR_SHARED_ROOT);
1965 flags |= RSTRING_NOEMBED | STR_SHARED;
1967 STR_SET_LEN(dup, RSTRING_LEN(str));
1968 return str_duplicate_setup_encoding(str, dup, flags);
1974 if (STR_EMBED_P(str)) {
1975 return str_duplicate_setup_embed(klass, str, dup);
1978 return str_duplicate_setup_heap(klass, str, dup);
1986 if (STR_EMBED_P(str)) {
1987 dup = str_alloc_embed(klass, RSTRING_LEN(str) + TERM_LEN(str));
1990 dup = str_alloc_heap(klass);
1993 return str_duplicate_setup(klass, str, dup);
2004rb_str_dup_m(
VALUE str)
2006 if (LIKELY(BARE_STRING_P(str))) {
2017 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2024 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2028 new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
2029 str_duplicate_setup_embed(klass, str, new_str);
2032 new_str = ec_str_alloc_heap(ec, klass);
2033 str_duplicate_setup_heap(klass, str, new_str);
2042rb_str_with_debug_created_info(
VALUE str,
VALUE path,
int line)
2044 VALUE debug_info = rb_ary_new_from_args(2, path,
INT2FIX(line));
2068 static ID keyword_ids[2];
2069 VALUE orig, opt, venc, vcapa;
2071 rb_encoding *enc = 0;
2074 if (!keyword_ids[0]) {
2075 keyword_ids[0] = rb_id_encoding();
2076 CONST_ID(keyword_ids[1],
"capacity");
2084 if (!UNDEF_P(venc) && !
NIL_P(venc)) {
2085 enc = rb_to_encoding(venc);
2087 if (!UNDEF_P(vcapa) && !
NIL_P(vcapa)) {
2090 int termlen = enc ? rb_enc_mbminlen(enc) : 1;
2092 if (
capa < STR_BUF_MIN_SIZE) {
2093 capa = STR_BUF_MIN_SIZE;
2097 len = RSTRING_LEN(orig);
2101 if (orig == str) n = 0;
2103 str_modifiable(str);
2104 if (STR_EMBED_P(str) ||
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2106 const size_t size = (size_t)
capa + termlen;
2107 const char *
const old_ptr = RSTRING_PTR(str);
2108 const size_t osize = RSTRING_LEN(str) + TERM_LEN(str);
2109 char *new_ptr =
ALLOC_N(
char, size);
2110 if (STR_EMBED_P(str))
RUBY_ASSERT((
long)osize <= str_embed_capa(str));
2111 memcpy(new_ptr, old_ptr, osize < size ? osize : size);
2113 RSTRING(str)->as.heap.ptr = new_ptr;
2115 else if (STR_HEAP_SIZE(str) != (
size_t)
capa + termlen) {
2116 SIZED_REALLOC_N(
RSTRING(str)->as.heap.ptr,
char,
2117 (
size_t)
capa + termlen, STR_HEAP_SIZE(str));
2119 STR_SET_LEN(str,
len);
2120 TERM_FILL(&
RSTRING(str)->as.heap.ptr[
len], termlen);
2122 memcpy(
RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig),
len);
2123 rb_enc_cr_str_exact_copy(str, orig);
2125 FL_SET(str, STR_NOEMBED);
2132 rb_enc_associate(str, enc);
2144rb_str_s_new(
int argc,
VALUE *argv,
VALUE klass)
2150 static ID keyword_ids[2];
2153 rb_encoding *enc = NULL;
2160 keyword_ids[0] = rb_id_encoding();
2161 CONST_ID(keyword_ids[1],
"capacity");
2163 encoding = kwargs[0];
2164 capacity = kwargs[1];
2173 if (UNDEF_P(encoding)) {
2175 encoding = rb_obj_encoding(orig);
2179 if (!UNDEF_P(encoding)) {
2180 enc = rb_to_encoding(encoding);
2184 if (UNDEF_P(capacity)) {
2186 VALUE empty_str = str_new(klass,
"", 0);
2188 rb_enc_associate(empty_str, enc);
2192 VALUE copy = str_duplicate(klass, orig);
2193 rb_enc_associate(copy, enc);
2206 if (orig_capa >
capa) {
2211 VALUE str = str_enc_new(klass, NULL,
capa, enc);
2212 STR_SET_LEN(str, 0);
2213 TERM_FILL(RSTRING_PTR(str), enc ? rb_enc_mbmaxlen(enc) : 1);
2223#define is_utf8_lead_byte(c) (((c)&0xC0) != 0x80)
2238static inline uintptr_t
2239count_utf8_lead_bytes_with_word(
const uintptr_t *s)
2244 d = (d>>6) | (~d>>7);
2245 d &= NONASCII_MASK >> 7;
2248#if defined(HAVE_BUILTIN___BUILTIN_POPCOUNT) && defined(__POPCNT__)
2250 return rb_popcount_intptr(d);
2254# if SIZEOF_VOIDP == 8
2263enc_strlen(
const char *p,
const char *e, rb_encoding *enc,
int cr)
2268 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
2269 long diff = (long)(e - p);
2270 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2275 if ((
int)
sizeof(uintptr_t) * 2 < e - p) {
2276 const uintptr_t *s, *t;
2277 const uintptr_t lowbits =
sizeof(uintptr_t) - 1;
2278 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
2279 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
2280 while (p < (
const char *)s) {
2281 if (is_utf8_lead_byte(*p))
len++;
2285 len += count_utf8_lead_bytes_with_word(s);
2288 p = (
const char *)s;
2291 if (is_utf8_lead_byte(*p))
len++;
2297 else if (rb_enc_asciicompat(enc)) {
2302 q = search_nonascii(p, e);
2308 p += rb_enc_fast_mbclen(p, e, enc);
2315 q = search_nonascii(p, e);
2321 p += rb_enc_mbclen(p, e, enc);
2328 for (c=0; p<e; c++) {
2329 p += rb_enc_mbclen(p, e, enc);
2344rb_enc_strlen_cr(
const char *p,
const char *e, rb_encoding *enc,
int *cr)
2351 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
2352 long diff = (long)(e - p);
2353 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2355 else if (rb_enc_asciicompat(enc)) {
2359 q = search_nonascii(p, e);
2367 ret = rb_enc_precise_mbclen(p, e, enc);
2382 for (c=0; p<e; c++) {
2383 ret = rb_enc_precise_mbclen(p, e, enc);
2390 if (p + rb_enc_mbminlen(enc) <= e)
2391 p += rb_enc_mbminlen(enc);
2402str_strlen(
VALUE str, rb_encoding *enc)
2407 if (single_byte_optimizable(str))
return RSTRING_LEN(str);
2408 if (!enc) enc = STR_ENC_GET(str);
2409 p = RSTRING_PTR(str);
2410 e = RSTRING_END(str);
2414 long n = rb_enc_strlen_cr(p, e, enc, &cr);
2419 return enc_strlen(p, e, enc, cr);
2426 return str_strlen(str, NULL);
2440 return LONG2NUM(str_strlen(str, NULL));
2452rb_str_bytesize(
VALUE str)
2471rb_str_empty(
VALUE str)
2473 return RBOOL(RSTRING_LEN(str) == 0);
2492 char *ptr1, *ptr2, *ptr3;
2497 enc = rb_enc_check_str(str1, str2);
2500 termlen = rb_enc_mbminlen(enc);
2501 if (len1 > LONG_MAX - len2) {
2502 rb_raise(rb_eArgError,
"string size too big");
2504 str3 = str_enc_new(
rb_cString, 0, len1+len2, enc);
2505 ptr3 = RSTRING_PTR(str3);
2506 memcpy(ptr3, ptr1, len1);
2507 memcpy(ptr3+len1, ptr2, len2);
2508 TERM_FILL(&ptr3[len1+len2], termlen);
2524 MAYBE_UNUSED(
char) *ptr1, *ptr2;
2527 int enc1 = rb_enc_get_index(str1);
2528 int enc2 = rb_enc_get_index(str2);
2533 else if (enc2 < 0) {
2536 else if (enc1 != enc2) {
2539 else if (len1 > LONG_MAX - len2) {
2573 rb_enc_copy(str2, str);
2578 rb_raise(rb_eArgError,
"negative argument");
2580 if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
2581 if (STR_EMBEDDABLE_P(
len, 1)) {
2583 memset(RSTRING_PTR(str2), 0,
len + 1);
2590 STR_SET_LEN(str2,
len);
2591 rb_enc_copy(str2, str);
2594 if (
len && LONG_MAX/
len < RSTRING_LEN(str)) {
2595 rb_raise(rb_eArgError,
"argument too big");
2598 len *= RSTRING_LEN(str);
2599 termlen = TERM_LEN(str);
2601 ptr2 = RSTRING_PTR(str2);
2603 n = RSTRING_LEN(str);
2604 memcpy(ptr2, RSTRING_PTR(str), n);
2605 while (n <=
len/2) {
2606 memcpy(ptr2 + n, ptr2, n);
2609 memcpy(ptr2 + n, ptr2,
len-n);
2611 STR_SET_LEN(str2,
len);
2612 TERM_FILL(&ptr2[
len], termlen);
2613 rb_enc_cr_str_copy_for_substr(str2, str);
2652rb_check_lockedtmp(
VALUE str)
2654 if (
FL_TEST(str, STR_TMPLOCK)) {
2661#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
2663str_modifiable(
VALUE str)
2667 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
2668 if (CHILLED_STRING_P(str)) {
2669 CHILLED_STRING_MUTATED(str);
2671 rb_check_lockedtmp(str);
2672 rb_check_frozen(str);
2677str_dependent_p(
VALUE str)
2679 if (STR_EMBED_P(str) || !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2689#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
2691str_independent(
VALUE str)
2695 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
2696 str_modifiable(str);
2697 return !str_dependent_p(str);
2703str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen)
2713 if (!STR_EMBED_P(str) && str_embed_capa(str) >=
capa + termlen) {
2717 TERM_FILL(
RSTRING(str)->as.embed.ary +
len, termlen);
2718 STR_SET_LEN(str,
len);
2723 oldptr = RSTRING_PTR(str);
2725 memcpy(
ptr, oldptr,
len);
2727 if (
FL_TEST_RAW(str, STR_NOEMBED|STR_NOFREE|STR_SHARED) == STR_NOEMBED) {
2730 STR_SET_NOEMBED(str);
2731 FL_UNSET(str, STR_SHARED|STR_NOFREE);
2732 TERM_FILL(
ptr +
len, termlen);
2734 STR_SET_LEN(str,
len);
2741 if (!str_independent(str))
2742 str_make_independent(str);
2751 int termlen = TERM_LEN(str);
2752 long len = RSTRING_LEN(str);
2755 rb_raise(rb_eArgError,
"negative expanding string size");
2757 if (expand >= LONG_MAX -
len) {
2758 rb_raise(rb_eArgError,
"string size too big");
2761 if (!str_independent(str)) {
2762 str_make_independent_expand(str,
len, expand, termlen);
2764 else if (expand > 0) {
2765 RESIZE_CAPA_TERM(str,
len + expand, termlen);
2772str_modify_keep_cr(
VALUE str)
2774 if (!str_independent(str))
2775 str_make_independent(str);
2782str_discard(
VALUE str)
2784 str_modifiable(str);
2785 if (!STR_EMBED_P(str) && !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2786 ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
2787 RSTRING(str)->as.heap.ptr = 0;
2788 STR_SET_LEN(str, 0);
2795 int encindex = rb_enc_get_index(str);
2797 if (RB_UNLIKELY(encindex == -1)) {
2801 if (RB_LIKELY(str_encindex_fastpath(encindex))) {
2805 rb_encoding *enc = rb_enc_from_index(encindex);
2806 if (!rb_enc_asciicompat(enc)) {
2828 return RSTRING_PTR(str);
2832zero_filled(
const char *s,
int n)
2834 for (; n > 0; --n) {
2841str_null_char(
const char *s,
long len,
const int minlen, rb_encoding *enc)
2843 const char *e = s +
len;
2845 for (; s + minlen <= e; s += rb_enc_mbclen(s, e, enc)) {
2846 if (zero_filled(s, minlen))
return s;
2852str_fill_term(
VALUE str,
char *s,
long len,
int termlen)
2857 if (str_dependent_p(str)) {
2858 if (!zero_filled(s +
len, termlen))
2859 str_make_independent_expand(str,
len, 0L, termlen);
2862 TERM_FILL(s +
len, termlen);
2865 return RSTRING_PTR(str);
2869rb_str_change_terminator_length(
VALUE str,
const int oldtermlen,
const int termlen)
2871 long capa = str_capacity(str, oldtermlen) + oldtermlen;
2872 long len = RSTRING_LEN(str);
2876 rb_check_lockedtmp(str);
2877 str_make_independent_expand(str,
len, 0L, termlen);
2879 else if (str_dependent_p(str)) {
2880 if (termlen > oldtermlen)
2881 str_make_independent_expand(str,
len, 0L, termlen);
2884 if (!STR_EMBED_P(str)) {
2889 if (termlen > oldtermlen) {
2890 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
2898str_null_check(
VALUE str,
int *w)
2900 char *s = RSTRING_PTR(str);
2901 long len = RSTRING_LEN(str);
2902 rb_encoding *enc = rb_enc_get(str);
2903 const int minlen = rb_enc_mbminlen(enc);
2907 if (str_null_char(s,
len, minlen, enc)) {
2910 return str_fill_term(str, s,
len, minlen);
2913 if (!s || memchr(s, 0,
len)) {
2917 s = str_fill_term(str, s,
len, minlen);
2923rb_str_to_cstr(
VALUE str)
2926 return str_null_check(str, &w);
2934 char *s = str_null_check(str, &w);
2937 rb_raise(rb_eArgError,
"string contains null char");
2939 rb_raise(rb_eArgError,
"string contains null byte");
2945rb_str_fill_terminator(
VALUE str,
const int newminlen)
2947 char *s = RSTRING_PTR(str);
2948 long len = RSTRING_LEN(str);
2949 return str_fill_term(str, s,
len, newminlen);
2955 str = rb_check_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
2981str_nth_len(
const char *p,
const char *e,
long *nthp, rb_encoding *enc)
2984 if (rb_enc_mbmaxlen(enc) == 1) {
2987 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
2988 p += nth * rb_enc_mbmaxlen(enc);
2990 else if (rb_enc_asciicompat(enc)) {
2991 const char *p2, *e2;
2994 while (p < e && 0 < nth) {
3001 p2 = search_nonascii(p, e2);
3010 n = rb_enc_mbclen(p, e, enc);
3021 while (p < e && nth--) {
3022 p += rb_enc_mbclen(p, e, enc);
3031rb_enc_nth(
const char *p,
const char *e,
long nth, rb_encoding *enc)
3033 return str_nth_len(p, e, &nth, enc);
3037str_nth(
const char *p,
const char *e,
long nth, rb_encoding *enc,
int singlebyte)
3042 p = str_nth_len(p, e, &nth, enc);
3051str_offset(
const char *p,
const char *e,
long nth, rb_encoding *enc,
int singlebyte)
3053 const char *pp = str_nth(p, e, nth, enc, singlebyte);
3054 if (!pp)
return e - p;
3061 return str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
3062 STR_ENC_GET(str), single_byte_optimizable(str));
3067str_utf8_nth(
const char *p,
const char *e,
long *nthp)
3070 if ((
int)SIZEOF_VOIDP * 2 < e - p && (
int)SIZEOF_VOIDP * 2 < nth) {
3071 const uintptr_t *s, *t;
3072 const uintptr_t lowbits = SIZEOF_VOIDP - 1;
3073 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
3074 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
3075 while (p < (
const char *)s) {
3076 if (is_utf8_lead_byte(*p)) nth--;
3080 nth -= count_utf8_lead_bytes_with_word(s);
3082 }
while (s < t && (
int)SIZEOF_VOIDP <= nth);
3086 if (is_utf8_lead_byte(*p)) {
3087 if (nth == 0)
break;
3097str_utf8_offset(
const char *p,
const char *e,
long nth)
3099 const char *pp = str_utf8_nth(p, e, &nth);
3108 if (single_byte_optimizable(str) || pos < 0)
3111 char *p = RSTRING_PTR(str);
3112 return enc_strlen(p, p + pos, STR_ENC_GET(str),
ENC_CODERANGE(str));
3117str_subseq(
VALUE str,
long beg,
long len)
3125 const int termlen = TERM_LEN(str);
3126 if (!SHARABLE_SUBSTRING_P(beg,
len, RSTRING_LEN(str))) {
3133 if (str_embed_capa(str2) >=
len + termlen) {
3134 char *ptr2 =
RSTRING(str2)->as.embed.ary;
3135 STR_SET_EMBED(str2);
3136 memcpy(ptr2, RSTRING_PTR(str) + beg,
len);
3137 TERM_FILL(ptr2+
len, termlen);
3139 STR_SET_LEN(str2,
len);
3143 str_replace_shared(str2, str);
3146 RSTRING(str2)->as.heap.ptr += beg;
3147 if (RSTRING_LEN(str2) >
len) {
3148 STR_SET_LEN(str2,
len);
3158 VALUE str2 = str_subseq(str, beg,
len);
3159 rb_enc_cr_str_copy_for_substr(str2, str);
3168 const long blen = RSTRING_LEN(str);
3169 rb_encoding *enc = STR_ENC_GET(str);
3170 char *p, *s = RSTRING_PTR(str), *e = s + blen;
3172 if (
len < 0)
return 0;
3173 if (beg < 0 && -beg < 0)
return 0;
3177 if (single_byte_optimizable(str)) {
3178 if (beg > blen)
return 0;
3181 if (beg < 0)
return 0;
3183 if (
len > blen - beg)
3185 if (
len < 0)
return 0;
3190 if (
len > -beg)
len = -beg;
3192 (-beg * rb_enc_mbmaxlen(enc) < blen / 8)) {
3194 while (beg-- >
len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
3197 while (
len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
3203 slen = str_strlen(str, enc);
3205 if (beg < 0)
return 0;
3207 if (
len == 0)
goto end;
3210 else if (beg > 0 && beg > blen) {
3214 if (beg > str_strlen(str, enc))
return 0;
3219 enc == rb_utf8_encoding()) {
3220 p = str_utf8_nth(s, e, &beg);
3221 if (beg > 0)
return 0;
3222 len = str_utf8_offset(p, e,
len);
3225 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
3226 int char_sz = rb_enc_mbmaxlen(enc);
3228 p = s + beg * char_sz;
3232 else if (
len * char_sz > e - p)
3237 else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
3238 if (beg > 0)
return 0;
3242 len = str_offset(p, e,
len, enc, 0);
3250static VALUE str_substr(
VALUE str,
long beg,
long len,
int empty);
3255 return str_substr(str, beg,
len, TRUE);
3265str_substr(
VALUE str,
long beg,
long len,
int empty)
3269 if (!p)
return Qnil;
3270 if (!
len && !empty)
return Qnil;
3272 beg = p - RSTRING_PTR(str);
3274 VALUE str2 = str_subseq(str, beg,
len);
3275 rb_enc_cr_str_copy_for_substr(str2, str);
3283 if (CHILLED_STRING_P(str)) {
3288 rb_str_resize(str, RSTRING_LEN(str));
3306 if (
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
3349str_uminus(
VALUE str)
3354 return rb_fstring(str);
3358#define rb_str_dup_frozen rb_str_new_frozen
3363 rb_check_frozen(str);
3364 if (
FL_TEST(str, STR_TMPLOCK)) {
3367 FL_SET(str, STR_TMPLOCK);
3374 rb_check_frozen(str);
3375 if (!
FL_TEST(str, STR_TMPLOCK)) {
3395 const int termlen = TERM_LEN(str);
3397 str_modifiable(str);
3398 if (STR_SHARED_P(str)) {
3401 if (
len > (
capa = (
long)str_capacity(str, termlen)) ||
len < 0) {
3402 rb_bug(
"probable buffer overflow: %ld for %ld",
len,
capa);
3413 else if (
len > RSTRING_LEN(str)) {
3416 const char *
const prev_end = RSTRING_END(str);
3417 const char *
const new_end = RSTRING_PTR(str) +
len;
3418 rb_encoding *enc = rb_enc_get(str);
3427 else if (
len < RSTRING_LEN(str)) {
3435 STR_SET_LEN(str,
len);
3436 TERM_FILL(&RSTRING_PTR(str)[
len], termlen);
3443 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3446 int independent = str_independent(str);
3447 long slen = RSTRING_LEN(str);
3448 const int termlen = TERM_LEN(str);
3450 if (slen >
len || (termlen != 1 && slen <
len)) {
3456 if (STR_EMBED_P(str)) {
3457 if (
len == slen)
return str;
3458 if (str_embed_capa(str) >=
len + termlen) {
3459 STR_SET_LEN(str,
len);
3460 TERM_FILL(
RSTRING(str)->as.embed.ary +
len, termlen);
3463 str_make_independent_expand(str, slen,
len - slen, termlen);
3465 else if (str_embed_capa(str) >=
len + termlen) {
3466 char *
ptr = STR_HEAP_PTR(str);
3468 if (slen >
len) slen =
len;
3470 TERM_FILL(
RSTRING(str)->as.embed.ary +
len, termlen);
3471 STR_SET_LEN(str,
len);
3472 if (independent) ruby_xfree(
ptr);
3475 else if (!independent) {
3476 if (
len == slen)
return str;
3477 str_make_independent_expand(str, slen,
len - slen, termlen);
3481 SIZED_REALLOC_N(
RSTRING(str)->as.heap.ptr,
char,
3482 (
size_t)
len + termlen, STR_HEAP_SIZE(str));
3485 else if (
len == slen)
return str;
3486 STR_SET_LEN(str,
len);
3487 TERM_FILL(
RSTRING(str)->as.heap.ptr +
len, termlen);
3493str_ensure_available_capa(
VALUE str,
long len)
3495 str_modify_keep_cr(str);
3497 const int termlen = TERM_LEN(str);
3498 long olen = RSTRING_LEN(str);
3500 if (RB_UNLIKELY(olen > LONG_MAX -
len)) {
3501 rb_raise(rb_eArgError,
"string sizes too big");
3504 long total = olen +
len;
3505 long capa = str_capacity(str, termlen);
3508 if (total >= LONG_MAX / 2) {
3511 while (total >
capa) {
3514 RESIZE_CAPA_TERM(str,
capa, termlen);
3519str_buf_cat4(
VALUE str,
const char *
ptr,
long len,
bool keep_cr)
3522 str_modify_keep_cr(str);
3527 if (
len == 0)
return 0;
3529 long total, olen,
off = -1;
3531 const int termlen = TERM_LEN(str);
3534 if (
ptr >= sptr &&
ptr <= sptr + olen) {
3538 long capa = str_capacity(str, termlen);
3540 if (olen > LONG_MAX -
len) {
3541 rb_raise(rb_eArgError,
"string sizes too big");
3545 if (total >= LONG_MAX / 2) {
3548 while (total >
capa) {
3551 RESIZE_CAPA_TERM(str,
capa, termlen);
3552 sptr = RSTRING_PTR(str);
3557 memcpy(sptr + olen,
ptr,
len);
3558 STR_SET_LEN(str, total);
3559 TERM_FILL(sptr + total, termlen);
3564#define str_buf_cat(str, ptr, len) str_buf_cat4((str), (ptr), len, false)
3565#define str_buf_cat2(str, ptr) str_buf_cat4((str), (ptr), rb_strlen_lit(ptr), false)
3570 if (
len == 0)
return str;
3572 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3574 return str_buf_cat(str,
ptr,
len);
3585rb_str_buf_cat_byte(
VALUE str,
unsigned char byte)
3587 RUBY_ASSERT(RB_ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT || RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII);
3590 if (UNLIKELY(!str_independent(str))) {
3591 str_make_independent(str);
3594 long string_length = -1;
3595 const int null_terminator_length = 1;
3600 if (UNLIKELY(string_length > LONG_MAX - 1)) {
3601 rb_raise(rb_eArgError,
"string sizes too big");
3604 long string_capacity = str_capacity(str, null_terminator_length);
3610 if (LIKELY(string_capacity >= string_length + 1)) {
3612 sptr[string_length] = byte;
3613 STR_SET_LEN(str, string_length + 1);
3614 TERM_FILL(sptr + string_length + 1, null_terminator_length);
3618 str_buf_cat(str, (
char *)&
byte, 1);
3626 if (ISASCII(
byte)) {
3633 if (UNLIKELY(RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)) {
3634 rb_enc_associate_index(str, ENCINDEX_ASCII_8BIT);
3645rb_enc_cr_str_buf_cat(
VALUE str,
const char *
ptr,
long len,
3646 int ptr_encindex,
int ptr_cr,
int *ptr_cr_ret)
3651 rb_encoding *str_enc, *ptr_enc;
3655 if (str_encindex == ptr_encindex) {
3657 ptr_cr = coderange_scan(
ptr,
len, rb_enc_from_index(ptr_encindex));
3661 str_enc = rb_enc_from_index(str_encindex);
3662 ptr_enc = rb_enc_from_index(ptr_encindex);
3663 if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
3666 if (RSTRING_LEN(str) == 0) {
3669 rb_str_change_terminator_length(str, rb_enc_mbminlen(str_enc), rb_enc_mbminlen(ptr_enc));
3675 ptr_cr = coderange_scan(
ptr,
len, ptr_enc);
3684 *ptr_cr_ret = ptr_cr;
3686 if (str_encindex != ptr_encindex &&
3689 str_enc = rb_enc_from_index(str_encindex);
3690 ptr_enc = rb_enc_from_index(ptr_encindex);
3695 res_encindex = str_encindex;
3700 res_encindex = str_encindex;
3704 res_encindex = ptr_encindex;
3709 res_encindex = str_encindex;
3716 res_encindex = str_encindex;
3722 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3724 str_buf_cat(str,
ptr,
len);
3730 rb_enc_inspect_name(str_enc), rb_enc_inspect_name(ptr_enc));
3737 return rb_enc_cr_str_buf_cat(str,
ptr,
len,
3746 rb_encoding *enc = rb_enc_from_index(encindex);
3747 if (rb_enc_asciicompat(enc)) {
3748 return rb_enc_cr_str_buf_cat(str,
ptr, strlen(
ptr),
3752 char *buf =
ALLOCA_N(
char, rb_enc_mbmaxlen(enc));
3754 unsigned int c = (
unsigned char)*
ptr;
3755 int len = rb_enc_codelen(c, enc);
3756 rb_enc_mbcput(c, buf, enc);
3757 rb_enc_cr_str_buf_cat(str, buf,
len,
3770 if (str_enc_fastpath(str)) {
3774 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3780 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3791 rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
3807rb_str_concat_literals(
size_t num,
const VALUE *strary)
3811 unsigned long len = 1;
3816 for (i = 0; i < num; ++i) {
len += RSTRING_LEN(strary[i]); }
3818 str_enc_copy_direct(str, strary[0]);
3820 for (i = s; i < num; ++i) {
3821 const VALUE v = strary[i];
3825 if (encidx != ENCINDEX_US_ASCII) {
3827 rb_enc_set_index(str, encidx);
3840rb_str_concat_multi(
int argc,
VALUE *argv,
VALUE str)
3842 str_modifiable(str);
3847 else if (argc > 1) {
3850 rb_enc_copy(arg_str, str);
3851 for (i = 0; i < argc; i++) {
3886rb_str_append_as_bytes(
int argc,
VALUE *argv,
VALUE str)
3888 long needed_capacity = 0;
3892 for (
int index = 0; index < argc; index++) {
3893 VALUE obj = argv[index];
3901 needed_capacity += RSTRING_LEN(obj);
3906 "wrong argument type %"PRIsVALUE
" (expected String or Integer)",
3913 str_ensure_available_capa(str, needed_capacity);
3914 char *sptr = RSTRING_END(str);
3916 for (
int index = 0; index < argc; index++) {
3917 VALUE obj = argv[index];
3922 argv[index] = obj = rb_int_and(obj,
INT2FIX(0xff));
3923 char byte = (char)(
NUM2INT(obj) & 0xFF);
3937 rb_bug(
"append_as_bytes arguments should have been validated");
3941 STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
3942 TERM_FILL(sptr, TERM_LEN(str));
3947 for (
int index = 0; index < argc; index++) {
3948 VALUE obj = argv[index];
3965 rb_bug(
"append_as_bytes arguments should have been validated");
4040 rb_encoding *enc = STR_ENC_GET(str1);
4044 if (rb_num_to_uint(str2, &code) == 0) {
4057 encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
4060 rb_str_buf_cat_byte(str1, (
unsigned char)code);
4063 long pos = RSTRING_LEN(str1);
4068 switch (
len = rb_enc_codelen(code, enc)) {
4069 case ONIGERR_INVALID_CODE_POINT_VALUE:
4070 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4072 case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
4078 rb_enc_mbcput(code, buf, enc);
4079 if (rb_enc_precise_mbclen(buf, buf +
len + 1, enc) !=
len) {
4080 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4082 rb_str_resize(str1, pos+
len);
4083 memcpy(RSTRING_PTR(str1) + pos, buf,
len);
4096rb_ascii8bit_appendable_encoding_index(rb_encoding *enc,
unsigned int code)
4098 int encidx = rb_enc_to_index(enc);
4100 if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII) {
4105 if (encidx == ENCINDEX_US_ASCII && code > 127) {
4106 return ENCINDEX_ASCII_8BIT;
4128rb_str_prepend_multi(
int argc,
VALUE *argv,
VALUE str)
4130 str_modifiable(str);
4135 else if (argc > 1) {
4138 rb_enc_copy(arg_str, str);
4139 for (i = 0; i < argc; i++) {
4152 st_index_t precomputed_hash;
4153 memcpy(&precomputed_hash, RSTRING_END(str) + TERM_LEN(str),
sizeof(precomputed_hash));
4155 RUBY_ASSERT(precomputed_hash == str_do_hash(str));
4156 return precomputed_hash;
4159 return str_do_hash(str);
4166 const char *ptr1, *ptr2;
4169 return (len1 != len2 ||
4171 memcmp(ptr1, ptr2, len1) != 0);
4183rb_str_hash_m(
VALUE str)
4189#define lesser(a,b) (((a)>(b))?(b):(a))
4197 if (RSTRING_LEN(str1) == 0)
return TRUE;
4198 if (RSTRING_LEN(str2) == 0)
return TRUE;
4201 if (idx1 == idx2)
return TRUE;
4206 if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
4210 if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
4220 const char *ptr1, *ptr2;
4223 if (str1 == str2)
return 0;
4226 if (ptr1 == ptr2 || (retval = memcmp(ptr1, ptr2, lesser(len1, len2))) == 0) {
4235 if (len1 > len2)
return 1;
4238 if (retval > 0)
return 1;
4272 if (str1 == str2)
return Qtrue;
4279 return rb_str_eql_internal(str1, str2);
4293 if (str1 == str2)
return Qtrue;
4295 return rb_str_eql_internal(str1, str2);
4333 return rb_invcmp(str1, str2);
4375 return str_casecmp(str1, s);
4383 const char *p1, *p1end, *p2, *p2end;
4385 enc = rb_enc_compatible(str1, str2);
4390 p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
4391 p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
4392 if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
4393 while (p1 < p1end && p2 < p2end) {
4395 unsigned int c1 =
TOLOWER(*p1 & 0xff);
4396 unsigned int c2 =
TOLOWER(*p2 & 0xff);
4398 return INT2FIX(c1 < c2 ? -1 : 1);
4405 while (p1 < p1end && p2 < p2end) {
4406 int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
4407 int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
4409 if (0 <= c1 && 0 <= c2) {
4413 return INT2FIX(c1 < c2 ? -1 : 1);
4417 l1 = rb_enc_mbclen(p1, p1end, enc);
4418 l2 = rb_enc_mbclen(p2, p2end, enc);
4419 len = l1 < l2 ? l1 : l2;
4420 r = memcmp(p1, p2,
len);
4422 return INT2FIX(r < 0 ? -1 : 1);
4424 return INT2FIX(l1 < l2 ? -1 : 1);
4430 if (p1 == p1end && p2 == p2end)
return INT2FIX(0);
4431 if (p1 == p1end)
return INT2FIX(-1);
4464 return str_casecmp_p(str1, s);
4471 VALUE folded_str1, folded_str2;
4472 VALUE fold_opt = sym_fold;
4474 enc = rb_enc_compatible(str1, str2);
4479 folded_str1 = rb_str_downcase(1, &fold_opt, str1);
4480 folded_str2 = rb_str_downcase(1, &fold_opt, str2);
4482 return rb_str_eql(folded_str1, folded_str2);
4486strseq_core(
const char *str_ptr,
const char *str_ptr_end,
long str_len,
4487 const char *sub_ptr,
long sub_len,
long offset, rb_encoding *enc)
4489 const char *search_start = str_ptr;
4490 long pos, search_len = str_len - offset;
4494 pos =
rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
4495 if (pos < 0)
return pos;
4496 t = rb_enc_right_char_head(search_start, search_start+pos, str_ptr_end, enc);
4497 if (t == search_start + pos)
break;
4498 search_len -= t - search_start;
4499 if (search_len <= 0)
return -1;
4500 offset += t - search_start;
4503 return pos + offset;
4507#define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0)
4508#define rb_str_byteindex(str, sub, offset) rb_strseq_index(str, sub, offset, 1)
4511rb_strseq_index(
VALUE str,
VALUE sub,
long offset,
int in_byte)
4513 const char *str_ptr, *str_ptr_end, *sub_ptr;
4514 long str_len, sub_len;
4517 enc = rb_enc_check(str, sub);
4518 if (is_broken_string(sub))
return -1;
4520 str_ptr = RSTRING_PTR(str);
4521 str_ptr_end = RSTRING_END(str);
4522 str_len = RSTRING_LEN(str);
4523 sub_ptr = RSTRING_PTR(sub);
4524 sub_len = RSTRING_LEN(sub);
4526 if (str_len < sub_len)
return -1;
4529 long str_len_char, sub_len_char;
4530 int single_byte = single_byte_optimizable(str);
4531 str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc);
4532 sub_len_char = in_byte ? sub_len : str_strlen(sub, enc);
4534 offset += str_len_char;
4535 if (offset < 0)
return -1;
4537 if (str_len_char - offset < sub_len_char)
return -1;
4538 if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
4541 if (sub_len == 0)
return offset;
4544 return strseq_core(str_ptr, str_ptr_end, str_len, sub_ptr, sub_len, offset, enc);
4557rb_str_index_m(
int argc,
VALUE *argv,
VALUE str)
4561 rb_encoding *enc = STR_ENC_GET(str);
4564 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4565 long slen = str_strlen(str, enc);
4567 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4579 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
4580 enc, single_byte_optimizable(str));
4591 pos = rb_str_index(str, sub, pos);
4605str_ensure_byte_pos(
VALUE str,
long pos)
4607 if (!single_byte_optimizable(str)) {
4608 const char *s = RSTRING_PTR(str);
4609 const char *e = RSTRING_END(str);
4610 const char *p = s + pos;
4611 if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
4613 "offset %ld does not land on character boundary", pos);
4686rb_str_byteindex_m(
int argc,
VALUE *argv,
VALUE str)
4692 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4693 long slen = RSTRING_LEN(str);
4695 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4706 str_ensure_byte_pos(str, pos);
4718 pos = rb_str_byteindex(str, sub, pos);
4719 if (pos >= 0)
return LONG2NUM(pos);
4726memrchr(
const char *search_str,
int chr,
long search_len)
4728 const char *
ptr = search_str + search_len;
4729 while (
ptr > search_str) {
4730 if ((
unsigned char)*(--
ptr) == chr)
return (
void *)
ptr;
4738str_rindex(
VALUE str,
VALUE sub,
const char *s, rb_encoding *enc)
4740 char *hit, *adjusted;
4742 long slen, searchlen;
4745 sbeg = RSTRING_PTR(str);
4746 slen = RSTRING_LEN(sub);
4747 if (slen == 0)
return s - sbeg;
4748 e = RSTRING_END(str);
4749 t = RSTRING_PTR(sub);
4751 searchlen = s - sbeg + 1;
4753 if (memcmp(s, t, slen) == 0) {
4758 hit = memrchr(sbeg, c, searchlen);
4760 adjusted = rb_enc_left_char_head(sbeg, hit, e, enc);
4761 if (hit != adjusted) {
4762 searchlen = adjusted - sbeg;
4765 if (memcmp(hit, t, slen) == 0)
4767 searchlen = adjusted - sbeg;
4768 }
while (searchlen > 0);
4782 enc = rb_enc_check(str, sub);
4783 if (is_broken_string(sub))
return -1;
4784 singlebyte = single_byte_optimizable(str);
4785 len = singlebyte ? RSTRING_LEN(str) : str_strlen(str, enc);
4786 slen = str_strlen(sub, enc);
4789 if (
len < slen)
return -1;
4790 if (
len - pos < slen) pos =
len - slen;
4791 if (
len == 0)
return pos;
4793 sbeg = RSTRING_PTR(str);
4796 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4802 s = str_nth(sbeg, RSTRING_END(str), pos, enc, singlebyte);
4803 return str_rindex(str, sub, s, enc);
4815rb_str_rindex_m(
int argc,
VALUE *argv,
VALUE str)
4819 rb_encoding *enc = STR_ENC_GET(str);
4820 long pos,
len = str_strlen(str, enc);
4822 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4824 if (pos < 0 && (pos +=
len) < 0) {
4830 if (pos >
len) pos =
len;
4838 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
4839 enc, single_byte_optimizable(str));
4850 pos = rb_str_rindex(str, sub, pos);
4860rb_str_byterindex(
VALUE str,
VALUE sub,
long pos)
4866 enc = rb_enc_check(str, sub);
4867 if (is_broken_string(sub))
return -1;
4868 len = RSTRING_LEN(str);
4869 slen = RSTRING_LEN(sub);
4872 if (
len < slen)
return -1;
4873 if (
len - pos < slen) pos =
len - slen;
4874 if (
len == 0)
return pos;
4876 sbeg = RSTRING_PTR(str);
4879 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4886 return str_rindex(str, sub, s, enc);
4976rb_str_byterindex_m(
int argc,
VALUE *argv,
VALUE str)
4980 long pos,
len = RSTRING_LEN(str);
4982 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4984 if (pos < 0 && (pos +=
len) < 0) {
4990 if (pos >
len) pos =
len;
4996 str_ensure_byte_pos(str, pos);
5008 pos = rb_str_byterindex(str, sub, pos);
5009 if (pos >= 0)
return LONG2NUM(pos);
5048 switch (OBJ_BUILTIN_TYPE(y)) {
5102rb_str_match_m(
int argc,
VALUE *argv,
VALUE str)
5106 rb_check_arity(argc, 1, 2);
5109 result = rb_funcallv(get_pat(re), rb_intern(
"match"), argc, argv);
5140rb_str_match_m_p(
int argc,
VALUE *argv,
VALUE str)
5143 rb_check_arity(argc, 1, 2);
5144 re = get_pat(argv[0]);
5145 return rb_reg_match_p(re, str, argc > 1 ?
NUM2LONG(argv[1]) : 0);
5154static enum neighbor_char
5155enc_succ_char(
char *p,
long len, rb_encoding *enc)
5160 if (rb_enc_mbminlen(enc) > 1) {
5162 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5164 return NEIGHBOR_NOT_CHAR;
5166 c = rb_enc_mbc_to_codepoint(p, p +
len, enc) + 1;
5167 l = rb_enc_code_to_mbclen(c, enc);
5168 if (!l)
return NEIGHBOR_NOT_CHAR;
5169 if (l !=
len)
return NEIGHBOR_WRAPPED;
5170 rb_enc_mbcput(c, p, enc);
5171 r = rb_enc_precise_mbclen(p, p +
len, enc);
5173 return NEIGHBOR_NOT_CHAR;
5175 return NEIGHBOR_FOUND;
5178 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0xff; i--)
5181 return NEIGHBOR_WRAPPED;
5182 ++((
unsigned char*)p)[i];
5183 l = rb_enc_precise_mbclen(p, p+
len, enc);
5187 return NEIGHBOR_FOUND;
5190 memset(p+l, 0xff,
len-l);
5196 for (len2 =
len-1; 0 < len2; len2--) {
5197 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5201 memset(p+len2+1, 0xff,
len-(len2+1));
5206static enum neighbor_char
5207enc_pred_char(
char *p,
long len, rb_encoding *enc)
5211 if (rb_enc_mbminlen(enc) > 1) {
5213 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5215 return NEIGHBOR_NOT_CHAR;
5217 c = rb_enc_mbc_to_codepoint(p, p +
len, enc);
5218 if (!c)
return NEIGHBOR_NOT_CHAR;
5220 l = rb_enc_code_to_mbclen(c, enc);
5221 if (!l)
return NEIGHBOR_NOT_CHAR;
5222 if (l !=
len)
return NEIGHBOR_WRAPPED;
5223 rb_enc_mbcput(c, p, enc);
5224 r = rb_enc_precise_mbclen(p, p +
len, enc);
5226 return NEIGHBOR_NOT_CHAR;
5228 return NEIGHBOR_FOUND;
5231 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0; i--)
5234 return NEIGHBOR_WRAPPED;
5235 --((
unsigned char*)p)[i];
5236 l = rb_enc_precise_mbclen(p, p+
len, enc);
5240 return NEIGHBOR_FOUND;
5243 memset(p+l, 0,
len-l);
5249 for (len2 =
len-1; 0 < len2; len2--) {
5250 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5254 memset(p+len2+1, 0,
len-(len2+1));
5268static enum neighbor_char
5269enc_succ_alnum_char(
char *p,
long len, rb_encoding *enc,
char *carry)
5271 enum neighbor_char ret;
5275 char save[ONIGENC_CODE_TO_MBC_MAXLEN];
5279 const int max_gaps = 1;
5281 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5282 if (rb_enc_isctype(c, ONIGENC_CTYPE_DIGIT, enc))
5283 ctype = ONIGENC_CTYPE_DIGIT;
5284 else if (rb_enc_isctype(c, ONIGENC_CTYPE_ALPHA, enc))
5285 ctype = ONIGENC_CTYPE_ALPHA;
5287 return NEIGHBOR_NOT_CHAR;
5290 for (
try = 0;
try <= max_gaps; ++
try) {
5291 ret = enc_succ_char(p,
len, enc);
5292 if (ret == NEIGHBOR_FOUND) {
5293 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5294 if (rb_enc_isctype(c, ctype, enc))
5295 return NEIGHBOR_FOUND;
5302 ret = enc_pred_char(p,
len, enc);
5303 if (ret == NEIGHBOR_FOUND) {
5304 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5305 if (!rb_enc_isctype(c, ctype, enc)) {
5317 return NEIGHBOR_NOT_CHAR;
5320 if (ctype != ONIGENC_CTYPE_DIGIT) {
5322 return NEIGHBOR_WRAPPED;
5326 enc_succ_char(carry,
len, enc);
5327 return NEIGHBOR_WRAPPED;
5345 str =
rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
5346 rb_enc_cr_str_copy_for_substr(str, orig);
5347 return str_succ(str);
5354 char *sbeg, *s, *e, *last_alnum = 0;
5355 int found_alnum = 0;
5357 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] =
"\1";
5358 long carry_pos = 0, carry_len = 1;
5359 enum neighbor_char neighbor = NEIGHBOR_FOUND;
5361 slen = RSTRING_LEN(str);
5362 if (slen == 0)
return str;
5364 enc = STR_ENC_GET(str);
5365 sbeg = RSTRING_PTR(str);
5366 s = e = sbeg + slen;
5368 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5369 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
5375 l = rb_enc_precise_mbclen(s, e, enc);
5376 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5377 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5378 neighbor = enc_succ_alnum_char(s, l, enc, carry);
5380 case NEIGHBOR_NOT_CHAR:
5382 case NEIGHBOR_FOUND:
5384 case NEIGHBOR_WRAPPED:
5389 carry_pos = s - sbeg;
5394 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5395 enum neighbor_char neighbor;
5396 char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
5397 l = rb_enc_precise_mbclen(s, e, enc);
5398 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5399 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5401 neighbor = enc_succ_char(tmp, l, enc);
5403 case NEIGHBOR_FOUND:
5407 case NEIGHBOR_WRAPPED:
5410 case NEIGHBOR_NOT_CHAR:
5413 if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
5415 enc_succ_char(s, l, enc);
5417 if (!rb_enc_asciicompat(enc)) {
5418 MEMCPY(carry, s,
char, l);
5421 carry_pos = s - sbeg;
5425 RESIZE_CAPA(str, slen + carry_len);
5426 sbeg = RSTRING_PTR(str);
5427 s = sbeg + carry_pos;
5428 memmove(s + carry_len, s, slen - carry_pos);
5429 memmove(s, carry, carry_len);
5431 STR_SET_LEN(str, slen);
5432 TERM_FILL(&sbeg[slen], rb_enc_mbminlen(enc));
5448rb_str_succ_bang(
VALUE str)
5456all_digits_p(
const char *s,
long len)
5484 VALUE end, exclusive;
5488 return rb_str_upto_each(beg, end,
RTEST(exclusive), str_upto_i,
Qnil);
5494 VALUE current, after_end;
5501 enc = rb_enc_check(beg, end);
5502 ascii = (is_ascii_string(beg) && is_ascii_string(end));
5504 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
5505 char c = RSTRING_PTR(beg)[0];
5506 char e = RSTRING_PTR(end)[0];
5508 if (c > e || (excl && c == e))
return beg;
5510 VALUE str = rb_enc_str_new(&c, 1, enc);
5512 if ((*each)(str, arg))
break;
5513 if (!excl && c == e)
break;
5515 if (excl && c == e)
break;
5520 if (ascii &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
ISDIGIT(RSTRING_PTR(end)[0]) &&
5521 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
5522 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
5526 width = RSTRING_LENINT(beg);
5527 b = rb_str_to_inum(beg, 10, FALSE);
5528 e = rb_str_to_inum(end, 10, FALSE);
5532 rb_encoding *usascii = rb_usascii_encoding();
5535 if (excl && bi == ei)
break;
5536 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5541 ID op = excl ?
'<' : idLE;
5542 VALUE args[2], fmt = rb_fstring_lit(
"%.*d");
5547 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5548 b = rb_funcallv(b, succ, 0, 0);
5555 if (n > 0 || (excl && n == 0))
return beg;
5557 after_end = rb_funcallv(end, succ, 0, 0);
5562 next = rb_funcallv(current, succ, 0, 0);
5563 if ((*each)(current, arg))
break;
5564 if (
NIL_P(next))
break;
5568 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
5583 if (is_ascii_string(beg) &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
5584 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
5585 VALUE b, args[2], fmt = rb_fstring_lit(
"%.*d");
5586 int width = RSTRING_LENINT(beg);
5587 b = rb_str_to_inum(beg, 10, FALSE);
5590 rb_encoding *usascii = rb_usascii_encoding();
5593 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5601 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5602 b = rb_funcallv(b, succ, 0, 0);
5608 VALUE next = rb_funcallv(current, succ, 0, 0);
5609 if ((*each)(current, arg))
break;
5612 if (RSTRING_LEN(current) == 0)
5623 if (!
rb_equal(str, *argp))
return 0;
5637 if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
5638 rb_enc_asciicompat(STR_ENC_GET(end)) &&
5639 rb_enc_asciicompat(STR_ENC_GET(val))) {
5640 const char *bp = RSTRING_PTR(beg);
5641 const char *ep = RSTRING_PTR(end);
5642 const char *vp = RSTRING_PTR(val);
5643 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
5644 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
5651 if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
5652 if (b <= v && v < e)
return Qtrue;
5653 return RBOOL(!
RTEST(exclusive) && b <= v && v == e);
5660 all_digits_p(bp, RSTRING_LEN(beg)) &&
5661 all_digits_p(ep, RSTRING_LEN(end))) {
5666 rb_str_upto_each(beg, end,
RTEST(exclusive), include_range_i, (
VALUE)&val);
5668 return RBOOL(
NIL_P(val));
5690 else if (RB_TYPE_P(indx,
T_REGEXP)) {
5691 return rb_str_subpat(str, indx,
INT2FIX(0));
5693 else if (RB_TYPE_P(indx,
T_STRING)) {
5694 if (rb_str_index(str, indx, 0) != -1)
5700 long beg,
len = str_strlen(str, NULL);
5712 return str_substr(str, idx, 1, FALSE);
5729rb_str_aref_m(
int argc,
VALUE *argv,
VALUE str)
5732 if (RB_TYPE_P(argv[0],
T_REGEXP)) {
5733 return rb_str_subpat(str, argv[0], argv[1]);
5736 return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
5739 rb_check_arity(argc, 1, 2);
5740 return rb_str_aref(str, argv[0]);
5746 char *
ptr = RSTRING_PTR(str);
5747 long olen = RSTRING_LEN(str), nlen;
5749 str_modifiable(str);
5750 if (
len > olen)
len = olen;
5752 if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
5754 int fl = (int)(
RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
5757 memmove(
ptr, oldptr +
len, nlen);
5758 if (fl == STR_NOEMBED)
xfree(oldptr);
5761 if (!STR_SHARED_P(str)) {
5763 rb_enc_cr_str_exact_copy(shared, str);
5768 STR_SET_LEN(str, nlen);
5770 if (!SHARABLE_MIDDLE_SUBSTRING) {
5771 TERM_FILL(
ptr + nlen, TERM_LEN(str));
5778rb_str_update_1(
VALUE str,
long beg,
long len,
VALUE val,
long vbeg,
long vlen)
5784 if (beg == 0 && vlen == 0) {
5789 str_modify_keep_cr(str);
5793 RESIZE_CAPA(str, slen + vlen -
len);
5794 sptr = RSTRING_PTR(str);
5803 memmove(sptr + beg + vlen,
5805 slen - (beg +
len));
5807 if (vlen < beg &&
len < 0) {
5811 memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
5814 STR_SET_LEN(str, slen);
5815 TERM_FILL(&sptr[slen], TERM_LEN(str));
5822 rb_str_update_1(str, beg,
len, val, 0, RSTRING_LEN(val));
5831 int singlebyte = single_byte_optimizable(str);
5837 enc = rb_enc_check(str, val);
5838 slen = str_strlen(str, enc);
5840 if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
5849 if (
len > slen - beg) {
5852 p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte);
5853 if (!p) p = RSTRING_END(str);
5854 e = str_nth(p, RSTRING_END(str),
len, enc, singlebyte);
5855 if (!e) e = RSTRING_END(str);
5857 beg = p - RSTRING_PTR(str);
5859 rb_str_update_0(str, beg,
len, val);
5860 rb_enc_associate(str, enc);
5871 long start, end,
len;
5880 regs = RMATCH_REGS(match);
5881 if ((nth >= regs->num_regs) || ((nth < 0) && (-nth >= regs->num_regs))) {
5885 nth += regs->num_regs;
5895 enc = rb_enc_check_str(str, val);
5896 rb_str_update_0(str, start,
len, val);
5897 rb_enc_associate(str, enc);
5905 switch (
TYPE(indx)) {
5907 rb_str_subpat_set(str, indx,
INT2FIX(0), val);
5911 beg = rb_str_index(str, indx, 0);
5950rb_str_aset_m(
int argc,
VALUE *argv,
VALUE str)
5953 if (RB_TYPE_P(argv[0],
T_REGEXP)) {
5954 rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
5961 rb_check_arity(argc, 2, 3);
5962 return rb_str_aset(str, argv[0], argv[1]);
6014rb_str_slice_bang(
int argc,
VALUE *argv,
VALUE str)
6021 rb_check_arity(argc, 1, 2);
6022 str_modify_keep_cr(str);
6030 if ((nth += regs->num_regs) <= 0)
return Qnil;
6032 else if (nth >= regs->num_regs)
return Qnil;
6034 len = END(nth) - beg;
6037 else if (argc == 2) {
6046 beg = p - RSTRING_PTR(str);
6049 else if (RB_TYPE_P(indx,
T_STRING)) {
6050 beg = rb_str_index(str, indx, 0);
6051 if (beg == -1)
return Qnil;
6052 len = RSTRING_LEN(indx);
6064 beg = p - RSTRING_PTR(str);
6073 beg = p - RSTRING_PTR(str);
6077 rb_enc_cr_str_copy_for_substr(result, str);
6085 char *sptr = RSTRING_PTR(str);
6086 long slen = RSTRING_LEN(str);
6087 if (beg +
len > slen)
6091 slen - (beg +
len));
6093 STR_SET_LEN(str, slen);
6094 TERM_FILL(&sptr[slen], TERM_LEN(str));
6105 switch (OBJ_BUILTIN_TYPE(pat)) {
6124get_pat_quoted(
VALUE pat,
int check)
6128 switch (OBJ_BUILTIN_TYPE(pat)) {
6142 if (check && is_broken_string(pat)) {
6149rb_pat_search0(
VALUE pat,
VALUE str,
long pos,
int set_backref_str,
VALUE *match)
6152 pos = rb_str_byteindex(str, pat, pos);
6153 if (set_backref_str) {
6155 str = rb_str_new_frozen_String(str);
6156 VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
6158 *match = match_data;
6168 return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
6173rb_pat_search(
VALUE pat,
VALUE str,
long pos,
int set_backref_str)
6175 return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
6193rb_str_sub_bang(
int argc,
VALUE *argv,
VALUE str)
6201 rb_check_arity(argc, min_arity, 2);
6207 hash = rb_check_hash_type(argv[1]);
6213 pat = get_pat_quoted(argv[0], 1);
6215 str_modifiable(str);
6216 beg = rb_pat_search(pat, str, 0, 1);
6227 regs = RMATCH_REGS(match);
6230 end0 = beg0 + RSTRING_LEN(pat);
6239 if (iter || !
NIL_P(hash)) {
6240 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6246 repl = rb_hash_aref(hash,
rb_str_subseq(str, beg0, end0 - beg0));
6249 str_mod_check(str, p,
len);
6250 rb_check_frozen(str);
6256 enc = rb_enc_compatible(str, repl);
6258 rb_encoding *str_enc = STR_ENC_GET(str);
6259 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6263 rb_enc_inspect_name(str_enc),
6264 rb_enc_inspect_name(STR_ENC_GET(repl)));
6266 enc = STR_ENC_GET(repl);
6269 rb_enc_associate(str, enc);
6279 rlen = RSTRING_LEN(repl);
6280 len = RSTRING_LEN(str);
6282 RESIZE_CAPA(str,
len + rlen - plen);
6284 p = RSTRING_PTR(str);
6286 memmove(p + beg0 + rlen, p + beg0 + plen,
len - beg0 - plen);
6288 rp = RSTRING_PTR(repl);
6289 memmove(p + beg0, rp, rlen);
6291 STR_SET_LEN(str,
len);
6292 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
6315 rb_str_sub_bang(argc, argv, str);
6320str_gsub(
int argc,
VALUE *argv,
VALUE str,
int bang)
6323 long beg, beg0, end0;
6324 long offset, blen, slen,
len, last;
6325 enum {STR, ITER, FAST_MAP, MAP} mode = STR;
6327 int need_backref_str = -1;
6328 rb_encoding *str_enc;
6337 hash = rb_check_hash_type(argv[1]);
6341 else if (rb_hash_default_unredefined(hash) && !
FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
6349 rb_error_arity(argc, 1, 2);
6352 pat = get_pat_quoted(argv[0], 1);
6353 beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
6356 if (bang)
return Qnil;
6361 blen = RSTRING_LEN(str) + 30;
6363 sp = RSTRING_PTR(str);
6364 slen = RSTRING_LEN(str);
6366 str_enc = STR_ENC_GET(str);
6367 rb_enc_associate(dest, str_enc);
6374 end0 = beg0 + RSTRING_LEN(pat);
6388 struct RString fake_str = {RBASIC_INIT};
6390 if (mode == FAST_MAP) {
6399 val = rb_hash_aref(hash, key);
6402 str_mod_check(str, sp, slen);
6407 else if (need_backref_str) {
6409 if (need_backref_str < 0) {
6410 need_backref_str = val != repl;
6417 len = beg0 - offset;
6431 if (RSTRING_LEN(str) <= end0)
break;
6432 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0, RSTRING_END(str), str_enc);
6434 offset = end0 +
len;
6436 cp = RSTRING_PTR(str) + offset;
6437 if (offset > RSTRING_LEN(str))
break;
6440 if (mode != FAST_MAP && mode != STR) {
6443 beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
6448 if (RSTRING_LEN(str) > offset) {
6451 rb_pat_search0(pat, str, last, 1, &match);
6453 str_shared_replace(str, dest);
6478rb_str_gsub_bang(
int argc,
VALUE *argv,
VALUE str)
6480 str_modify_keep_cr(str);
6481 return str_gsub(argc, argv, str, 1);
6531 return str_gsub(argc, argv, str, 0);
6551 str_modifiable(str);
6552 if (str == str2)
return str;
6556 return str_replace(str, str2);
6573rb_str_clear(
VALUE str)
6577 STR_SET_LEN(str, 0);
6578 RSTRING_PTR(str)[0] = 0;
6579 if (rb_enc_asciicompat(STR_ENC_GET(str)))
6595rb_str_chr(
VALUE str)
6613 pos += RSTRING_LEN(str);
6614 if (pos < 0 || RSTRING_LEN(str) <= pos)
6617 return INT2FIX((
unsigned char)RSTRING_PTR(str)[pos]);
6637 long len = RSTRING_LEN(str);
6638 char *
ptr, *head, *left = 0;
6642 if (pos < -
len ||
len <= pos)
6649 char byte = (char)(
NUM2INT(w) & 0xFF);
6651 if (!str_independent(str))
6652 str_make_independent(str);
6653 enc = STR_ENC_GET(str);
6654 head = RSTRING_PTR(str);
6656 if (!STR_EMBED_P(str)) {
6662 if (ISASCII(
byte))
goto end;
6663 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6670 left = rb_enc_left_char_head(head,
ptr, head+
len, enc);
6671 width = rb_enc_precise_mbclen(left, head+
len, enc);
6673 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6689str_byte_substr(
VALUE str,
long beg,
long len,
int empty)
6691 long n = RSTRING_LEN(str);
6693 if (beg > n ||
len < 0)
return Qnil;
6696 if (beg < 0)
return Qnil;
6701 if (!empty)
return Qnil;
6705 VALUE str2 = str_subseq(str, beg,
len);
6707 str_enc_copy_direct(str2, str);
6709 if (RSTRING_LEN(str2) == 0) {
6710 if (!rb_enc_asciicompat(STR_ENC_GET(str)))
6744 long beg,
len = RSTRING_LEN(str);
6752 return str_byte_substr(str, beg,
len, TRUE);
6757 return str_byte_substr(str, idx, 1, FALSE);
6769rb_str_byteslice(
int argc,
VALUE *argv,
VALUE str)
6774 return str_byte_substr(str, beg,
len, TRUE);
6776 rb_check_arity(argc, 1, 2);
6777 return str_byte_aref(str, argv[0]);
6781str_check_beg_len(
VALUE str,
long *beg,
long *
len)
6783 long end, slen = RSTRING_LEN(str);
6786 if ((slen < *beg) || ((*beg < 0) && (*beg + slen < 0))) {
6795 if (*
len > slen - *beg) {
6799 str_ensure_byte_pos(str, *beg);
6800 str_ensure_byte_pos(str, end);
6814rb_str_bytesplice(
int argc,
VALUE *argv,
VALUE str)
6816 long beg,
len, vbeg, vlen;
6820 rb_check_arity(argc, 2, 5);
6821 if (!(argc == 2 || argc == 3 || argc == 5)) {
6822 rb_raise(rb_eArgError,
"wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
6826 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
6827 rb_builtin_class_name(argv[0]));
6834 vlen = RSTRING_LEN(val);
6839 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
6840 rb_builtin_class_name(argv[2]));
6852 vlen = RSTRING_LEN(val);
6860 str_check_beg_len(str, &beg, &
len);
6861 str_check_beg_len(val, &vbeg, &vlen);
6862 str_modify_keep_cr(str);
6865 rb_enc_associate(str, rb_enc_check(str, val));
6868 rb_str_update_1(str, beg,
len, val, vbeg, vlen);
6890rb_str_reverse(
VALUE str)
6897 if (RSTRING_LEN(str) <= 1)
return str_duplicate(
rb_cString, str);
6898 enc = STR_ENC_GET(str);
6900 s = RSTRING_PTR(str); e = RSTRING_END(str);
6901 p = RSTRING_END(rev);
6904 if (RSTRING_LEN(str) > 1) {
6905 if (single_byte_optimizable(str)) {
6912 int clen = rb_enc_fast_mbclen(s, e, enc);
6920 cr = rb_enc_asciicompat(enc) ?
6923 int clen = rb_enc_mbclen(s, e, enc);
6932 STR_SET_LEN(rev, RSTRING_LEN(str));
6933 str_enc_copy_direct(rev, str);
6955rb_str_reverse_bang(
VALUE str)
6957 if (RSTRING_LEN(str) > 1) {
6958 if (single_byte_optimizable(str)) {
6961 str_modify_keep_cr(str);
6962 s = RSTRING_PTR(str);
6963 e = RSTRING_END(str) - 1;
6971 str_shared_replace(str, rb_str_reverse(str));
6975 str_modify_keep_cr(str);
7004 i = rb_str_index(str, arg, 0);
7006 return RBOOL(i != -1);
7049 if (rb_check_arity(argc, 0, 1) && (base =
NUM2INT(argv[0])) < 0) {
7050 rb_raise(rb_eArgError,
"invalid radix %d", base);
7052 return rb_str_to_inum(str, base, FALSE);
7077rb_str_to_f(
VALUE str)
7094rb_str_to_s(
VALUE str)
7104str_cat_char(
VALUE str,
unsigned int c, rb_encoding *enc)
7106 char s[RUBY_MAX_CHAR_LEN];
7107 int n = rb_enc_codelen(c, enc);
7109 rb_enc_mbcput(c, s, enc);
7114#define CHAR_ESC_LEN 13
7117rb_str_buf_cat_escaped_char(
VALUE result,
unsigned int c,
int unicode_p)
7119 char buf[CHAR_ESC_LEN + 1];
7127 snprintf(buf, CHAR_ESC_LEN,
"%c", c);
7129 else if (c < 0x10000) {
7130 snprintf(buf, CHAR_ESC_LEN,
"\\u%04X", c);
7133 snprintf(buf, CHAR_ESC_LEN,
"\\u{%X}", c);
7138 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", c);
7141 snprintf(buf, CHAR_ESC_LEN,
"\\x{%X}", c);
7144 l = (int)strlen(buf);
7150ruby_escaped_char(
int c)
7153 case '\0':
return "\\0";
7154 case '\n':
return "\\n";
7155 case '\r':
return "\\r";
7156 case '\t':
return "\\t";
7157 case '\f':
return "\\f";
7158 case '\013':
return "\\v";
7159 case '\010':
return "\\b";
7160 case '\007':
return "\\a";
7161 case '\033':
return "\\e";
7162 case '\x7f':
return "\\c?";
7168rb_str_escape(
VALUE str)
7171 rb_encoding *enc = rb_enc_from_index(encidx);
7172 const char *p = RSTRING_PTR(str);
7173 const char *pend = RSTRING_END(str);
7174 const char *prev = p;
7175 char buf[CHAR_ESC_LEN + 1];
7177 int unicode_p = rb_enc_unicode_p(enc);
7178 int asciicompat = rb_enc_asciicompat(enc);
7183 int n = rb_enc_precise_mbclen(p, pend, enc);
7185 if (p > prev) str_buf_cat(result, prev, p - prev);
7186 n = rb_enc_mbminlen(enc);
7188 n = (int)(pend - p);
7190 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7191 str_buf_cat(result, buf, strlen(buf));
7197 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7199 cc = ruby_escaped_char(c);
7201 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7202 str_buf_cat(result, cc, strlen(cc));
7205 else if (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c)) {
7208 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7209 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7213 if (p > prev) str_buf_cat(result, prev, p - prev);
7231 rb_encoding *enc = rb_enc_from_index(encidx);
7232 const char *p, *pend, *prev;
7233 char buf[CHAR_ESC_LEN + 1];
7235 rb_encoding *resenc = rb_default_internal_encoding();
7236 int unicode_p = rb_enc_unicode_p(enc);
7237 int asciicompat = rb_enc_asciicompat(enc);
7239 if (resenc == NULL) resenc = rb_default_external_encoding();
7240 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
7241 rb_enc_associate(result, resenc);
7242 str_buf_cat2(result,
"\"");
7244 p = RSTRING_PTR(str); pend = RSTRING_END(str);
7250 n = rb_enc_precise_mbclen(p, pend, enc);
7252 if (p > prev) str_buf_cat(result, prev, p - prev);
7253 n = rb_enc_mbminlen(enc);
7255 n = (int)(pend - p);
7257 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7258 str_buf_cat(result, buf, strlen(buf));
7264 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7266 if ((asciicompat || unicode_p) &&
7267 (c ==
'"'|| c ==
'\\' ||
7271 (cc = rb_enc_codepoint(p,pend,enc),
7272 (cc ==
'$' || cc ==
'@' || cc ==
'{'))))) {
7273 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7274 str_buf_cat2(result,
"\\");
7275 if (asciicompat || enc == resenc) {
7281 case '\n': cc =
'n';
break;
7282 case '\r': cc =
'r';
break;
7283 case '\t': cc =
't';
break;
7284 case '\f': cc =
'f';
break;
7285 case '\013': cc =
'v';
break;
7286 case '\010': cc =
'b';
break;
7287 case '\007': cc =
'a';
break;
7288 case 033: cc =
'e';
break;
7289 default: cc = 0;
break;
7292 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7295 str_buf_cat(result, buf, 2);
7307 if ((enc == resenc && rb_enc_isprint(c, enc) && c != 0x85) ||
7308 (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c))) {
7312 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7313 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7318 if (p > prev) str_buf_cat(result, prev, p - prev);
7319 str_buf_cat2(result,
"\"");
7324#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
7337 int encidx = rb_enc_get_index(str);
7338 rb_encoding *enc = rb_enc_from_index(encidx);
7340 const char *p, *pend;
7343 int u8 = (encidx == rb_utf8_encindex());
7344 static const char nonascii_suffix[] =
".dup.force_encoding(\"%s\")";
7347 if (!rb_enc_asciicompat(enc)) {
7349 len += strlen(enc->name);
7352 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7355 unsigned char c = *p++;
7358 case '"':
case '\\':
7359 case '\n':
case '\r':
7360 case '\t':
case '\f':
7361 case '\013':
case '\010':
case '\007':
case '\033':
7366 clen = IS_EVSTR(p, pend) ? 2 : 1;
7374 if (u8 && c > 0x7F) {
7375 int n = rb_enc_precise_mbclen(p-1, pend, enc);
7377 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
7380 else if (cc <= 0xFFFFF)
7393 if (clen > LONG_MAX -
len) {
7400 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7401 q = RSTRING_PTR(result); qend = q +
len + 1;
7405 unsigned char c = *p++;
7407 if (c ==
'"' || c ==
'\\') {
7411 else if (c ==
'#') {
7412 if (IS_EVSTR(p, pend)) *q++ =
'\\';
7415 else if (c ==
'\n') {
7419 else if (c ==
'\r') {
7423 else if (c ==
'\t') {
7427 else if (c ==
'\f') {
7431 else if (c ==
'\013') {
7435 else if (c ==
'\010') {
7439 else if (c ==
'\007') {
7443 else if (c ==
'\033') {
7453 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
7455 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
7458 snprintf(q, qend-q,
"u%04X", cc);
7460 snprintf(q, qend-q,
"u{%X}", cc);
7465 snprintf(q, qend-q,
"x%02X", c);
7471 if (!rb_enc_asciicompat(enc)) {
7472 snprintf(q, qend-q, nonascii_suffix, enc->name);
7473 encidx = rb_ascii8bit_encindex();
7476 rb_enc_associate_index(result, encidx);
7482unescape_ascii(
unsigned int c)
7506undump_after_backslash(
VALUE undumped,
const char **ss,
const char *s_end, rb_encoding **penc,
bool *utf8,
bool *binary)
7508 const char *s = *ss;
7512 unsigned char buf[6];
7513 static rb_encoding *enc_utf8 = NULL;
7530 *buf = unescape_ascii(*s);
7542 if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
7543 if (*penc != enc_utf8) {
7545 rb_enc_associate(undumped, enc_utf8);
7562 if (hexlen == 0 || hexlen > 6) {
7568 if (0xd800 <= c && c <= 0xdfff) {
7571 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
7581 if (0xd800 <= c && c <= 0xdfff) {
7584 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
7597 if (!ISASCII(*buf)) {
7614static VALUE rb_str_is_ascii_only_p(
VALUE str);
7626str_undump(
VALUE str)
7628 const char *s = RSTRING_PTR(str);
7629 const char *s_end = RSTRING_END(str);
7630 rb_encoding *enc = rb_enc_get(str);
7631 VALUE undumped = rb_enc_str_new(s, 0L, enc);
7633 bool binary =
false;
7637 if (rb_str_is_ascii_only_p(str) ==
Qfalse) {
7640 if (!str_null_check(str, &w)) {
7643 if (RSTRING_LEN(str) < 2)
goto invalid_format;
7644 if (*s !=
'"')
goto invalid_format;
7662 static const char force_encoding_suffix[] =
".force_encoding(\"";
7663 static const char dup_suffix[] =
".dup";
7664 const char *encname;
7669 size =
sizeof(dup_suffix) - 1;
7670 if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
7672 size =
sizeof(force_encoding_suffix) - 1;
7673 if (s_end - s <= size)
goto invalid_format;
7674 if (memcmp(s, force_encoding_suffix, size) != 0)
goto invalid_format;
7678 rb_raise(
rb_eRuntimeError,
"dumped string contained Unicode escape but used force_encoding");
7682 s = memchr(s,
'"', s_end-s);
7684 if (!s)
goto invalid_format;
7685 if (s_end - s != 2)
goto invalid_format;
7686 if (s[0] !=
'"' || s[1] !=
')')
goto invalid_format;
7688 encidx = rb_enc_find_index2(encname, (
long)size);
7692 rb_enc_associate_index(undumped, encidx);
7702 undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
7713 rb_raise(
rb_eRuntimeError,
"invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
7717rb_str_check_dummy_enc(rb_encoding *enc)
7719 if (rb_enc_dummy_p(enc)) {
7726str_true_enc(
VALUE str)
7728 rb_encoding *enc = STR_ENC_GET(str);
7729 rb_str_check_dummy_enc(enc);
7733static OnigCaseFoldType
7734check_case_options(
int argc,
VALUE *argv, OnigCaseFoldType flags)
7739 rb_raise(rb_eArgError,
"too many options");
7740 if (argv[0]==sym_turkic) {
7741 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
7743 if (argv[1]==sym_lithuanian)
7744 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
7746 rb_raise(rb_eArgError,
"invalid second option");
7749 else if (argv[0]==sym_lithuanian) {
7750 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
7752 if (argv[1]==sym_turkic)
7753 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
7755 rb_raise(rb_eArgError,
"invalid second option");
7759 rb_raise(rb_eArgError,
"too many options");
7760 else if (argv[0]==sym_ascii)
7761 flags |= ONIGENC_CASE_ASCII_ONLY;
7762 else if (argv[0]==sym_fold) {
7763 if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
7764 flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
7766 rb_raise(rb_eArgError,
"option :fold only allowed for downcasing");
7769 rb_raise(rb_eArgError,
"invalid option");
7774case_option_single_p(OnigCaseFoldType flags, rb_encoding *enc,
VALUE str)
7776 if ((flags & ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc) == 1))
7782#define CASE_MAPPING_ADDITIONAL_LENGTH 20
7783#ifndef CASEMAP_DEBUG
7784# define CASEMAP_DEBUG 0
7792 OnigUChar space[FLEX_ARY_LEN];
7796mapping_buffer_free(
void *p)
7800 while (current_buffer) {
7801 previous_buffer = current_buffer;
7802 current_buffer = current_buffer->next;
7803 ruby_sized_xfree(previous_buffer, previous_buffer->capa);
7809 {0, mapping_buffer_free,},
7810 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
7814rb_str_casemap(
VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
7818 const OnigUChar *source_current, *source_end;
7819 int target_length = 0;
7820 VALUE buffer_anchor;
7823 size_t buffer_count = 0;
7824 int buffer_length_or_invalid;
7826 if (RSTRING_LEN(source) == 0)
return str_duplicate(
rb_cString, source);
7828 source_current = (OnigUChar*)RSTRING_PTR(source);
7829 source_end = (OnigUChar*)RSTRING_END(source);
7833 while (source_current < source_end) {
7835 size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
7836 if (CASEMAP_DEBUG) {
7837 fprintf(stderr,
"Buffer allocation, capa is %"PRIuSIZE
"\n",
capa);
7840 *pre_buffer = current_buffer;
7841 pre_buffer = ¤t_buffer->next;
7842 current_buffer->next = NULL;
7843 current_buffer->capa =
capa;
7844 buffer_length_or_invalid = enc->case_map(flags,
7845 &source_current, source_end,
7846 current_buffer->space,
7847 current_buffer->space+current_buffer->capa,
7849 if (buffer_length_or_invalid < 0) {
7850 current_buffer =
DATA_PTR(buffer_anchor);
7852 mapping_buffer_free(current_buffer);
7853 rb_raise(rb_eArgError,
"input string invalid");
7855 target_length += current_buffer->used = buffer_length_or_invalid;
7857 if (CASEMAP_DEBUG) {
7858 fprintf(stderr,
"Buffer count is %"PRIuSIZE
"\n", buffer_count);
7861 if (buffer_count==1) {
7862 target =
rb_str_new((
const char*)current_buffer->space, target_length);
7865 char *target_current;
7868 target_current = RSTRING_PTR(target);
7869 current_buffer =
DATA_PTR(buffer_anchor);
7870 while (current_buffer) {
7871 memcpy(target_current, current_buffer->space, current_buffer->used);
7872 target_current += current_buffer->used;
7873 current_buffer = current_buffer->next;
7876 current_buffer =
DATA_PTR(buffer_anchor);
7878 mapping_buffer_free(current_buffer);
7883 str_enc_copy_direct(target, source);
7890rb_str_ascii_casemap(
VALUE source,
VALUE target, OnigCaseFoldType *flags, rb_encoding *enc)
7892 const OnigUChar *source_current, *source_end;
7893 OnigUChar *target_current, *target_end;
7894 long old_length = RSTRING_LEN(source);
7895 int length_or_invalid;
7897 if (old_length == 0)
return Qnil;
7899 source_current = (OnigUChar*)RSTRING_PTR(source);
7900 source_end = (OnigUChar*)RSTRING_END(source);
7901 if (source == target) {
7902 target_current = (OnigUChar*)source_current;
7903 target_end = (OnigUChar*)source_end;
7906 target_current = (OnigUChar*)RSTRING_PTR(target);
7907 target_end = (OnigUChar*)RSTRING_END(target);
7910 length_or_invalid = onigenc_ascii_only_case_map(flags,
7911 &source_current, source_end,
7912 target_current, target_end, enc);
7913 if (length_or_invalid < 0)
7914 rb_raise(rb_eArgError,
"input string invalid");
7915 if (CASEMAP_DEBUG && length_or_invalid != old_length) {
7916 fprintf(stderr,
"problem with rb_str_ascii_casemap"
7917 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
7918 rb_raise(rb_eArgError,
"internal problem with rb_str_ascii_casemap"
7919 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
7922 str_enc_copy(target, source);
7928upcase_single(
VALUE str)
7930 char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
7931 bool modified =
false;
7934 unsigned int c = *(
unsigned char*)s;
7936 if (
'a' <= c && c <=
'z') {
7937 *s =
'A' + (c -
'a');
7958rb_str_upcase_bang(
int argc,
VALUE *argv,
VALUE str)
7961 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
7963 flags = check_case_options(argc, argv, flags);
7964 str_modify_keep_cr(str);
7965 enc = str_true_enc(str);
7966 if (case_option_single_p(flags, enc, str)) {
7967 if (upcase_single(str))
7968 flags |= ONIGENC_CASE_MODIFIED;
7970 else if (flags&ONIGENC_CASE_ASCII_ONLY)
7971 rb_str_ascii_casemap(str, str, &flags, enc);
7973 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
7975 if (ONIGENC_CASE_MODIFIED&flags)
return str;
7988rb_str_upcase(
int argc,
VALUE *argv,
VALUE str)
7991 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
7994 flags = check_case_options(argc, argv, flags);
7995 enc = str_true_enc(str);
7996 if (case_option_single_p(flags, enc, str)) {
7997 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
7998 str_enc_copy_direct(ret, str);
8001 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8003 rb_str_ascii_casemap(str, ret, &flags, enc);
8006 ret = rb_str_casemap(str, &flags, enc);
8013downcase_single(
VALUE str)
8015 char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
8016 bool modified =
false;
8019 unsigned int c = *(
unsigned char*)s;
8021 if (
'A' <= c && c <=
'Z') {
8022 *s =
'a' + (c -
'A');
8044rb_str_downcase_bang(
int argc,
VALUE *argv,
VALUE str)
8047 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8049 flags = check_case_options(argc, argv, flags);
8050 str_modify_keep_cr(str);
8051 enc = str_true_enc(str);
8052 if (case_option_single_p(flags, enc, str)) {
8053 if (downcase_single(str))
8054 flags |= ONIGENC_CASE_MODIFIED;
8056 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8057 rb_str_ascii_casemap(str, str, &flags, enc);
8059 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8061 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8075rb_str_downcase(
int argc,
VALUE *argv,
VALUE str)
8078 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8081 flags = check_case_options(argc, argv, flags);
8082 enc = str_true_enc(str);
8083 if (case_option_single_p(flags, enc, str)) {
8084 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8085 str_enc_copy_direct(ret, str);
8086 downcase_single(ret);
8088 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8090 rb_str_ascii_casemap(str, ret, &flags, enc);
8093 ret = rb_str_casemap(str, &flags, enc);
8113rb_str_capitalize_bang(
int argc,
VALUE *argv,
VALUE str)
8116 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8118 flags = check_case_options(argc, argv, flags);
8119 str_modify_keep_cr(str);
8120 enc = str_true_enc(str);
8121 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8122 if (flags&ONIGENC_CASE_ASCII_ONLY)
8123 rb_str_ascii_casemap(str, str, &flags, enc);
8125 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8127 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8141rb_str_capitalize(
int argc,
VALUE *argv,
VALUE str)
8144 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8147 flags = check_case_options(argc, argv, flags);
8148 enc = str_true_enc(str);
8149 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str;
8150 if (flags&ONIGENC_CASE_ASCII_ONLY) {
8152 rb_str_ascii_casemap(str, ret, &flags, enc);
8155 ret = rb_str_casemap(str, &flags, enc);
8174rb_str_swapcase_bang(
int argc,
VALUE *argv,
VALUE str)
8177 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8179 flags = check_case_options(argc, argv, flags);
8180 str_modify_keep_cr(str);
8181 enc = str_true_enc(str);
8182 if (flags&ONIGENC_CASE_ASCII_ONLY)
8183 rb_str_ascii_casemap(str, str, &flags, enc);
8185 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8187 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8201rb_str_swapcase(
int argc,
VALUE *argv,
VALUE str)
8204 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8207 flags = check_case_options(argc, argv, flags);
8208 enc = str_true_enc(str);
8209 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str_duplicate(
rb_cString, str);
8210 if (flags&ONIGENC_CASE_ASCII_ONLY) {
8212 rb_str_ascii_casemap(str, ret, &flags, enc);
8215 ret = rb_str_casemap(str, &flags, enc);
8220typedef unsigned char *USTR;
8224 unsigned int now, max;
8229trnext(
struct tr *t, rb_encoding *enc)
8236 if (t->p == t->pend)
return -1;
8237 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'\\' && t->p + n < t->pend) {
8240 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8242 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'-' && t->p + n < t->pend) {
8244 if (t->p < t->pend) {
8245 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8248 if (t->now < 0x80 && c < 0x80) {
8249 rb_raise(rb_eArgError,
8250 "invalid range \"%c-%c\" in string transliteration",
8254 rb_raise(rb_eArgError,
"invalid range in string transliteration");
8258 else if (t->now < c) {
8267 while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
8268 if (t->now == t->max) {
8273 if (t->now < t->max) {
8289 const unsigned int errc = -1;
8290 unsigned int trans[256];
8291 rb_encoding *enc, *e1, *e2;
8292 struct tr trsrc, trrepl;
8294 unsigned int c, c0, last = 0;
8295 int modify = 0, i, l;
8296 unsigned char *s, *send;
8298 int singlebyte = single_byte_optimizable(str);
8302#define CHECK_IF_ASCII(c) \
8303 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
8304 (cr = ENC_CODERANGE_VALID) : 0)
8308 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8309 if (RSTRING_LEN(repl) == 0) {
8310 return rb_str_delete_bang(1, &src, str);
8314 e1 = rb_enc_check(str, src);
8315 e2 = rb_enc_check(str, repl);
8320 enc = rb_enc_check(src, repl);
8322 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
8323 if (RSTRING_LEN(src) > 1 &&
8324 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) ==
'^' &&
8325 trsrc.p + l < trsrc.pend) {
8329 trrepl.p = RSTRING_PTR(repl);
8330 trrepl.pend = trrepl.p + RSTRING_LEN(repl);
8331 trsrc.gen = trrepl.gen = 0;
8332 trsrc.now = trrepl.now = 0;
8333 trsrc.max = trrepl.max = 0;
8336 for (i=0; i<256; i++) {
8339 while ((c = trnext(&trsrc, enc)) != errc) {
8344 if (!hash) hash = rb_hash_new();
8348 while ((c = trnext(&trrepl, enc)) != errc)
8351 for (i=0; i<256; i++) {
8352 if (trans[i] != errc) {
8360 for (i=0; i<256; i++) {
8363 while ((c = trnext(&trsrc, enc)) != errc) {
8364 r = trnext(&trrepl, enc);
8365 if (r == errc) r = trrepl.now;
8368 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
8371 if (!hash) hash = rb_hash_new();
8379 str_modify_keep_cr(str);
8380 s = (
unsigned char *)RSTRING_PTR(str); send = (
unsigned char *)RSTRING_END(str);
8381 termlen = rb_enc_mbminlen(enc);
8384 long offset, max = RSTRING_LEN(str);
8385 unsigned int save = -1;
8386 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
8391 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
8394 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
8397 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
8399 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
8408 if (cflag) c = last;
8411 else if (cflag) c = errc;
8417 if (c != (
unsigned int)-1) {
8423 tlen = rb_enc_codelen(c, enc);
8429 if (enc != e1) may_modify = 1;
8431 if ((offset = t - buf) + tlen > max) {
8432 size_t MAYBE_UNUSED(old) = max + termlen;
8433 max = offset + tlen + (send - s);
8434 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
8437 rb_enc_mbcput(c, t, enc);
8438 if (may_modify && memcmp(s, t, tlen) != 0) {
8444 if (!STR_EMBED_P(str)) {
8445 ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
8447 TERM_FILL((
char *)t, termlen);
8448 RSTRING(str)->as.heap.ptr = (
char *)buf;
8449 STR_SET_LEN(str, t - buf);
8450 STR_SET_NOEMBED(str);
8451 RSTRING(str)->as.heap.aux.capa = max;
8453 else if (rb_enc_mbmaxlen(enc) == 1 || (singlebyte && !hash)) {
8455 c = (
unsigned char)*s;
8456 if (trans[c] != errc) {
8473 long offset, max = (long)((send - s) * 1.2);
8474 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
8479 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
8482 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
8485 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
8487 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
8495 if (cflag) c = last;
8498 else if (cflag) c = errc;
8502 c = cflag ? last : errc;
8505 tlen = rb_enc_codelen(c, enc);
8510 if (enc != e1) may_modify = 1;
8512 if ((offset = t - buf) + tlen > max) {
8513 size_t MAYBE_UNUSED(old) = max + termlen;
8514 max = offset + tlen + (long)((send - s) * 1.2);
8515 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
8519 rb_enc_mbcput(c, t, enc);
8520 if (may_modify && memcmp(s, t, tlen) != 0) {
8528 if (!STR_EMBED_P(str)) {
8529 ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
8531 TERM_FILL((
char *)t, termlen);
8532 RSTRING(str)->as.heap.ptr = (
char *)buf;
8533 STR_SET_LEN(str, t - buf);
8534 STR_SET_NOEMBED(str);
8535 RSTRING(str)->as.heap.aux.capa = max;
8541 rb_enc_associate(str, enc);
8563 return tr_trans(str, src, repl, 0);
8608 tr_trans(str, src, repl, 0);
8612#define TR_TABLE_MAX (UCHAR_MAX+1)
8613#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
8615tr_setup_table(
VALUE str,
char stable[TR_TABLE_SIZE],
int first,
8616 VALUE *tablep,
VALUE *ctablep, rb_encoding *enc)
8618 const unsigned int errc = -1;
8619 char buf[TR_TABLE_MAX];
8622 VALUE table = 0, ptable = 0;
8623 int i, l, cflag = 0;
8625 tr.p = RSTRING_PTR(str);
tr.pend =
tr.p + RSTRING_LEN(str);
8626 tr.gen =
tr.now =
tr.max = 0;
8628 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(
tr.p,
tr.pend, &l, enc) ==
'^') {
8633 for (i=0; i<TR_TABLE_MAX; i++) {
8636 stable[TR_TABLE_MAX] = cflag;
8638 else if (stable[TR_TABLE_MAX] && !cflag) {
8639 stable[TR_TABLE_MAX] = 0;
8641 for (i=0; i<TR_TABLE_MAX; i++) {
8645 while ((c = trnext(&
tr, enc)) != errc) {
8646 if (c < TR_TABLE_MAX) {
8647 buf[(
unsigned char)c] = !cflag;
8652 if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
8655 table = ptable ? ptable : rb_hash_new();
8659 table = rb_hash_new();
8664 if (table && (!ptable || (cflag ^ !
NIL_P(rb_hash_aref(ptable, key))))) {
8665 rb_hash_aset(table, key,
Qtrue);
8669 for (i=0; i<TR_TABLE_MAX; i++) {
8670 stable[i] = stable[i] && buf[i];
8672 if (!table && !cflag) {
8679tr_find(
unsigned int c,
const char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
8681 if (c < TR_TABLE_MAX) {
8682 return table[c] != 0;
8688 if (!
NIL_P(rb_hash_lookup(del, v)) &&
8689 (!nodel ||
NIL_P(rb_hash_lookup(nodel, v)))) {
8693 else if (nodel && !
NIL_P(rb_hash_lookup(nodel, v))) {
8696 return table[TR_TABLE_MAX] ? TRUE : FALSE;
8711rb_str_delete_bang(
int argc,
VALUE *argv,
VALUE str)
8713 char squeez[TR_TABLE_SIZE];
8714 rb_encoding *enc = 0;
8716 VALUE del = 0, nodel = 0;
8718 int i, ascompat, cr;
8720 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8722 for (i=0; i<argc; i++) {
8726 enc = rb_enc_check(str, s);
8727 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
8730 str_modify_keep_cr(str);
8731 ascompat = rb_enc_asciicompat(enc);
8732 s = t = RSTRING_PTR(str);
8733 send = RSTRING_END(str);
8739 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
8750 c = rb_enc_codepoint_len(s, send, &clen, enc);
8752 if (tr_find(c, squeez, del, nodel)) {
8756 if (t != s) rb_enc_mbcput(c, t, enc);
8763 TERM_FILL(t, TERM_LEN(str));
8764 STR_SET_LEN(str, t - RSTRING_PTR(str));
8767 if (modify)
return str;
8781rb_str_delete(
int argc,
VALUE *argv,
VALUE str)
8784 rb_str_delete_bang(argc, argv, str);
8802rb_str_squeeze_bang(
int argc,
VALUE *argv,
VALUE str)
8804 char squeez[TR_TABLE_SIZE];
8805 rb_encoding *enc = 0;
8806 VALUE del = 0, nodel = 0;
8807 unsigned char *s, *send, *t;
8809 int ascompat, singlebyte = single_byte_optimizable(str);
8813 enc = STR_ENC_GET(str);
8816 for (i=0; i<argc; i++) {
8820 enc = rb_enc_check(str, s);
8821 if (singlebyte && !single_byte_optimizable(s))
8823 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
8827 str_modify_keep_cr(str);
8828 s = t = (
unsigned char *)RSTRING_PTR(str);
8829 if (!s || RSTRING_LEN(str) == 0)
return Qnil;
8830 send = (
unsigned char *)RSTRING_END(str);
8832 ascompat = rb_enc_asciicompat(enc);
8836 unsigned int c = *s++;
8837 if (c != save || (argc > 0 && !squeez[c])) {
8847 if (ascompat && (c = *s) < 0x80) {
8848 if (c != save || (argc > 0 && !squeez[c])) {
8854 c = rb_enc_codepoint_len((
char *)s, (
char *)send, &clen, enc);
8856 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
8857 if (t != s) rb_enc_mbcput(c, t, enc);
8866 TERM_FILL((
char *)t, TERM_LEN(str));
8867 if ((
char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
8868 STR_SET_LEN(str, (
char *)t - RSTRING_PTR(str));
8872 if (modify)
return str;
8886rb_str_squeeze(
int argc,
VALUE *argv,
VALUE str)
8889 rb_str_squeeze_bang(argc, argv, str);
8909 return tr_trans(str, src, repl, 1);
8937 tr_trans(str, src, repl, 1);
8950rb_str_count(
int argc,
VALUE *argv,
VALUE str)
8952 char table[TR_TABLE_SIZE];
8953 rb_encoding *enc = 0;
8954 VALUE del = 0, nodel = 0, tstr;
8964 enc = rb_enc_check(str, tstr);
8967 if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
8968 (ptstr = RSTRING_PTR(tstr),
8969 ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (
const unsigned char *)ptstr, (
const unsigned char *)ptstr+1)) &&
8970 !is_broken_string(str)) {
8972 unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
8974 s = RSTRING_PTR(str);
8975 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
8976 send = RSTRING_END(str);
8978 if (*(
unsigned char*)s++ == c) n++;
8984 tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
8985 for (i=1; i<argc; i++) {
8988 enc = rb_enc_check(str, tstr);
8989 tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
8992 s = RSTRING_PTR(str);
8993 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
8994 send = RSTRING_END(str);
8995 ascompat = rb_enc_asciicompat(enc);
8999 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
9007 c = rb_enc_codepoint_len(s, send, &clen, enc);
9008 if (tr_find(c, table, del, nodel)) {
9019rb_fs_check(
VALUE val)
9023 if (
NIL_P(val))
return 0;
9028static const char isspacetable[256] = {
9029 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
9030 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9031 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9032 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9033 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9034 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9035 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9036 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9040 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9042 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9043 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
9047#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
9050split_string(
VALUE result,
VALUE str,
long beg,
long len,
long empty_count)
9052 if (empty_count >= 0 &&
len == 0) {
9053 return empty_count + 1;
9055 if (empty_count > 0) {
9060 }
while (--empty_count > 0);
9064 rb_yield(str_new_empty_String(str));
9065 }
while (--empty_count > 0);
9079 SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
9083literal_split_pattern(
VALUE spat, split_type_t default_type)
9085 rb_encoding *enc = STR_ENC_GET(spat);
9091 return SPLIT_TYPE_CHARS;
9093 else if (rb_enc_asciicompat(enc)) {
9094 if (
len == 1 &&
ptr[0] ==
' ') {
9095 return SPLIT_TYPE_AWK;
9100 if (rb_enc_ascget(
ptr,
ptr +
len, &l, enc) ==
' ' &&
len == l) {
9101 return SPLIT_TYPE_AWK;
9104 return default_type;
9117rb_str_split_m(
int argc,
VALUE *argv,
VALUE str)
9122 split_type_t split_type;
9123 long beg, end, i = 0, empty_count = -1;
9128 if (
rb_scan_args(argc, argv,
"02", &spat, &limit) == 2) {
9130 if (lim <= 0) limit =
Qnil;
9131 else if (lim == 1) {
9132 if (RSTRING_LEN(str) == 0)
9143 if (
NIL_P(limit) && !lim) empty_count = 0;
9145 enc = STR_ENC_GET(str);
9146 split_type = SPLIT_TYPE_REGEXP;
9148 spat = get_pat_quoted(spat, 0);
9151 split_type = SPLIT_TYPE_AWK;
9153 else if (!(spat = rb_fs_check(spat))) {
9154 rb_raise(
rb_eTypeError,
"value of $; must be String or Regexp");
9159 if (split_type != SPLIT_TYPE_AWK) {
9163 tmp = RREGEXP_SRC(spat);
9164 split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
9165 if (split_type == SPLIT_TYPE_AWK) {
9167 split_type = SPLIT_TYPE_STRING;
9172 mustnot_broken(spat);
9173 split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
9181#define SPLIT_STR(beg, len) ( \
9182 empty_count = split_string(result, str, beg, len, empty_count), \
9183 str_mod_check(str, str_start, str_len))
9186 char *
ptr = RSTRING_PTR(str);
9187 char *
const str_start =
ptr;
9188 const long str_len = RSTRING_LEN(str);
9189 char *
const eptr = str_start + str_len;
9190 if (split_type == SPLIT_TYPE_AWK) {
9197 if (is_ascii_string(str)) {
9198 while (
ptr < eptr) {
9199 c = (
unsigned char)*
ptr++;
9201 if (ascii_isspace(c)) {
9207 if (!
NIL_P(limit) && lim <= i)
break;
9210 else if (ascii_isspace(c)) {
9211 SPLIT_STR(beg, end-beg);
9214 if (!
NIL_P(limit)) ++i;
9222 while (
ptr < eptr) {
9225 c = rb_enc_codepoint_len(
ptr, eptr, &n, enc);
9228 if (rb_isspace(c)) {
9234 if (!
NIL_P(limit) && lim <= i)
break;
9237 else if (rb_isspace(c)) {
9238 SPLIT_STR(beg, end-beg);
9241 if (!
NIL_P(limit)) ++i;
9249 else if (split_type == SPLIT_TYPE_STRING) {
9250 char *substr_start =
ptr;
9251 char *sptr = RSTRING_PTR(spat);
9252 long slen = RSTRING_LEN(spat);
9255 mustnot_broken(str);
9256 enc = rb_enc_check(str, spat);
9257 while (
ptr < eptr &&
9260 char *t = rb_enc_right_char_head(
ptr,
ptr + end, eptr, enc);
9261 if (t !=
ptr + end) {
9265 SPLIT_STR(substr_start - str_start, (
ptr+end) - substr_start);
9266 str_mod_check(spat, sptr, slen);
9269 if (!
NIL_P(limit) && lim <= ++i)
break;
9271 beg =
ptr - str_start;
9273 else if (split_type == SPLIT_TYPE_CHARS) {
9277 mustnot_broken(str);
9278 enc = rb_enc_get(str);
9279 while (
ptr < eptr &&
9280 (n = rb_enc_precise_mbclen(
ptr, eptr, enc)) > 0) {
9281 SPLIT_STR(
ptr - str_start, n);
9283 if (!
NIL_P(limit) && lim <= ++i)
break;
9285 beg =
ptr - str_start;
9289 long len = RSTRING_LEN(str);
9297 (match ? (rb_match_unbusy(match),
rb_backref_set(match)) : (void)0)) {
9300 regs = RMATCH_REGS(match);
9302 if (start == end && BEG(0) == END(0)) {
9307 else if (last_null == 1) {
9308 SPLIT_STR(beg, rb_enc_fast_mbclen(
ptr+beg, eptr, enc));
9315 start += rb_enc_fast_mbclen(
ptr+start,eptr,enc);
9321 SPLIT_STR(beg, end-beg);
9322 beg = start = END(0);
9326 for (idx=1; idx < regs->num_regs; idx++) {
9327 if (BEG(idx) == -1)
continue;
9328 SPLIT_STR(BEG(idx), END(idx)-BEG(idx));
9330 if (!
NIL_P(limit) && lim <= ++i)
break;
9332 if (match) rb_match_unbusy(match);
9334 if (RSTRING_LEN(str) > 0 && (!
NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
9335 SPLIT_STR(beg, RSTRING_LEN(str)-beg);
9338 return result ? result : str;
9348 return rb_str_split_m(1, &sep, str);
9351#define WANTARRAY(m, size) (!rb_block_given_p() ? rb_ary_new_capa(size) : 0)
9366#define ENUM_ELEM(ary, e) enumerator_element(ary, e)
9369chomp_newline(
const char *p,
const char *e, rb_encoding *enc)
9371 const char *prev = rb_enc_prev_char(p, e, e, enc);
9372 if (rb_enc_is_newline(prev, e, enc)) {
9374 prev = rb_enc_prev_char(p, e, e, enc);
9375 if (prev && rb_enc_ascget(prev, e, NULL, enc) ==
'\r')
9387 RSTRING_LEN(rs) != 1 ||
9388 RSTRING_PTR(rs)[0] !=
'\n')) {
9394#define rb_rs get_rs()
9401 const char *
ptr, *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
9402 long pos,
len, rslen;
9408 static ID keywords[1];
9410 keywords[0] = rb_intern_const(
"chomp");
9413 chomp = (!UNDEF_P(chomp) &&
RTEST(chomp));
9417 if (!ENUM_ELEM(ary, str)) {
9425 if (!RSTRING_LEN(str))
goto end;
9427 ptr = subptr = RSTRING_PTR(str);
9428 pend = RSTRING_END(str);
9429 len = RSTRING_LEN(str);
9431 rslen = RSTRING_LEN(rs);
9434 enc = rb_enc_get(str);
9436 enc = rb_enc_check(str, rs);
9441 const char *eol = NULL;
9443 while (subend < pend) {
9444 long chomp_rslen = 0;
9446 if (rb_enc_ascget(subend, pend, &n, enc) !=
'\r')
9448 rslen = n + rb_enc_mbclen(subend + n, pend, enc);
9449 if (rb_enc_is_newline(subend + n, pend, enc)) {
9450 if (eol == subend)
break;
9454 chomp_rslen = -rslen;
9458 if (!subptr) subptr = subend;
9462 }
while (subend < pend);
9464 if (rslen == 0) chomp_rslen = 0;
9466 subend - subptr + (chomp ? chomp_rslen : rslen));
9467 if (ENUM_ELEM(ary, line)) {
9468 str_mod_check(str,
ptr,
len);
9470 subptr = eol = NULL;
9475 rsptr = RSTRING_PTR(rs);
9476 if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
9477 rb_enc_is_newline(rsptr, rsptr + RSTRING_LEN(rs), enc)) {
9485 rsptr = RSTRING_PTR(rs);
9486 rslen = RSTRING_LEN(rs);
9489 while (subptr < pend) {
9490 pos =
rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
9493 adjusted = rb_enc_right_char_head(subptr, hit, pend, enc);
9494 if (hit != adjusted) {
9498 subend = hit += rslen;
9501 subend = chomp_newline(subptr, subend, enc);
9508 if (ENUM_ELEM(ary, line)) {
9509 str_mod_check(str,
ptr,
len);
9514 if (subptr != pend) {
9517 pend = chomp_newline(subptr, pend, enc);
9519 else if (pend - subptr >= rslen &&
9520 memcmp(pend - rslen, rsptr, rslen) == 0) {
9525 ENUM_ELEM(ary, line);
9546rb_str_each_line(
int argc,
VALUE *argv,
VALUE str)
9549 return rb_str_enumerate_lines(argc, argv, str, 0);
9604rb_str_lines(
int argc,
VALUE *argv,
VALUE str)
9606 VALUE ary = WANTARRAY(
"lines", 0);
9607 return rb_str_enumerate_lines(argc, argv, str, ary);
9621 for (i=0; i<RSTRING_LEN(str); i++) {
9622 ENUM_ELEM(ary,
INT2FIX((
unsigned char)RSTRING_PTR(str)[i]));
9640rb_str_each_byte(
VALUE str)
9643 return rb_str_enumerate_bytes(str, 0);
9655rb_str_bytes(
VALUE str)
9657 VALUE ary = WANTARRAY(
"bytes", RSTRING_LEN(str));
9658 return rb_str_enumerate_bytes(str, ary);
9676 ptr = RSTRING_PTR(str);
9677 len = RSTRING_LEN(str);
9678 enc = rb_enc_get(str);
9681 for (i = 0; i <
len; i += n) {
9682 n = rb_enc_fast_mbclen(
ptr + i,
ptr +
len, enc);
9687 for (i = 0; i <
len; i += n) {
9688 n = rb_enc_mbclen(
ptr + i,
ptr +
len, enc);
9709rb_str_each_char(
VALUE str)
9712 return rb_str_enumerate_chars(str, 0);
9724rb_str_chars(
VALUE str)
9727 return rb_str_enumerate_chars(str, ary);
9731rb_str_enumerate_codepoints(
VALUE str,
VALUE ary)
9736 const char *
ptr, *end;
9739 if (single_byte_optimizable(str))
9740 return rb_str_enumerate_bytes(str, ary);
9743 ptr = RSTRING_PTR(str);
9744 end = RSTRING_END(str);
9745 enc = STR_ENC_GET(str);
9748 c = rb_enc_codepoint_len(
ptr, end, &n, enc);
9769rb_str_each_codepoint(
VALUE str)
9772 return rb_str_enumerate_codepoints(str, 0);
9784rb_str_codepoints(
VALUE str)
9787 return rb_str_enumerate_codepoints(str, ary);
9791get_reg_grapheme_cluster(rb_encoding *enc)
9793 int encidx = rb_enc_to_index(enc);
9795 const OnigUChar source_ascii[] =
"\\X";
9796 const OnigUChar *source = source_ascii;
9797 size_t source_len =
sizeof(source_ascii) - 1;
9800#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
9801#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
9802#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
9803#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
9804#define CASE_UTF(e) \
9805 case ENCINDEX_UTF_##e: { \
9806 static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
9807 source = source_UTF_##e; \
9808 source_len = sizeof(source_UTF_##e); \
9811 CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
9819 regex_t *reg_grapheme_cluster;
9821 int r = onig_new(®_grapheme_cluster, source, source + source_len,
9822 ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
9824 UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
9825 onig_error_code_to_str(message, r, &einfo);
9826 rb_fatal(
"cannot compile grapheme cluster regexp: %s", (
char *)message);
9829 return reg_grapheme_cluster;
9833get_cached_reg_grapheme_cluster(rb_encoding *enc)
9835 int encidx = rb_enc_to_index(enc);
9836 static regex_t *reg_grapheme_cluster_utf8 = NULL;
9838 if (encidx == rb_utf8_encindex()) {
9839 if (!reg_grapheme_cluster_utf8) {
9840 reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
9843 return reg_grapheme_cluster_utf8;
9852 size_t grapheme_cluster_count = 0;
9853 rb_encoding *enc = get_encoding(str);
9854 const char *
ptr, *end;
9856 if (!rb_enc_unicode_p(enc)) {
9860 bool cached_reg_grapheme_cluster =
true;
9861 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
9862 if (!reg_grapheme_cluster) {
9863 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
9864 cached_reg_grapheme_cluster =
false;
9867 ptr = RSTRING_PTR(str);
9868 end = RSTRING_END(str);
9871 OnigPosition
len = onig_match(reg_grapheme_cluster,
9872 (
const OnigUChar *)
ptr, (
const OnigUChar *)end,
9873 (
const OnigUChar *)
ptr, NULL, 0);
9874 if (
len <= 0)
break;
9875 grapheme_cluster_count++;
9879 if (!cached_reg_grapheme_cluster) {
9880 onig_free(reg_grapheme_cluster);
9883 return SIZET2NUM(grapheme_cluster_count);
9887rb_str_enumerate_grapheme_clusters(
VALUE str,
VALUE ary)
9890 rb_encoding *enc = get_encoding(str);
9891 const char *ptr0, *
ptr, *end;
9893 if (!rb_enc_unicode_p(enc)) {
9894 return rb_str_enumerate_chars(str, ary);
9899 bool cached_reg_grapheme_cluster =
true;
9900 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
9901 if (!reg_grapheme_cluster) {
9902 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
9903 cached_reg_grapheme_cluster =
false;
9906 ptr0 =
ptr = RSTRING_PTR(str);
9907 end = RSTRING_END(str);
9910 OnigPosition
len = onig_match(reg_grapheme_cluster,
9911 (
const OnigUChar *)
ptr, (
const OnigUChar *)end,
9912 (
const OnigUChar *)
ptr, NULL, 0);
9913 if (
len <= 0)
break;
9918 if (!cached_reg_grapheme_cluster) {
9919 onig_free(reg_grapheme_cluster);
9939rb_str_each_grapheme_cluster(
VALUE str)
9942 return rb_str_enumerate_grapheme_clusters(str, 0);
9954rb_str_grapheme_clusters(
VALUE str)
9957 return rb_str_enumerate_grapheme_clusters(str, ary);
9961chopped_length(
VALUE str)
9963 rb_encoding *enc = STR_ENC_GET(str);
9964 const char *p, *p2, *beg, *end;
9966 beg = RSTRING_PTR(str);
9967 end = beg + RSTRING_LEN(str);
9968 if (beg >= end)
return 0;
9969 p = rb_enc_prev_char(beg, end, end, enc);
9971 if (p > beg && rb_enc_ascget(p, end, 0, enc) ==
'\n') {
9972 p2 = rb_enc_prev_char(beg, p, end, enc);
9973 if (p2 && rb_enc_ascget(p2, end, 0, enc) ==
'\r') p = p2;
9991rb_str_chop_bang(
VALUE str)
9993 str_modify_keep_cr(str);
9994 if (RSTRING_LEN(str) > 0) {
9996 len = chopped_length(str);
9997 STR_SET_LEN(str,
len);
9998 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
10017rb_str_chop(
VALUE str)
10023smart_chomp(
VALUE str,
const char *e,
const char *p)
10025 rb_encoding *enc = rb_enc_get(str);
10026 if (rb_enc_mbminlen(enc) > 1) {
10027 const char *pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
10028 if (rb_enc_is_newline(pp, e, enc)) {
10031 pp = e - rb_enc_mbminlen(enc);
10033 pp = rb_enc_left_char_head(p, pp, e, enc);
10034 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
10042 if (--e > p && *(e-1) ==
'\r') {
10059 char *pp, *e, *rsptr;
10061 char *
const p = RSTRING_PTR(str);
10062 long len = RSTRING_LEN(str);
10064 if (
len == 0)
return 0;
10067 return smart_chomp(str, e, p);
10070 enc = rb_enc_get(str);
10073 if (rb_enc_mbminlen(enc) > 1) {
10075 pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
10076 if (!rb_enc_is_newline(pp, e, enc))
break;
10078 pp -= rb_enc_mbminlen(enc);
10080 pp = rb_enc_left_char_head(p, pp, e, enc);
10081 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
10088 while (e > p && *(e-1) ==
'\n') {
10090 if (e > p && *(e-1) ==
'\r')
10096 if (rslen >
len)
return len;
10098 enc = rb_enc_get(rs);
10099 newline = rsptr[rslen-1];
10100 if (rslen == rb_enc_mbminlen(enc)) {
10102 if (newline ==
'\n')
10103 return smart_chomp(str, e, p);
10106 if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
10107 return smart_chomp(str, e, p);
10111 enc = rb_enc_check(str, rs);
10112 if (is_broken_string(rs)) {
10116 if (p[
len-1] == newline &&
10118 memcmp(rsptr, pp, rslen) == 0)) {
10119 if (at_char_boundary(p, pp, e, enc))
10120 return len - rslen;
10132chomp_rs(
int argc,
const VALUE *argv)
10134 rb_check_arity(argc, 0, 1);
10136 VALUE rs = argv[0];
10148 long olen = RSTRING_LEN(str);
10149 long len = chompped_length(str, rs);
10150 if (
len >= olen)
return Qnil;
10151 str_modify_keep_cr(str);
10152 STR_SET_LEN(str,
len);
10153 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
10173rb_str_chomp_bang(
int argc,
VALUE *argv,
VALUE str)
10176 str_modifiable(str);
10177 if (RSTRING_LEN(str) == 0 && argc < 2)
return Qnil;
10178 rs = chomp_rs(argc, argv);
10180 return rb_str_chomp_string(str, rs);
10193rb_str_chomp(
int argc,
VALUE *argv,
VALUE str)
10195 VALUE rs = chomp_rs(argc, argv);
10201tr_setup_table_multi(
char table[TR_TABLE_SIZE],
VALUE *tablep,
VALUE *ctablep,
10202 VALUE str,
int num_selectors,
VALUE *selectors)
10206 for (i=0; i<num_selectors; i++) {
10207 VALUE selector = selectors[i];
10211 enc = rb_enc_check(str, selector);
10212 tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
10217lstrip_offset(
VALUE str,
const char *s,
const char *e, rb_encoding *enc)
10219 const char *
const start = s;
10221 if (!s || s >= e)
return 0;
10224 if (single_byte_optimizable(str)) {
10225 while (s < e && (*s ==
'\0' || ascii_isspace(*s))) s++;
10230 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10232 if (cc && !rb_isspace(cc))
break;
10240lstrip_offset_table(
VALUE str,
const char *s,
const char *e, rb_encoding *enc,
10241 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
10243 const char *
const start = s;
10245 if (!s || s >= e)
return 0;
10250 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10252 if (!tr_find(cc, table, del, nodel))
break;
10271rb_str_lstrip_bang(
int argc,
VALUE *argv,
VALUE str)
10275 long olen, loffset;
10277 str_modify_keep_cr(str);
10278 enc = STR_ENC_GET(str);
10281 char table[TR_TABLE_SIZE];
10282 VALUE del = 0, nodel = 0;
10284 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10285 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10288 loffset = lstrip_offset(str, start, start+olen, enc);
10292 long len = olen-loffset;
10293 s = start + loffset;
10294 memmove(start, s,
len);
10295 STR_SET_LEN(str,
len);
10296 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
10331rb_str_lstrip(
int argc,
VALUE *argv,
VALUE str)
10338 char table[TR_TABLE_SIZE];
10339 VALUE del = 0, nodel = 0;
10341 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10342 loffset = lstrip_offset_table(str, start, start+
len, STR_ENC_GET(str), table, del, nodel);
10345 loffset = lstrip_offset(str, start, start+
len, STR_ENC_GET(str));
10347 if (loffset <= 0)
return str_duplicate(
rb_cString, str);
10352rstrip_offset(
VALUE str,
const char *s,
const char *e, rb_encoding *enc)
10356 rb_str_check_dummy_enc(enc);
10360 if (!s || s >= e)
return 0;
10364 if (single_byte_optimizable(str)) {
10366 while (s < t && ((c = *(t-1)) ==
'\0' || ascii_isspace(c))) t--;
10371 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
10372 unsigned int c = rb_enc_codepoint(tp, e, enc);
10373 if (c && !rb_isspace(c))
break;
10381rstrip_offset_table(
VALUE str,
const char *s,
const char *e, rb_encoding *enc,
10382 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
10387 rb_str_check_dummy_enc(enc);
10391 if (!s || s >= e)
return 0;
10395 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
10396 unsigned int c = rb_enc_codepoint(tp, e, enc);
10397 if (!tr_find(c, table, del, nodel))
break;
10417rb_str_rstrip_bang(
int argc,
VALUE *argv,
VALUE str)
10421 long olen, roffset;
10423 str_modify_keep_cr(str);
10424 enc = STR_ENC_GET(str);
10427 char table[TR_TABLE_SIZE];
10428 VALUE del = 0, nodel = 0;
10430 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10431 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10434 roffset = rstrip_offset(str, start, start+olen, enc);
10437 long len = olen - roffset;
10439 STR_SET_LEN(str,
len);
10440 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
10474rb_str_rstrip(
int argc,
VALUE *argv,
VALUE str)
10478 long olen, roffset;
10480 enc = STR_ENC_GET(str);
10483 char table[TR_TABLE_SIZE];
10484 VALUE del = 0, nodel = 0;
10486 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10487 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10490 roffset = rstrip_offset(str, start, start+olen, enc);
10492 if (roffset <= 0)
return str_duplicate(
rb_cString, str);
10510rb_str_strip_bang(
int argc,
VALUE *argv,
VALUE str)
10513 long olen, loffset, roffset;
10516 str_modify_keep_cr(str);
10517 enc = STR_ENC_GET(str);
10521 char table[TR_TABLE_SIZE];
10522 VALUE del = 0, nodel = 0;
10524 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10525 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10526 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
10529 loffset = lstrip_offset(str, start, start+olen, enc);
10530 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
10533 if (loffset > 0 || roffset > 0) {
10534 long len = olen-roffset;
10537 memmove(start, start + loffset,
len);
10539 STR_SET_LEN(str,
len);
10540 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
10575rb_str_strip(
int argc,
VALUE *argv,
VALUE str)
10578 long olen, loffset, roffset;
10579 rb_encoding *enc = STR_ENC_GET(str);
10584 char table[TR_TABLE_SIZE];
10585 VALUE del = 0, nodel = 0;
10587 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10588 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10589 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
10592 loffset = lstrip_offset(str, start, start+olen, enc);
10593 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
10596 if (loffset <= 0 && roffset <= 0)
return str_duplicate(
rb_cString, str);
10601scan_once(
VALUE str,
VALUE pat,
long *start,
int set_backref_str)
10604 long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
10610 end = pos + RSTRING_LEN(pat);
10614 regs = RMATCH_REGS(match);
10620 rb_encoding *enc = STR_ENC_GET(str);
10624 if (RSTRING_LEN(str) > end)
10625 *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
10626 RSTRING_END(str), enc);
10634 if (!regs || regs->num_regs == 1) {
10640 for (
int i = 1; i < regs->num_regs; i++) {
10671 long last = -1, prev = 0;
10672 char *p = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
10674 pat = get_pat_quoted(pat, 1);
10675 mustnot_broken(str);
10679 while (!
NIL_P(result = scan_once(str, pat, &start, 0))) {
10684 if (last >= 0) rb_pat_search(pat, str, last, 1);
10689 while (!
NIL_P(result = scan_once(str, pat, &start, 1))) {
10693 str_mod_check(str, p,
len);
10695 if (last >= 0) rb_pat_search(pat, str, last, 1);
10747rb_str_hex(
VALUE str)
10749 return rb_str_to_inum(str, 16, FALSE);
10833rb_str_oct(
VALUE str)
10835 return rb_str_to_inum(str, -8, FALSE);
10838#ifndef HAVE_CRYPT_R
10843 rb_nativethread_lock_t lock;
10844} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
10913# define CRYPT_END() ALLOCV_END(databuf)
10916 extern char *crypt(
const char *,
const char *);
10917# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
10920 const char *s, *saltp;
10923 char salt_8bit_clean[3];
10927 mustnot_wchar(str);
10928 mustnot_wchar(salt);
10930 saltp = RSTRING_PTR(salt);
10931 if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
10932 rb_raise(rb_eArgError,
"salt too short (need >=2 bytes)");
10936 if (!ISASCII((
unsigned char)saltp[0]) || !ISASCII((
unsigned char)saltp[1])) {
10937 salt_8bit_clean[0] = saltp[0] & 0x7f;
10938 salt_8bit_clean[1] = saltp[1] & 0x7f;
10939 salt_8bit_clean[2] =
'\0';
10940 saltp = salt_8bit_clean;
10945# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
10946 data->initialized = 0;
10948 res = crypt_r(s, saltp, data);
10951 res = crypt(s, saltp);
10966 size_t res_size = strlen(res)+1;
10967 tmp_buf =
ALLOCA_N(
char, res_size);
10968 memcpy(tmp_buf, res, res_size);
10990 c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
11005 char *
ptr, *p, *pend;
11008 unsigned long sum0 = 0;
11010 if (rb_check_arity(argc, 0, 1) && (bits =
NUM2INT(argv[0])) < 0) {
11013 ptr = p = RSTRING_PTR(str);
11014 len = RSTRING_LEN(str);
11020 str_mod_check(str,
ptr,
len);
11023 sum0 += (
unsigned char)*p;
11034 if (bits < (
int)
sizeof(
long)*CHAR_BIT) {
11035 sum0 &= (((
unsigned long)1)<<bits)-1;
11055rb_str_justify(
int argc,
VALUE *argv,
VALUE str,
char jflag)
11059 long width,
len, flen = 1, fclen = 1;
11062 const char *f =
" ";
11063 long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
11065 int singlebyte = 1, cr;
11069 enc = STR_ENC_GET(str);
11070 termlen = rb_enc_mbminlen(enc);
11074 enc = rb_enc_check(str, pad);
11075 f = RSTRING_PTR(pad);
11076 flen = RSTRING_LEN(pad);
11077 fclen = str_strlen(pad, enc);
11078 singlebyte = single_byte_optimizable(pad);
11079 if (flen == 0 || fclen == 0) {
11080 rb_raise(rb_eArgError,
"zero width padding");
11083 len = str_strlen(str, enc);
11084 if (width < 0 || len >= width)
return str_duplicate(
rb_cString, str);
11086 llen = (jflag ==
'l') ? 0 : ((jflag ==
'r') ? n : n/2);
11090 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
11091 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
11093 size = RSTRING_LEN(str);
11094 if ((
len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
11095 (
len *= flen) >= LONG_MAX - llen2 - rlen2 ||
11096 (
len += llen2 + rlen2) >= LONG_MAX - size) {
11097 rb_raise(rb_eArgError,
"argument too big");
11101 p = RSTRING_PTR(res);
11103 memset(p, *f, llen);
11107 while (llen >= fclen) {
11113 memcpy(p, f, llen2);
11117 memcpy(p, RSTRING_PTR(str), size);
11120 memset(p, *f, rlen);
11124 while (rlen >= fclen) {
11130 memcpy(p, f, rlen2);
11134 TERM_FILL(p, termlen);
11135 STR_SET_LEN(res, p-RSTRING_PTR(res));
11156rb_str_ljust(
int argc,
VALUE *argv,
VALUE str)
11158 return rb_str_justify(argc, argv, str,
'l');
11170rb_str_rjust(
int argc,
VALUE *argv,
VALUE str)
11172 return rb_str_justify(argc, argv, str,
'r');
11185rb_str_center(
int argc,
VALUE *argv,
VALUE str)
11187 return rb_str_justify(argc, argv, str,
'c');
11203 sep = get_pat_quoted(sep, 0);
11215 pos = rb_str_index(str, sep, 0);
11216 if (pos < 0)
goto failed;
11221 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11224 return rb_ary_new3(3, str_duplicate(
rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
11238 long pos = RSTRING_LEN(str);
11240 sep = get_pat_quoted(sep, 0);
11253 pos = rb_str_rindex(str, sep, pos);
11262 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11264 return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(
rb_cString, str));
11276rb_str_start_with(
int argc,
VALUE *argv,
VALUE str)
11280 for (i=0; i<argc; i++) {
11281 VALUE tmp = argv[i];
11283 if (rb_reg_start_with_p(tmp, str))
11287 const char *p, *s, *e;
11292 enc = rb_enc_check(str, tmp);
11293 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
11294 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
11295 p = RSTRING_PTR(str);
11298 if (!at_char_right_boundary(p, s, e, enc))
11300 if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
11316rb_str_end_with(
int argc,
VALUE *argv,
VALUE str)
11320 for (i=0; i<argc; i++) {
11321 VALUE tmp = argv[i];
11322 const char *p, *s, *e;
11327 enc = rb_enc_check(str, tmp);
11328 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
11329 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
11330 p = RSTRING_PTR(str);
11333 if (!at_char_boundary(p, s, e, enc))
11335 if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
11351deleted_prefix_length(
VALUE str,
VALUE prefix)
11353 const char *strptr, *prefixptr;
11354 long olen, prefixlen;
11355 rb_encoding *enc = rb_enc_get(str);
11359 if (!is_broken_string(prefix) ||
11360 !rb_enc_asciicompat(enc) ||
11361 !rb_enc_asciicompat(rb_enc_get(prefix))) {
11362 enc = rb_enc_check(str, prefix);
11366 prefixlen = RSTRING_LEN(prefix);
11367 if (prefixlen <= 0)
return 0;
11368 olen = RSTRING_LEN(str);
11369 if (olen < prefixlen)
return 0;
11370 strptr = RSTRING_PTR(str);
11371 prefixptr = RSTRING_PTR(prefix);
11372 if (memcmp(strptr, prefixptr, prefixlen) != 0)
return 0;
11373 if (is_broken_string(prefix)) {
11374 if (!is_broken_string(str)) {
11378 const char *strend = strptr + olen;
11379 const char *after_prefix = strptr + prefixlen;
11380 if (!at_char_right_boundary(strptr, after_prefix, strend, enc)) {
11401rb_str_delete_prefix_bang(
VALUE str,
VALUE prefix)
11404 str_modify_keep_cr(str);
11406 prefixlen = deleted_prefix_length(str, prefix);
11407 if (prefixlen <= 0)
return Qnil;
11421rb_str_delete_prefix(
VALUE str,
VALUE prefix)
11425 prefixlen = deleted_prefix_length(str, prefix);
11426 if (prefixlen <= 0)
return str_duplicate(
rb_cString, str);
11428 return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
11441deleted_suffix_length(
VALUE str,
VALUE suffix)
11443 const char *strptr, *suffixptr;
11444 long olen, suffixlen;
11448 if (is_broken_string(suffix))
return 0;
11449 enc = rb_enc_check(str, suffix);
11452 suffixlen = RSTRING_LEN(suffix);
11453 if (suffixlen <= 0)
return 0;
11454 olen = RSTRING_LEN(str);
11455 if (olen < suffixlen)
return 0;
11456 strptr = RSTRING_PTR(str);
11457 suffixptr = RSTRING_PTR(suffix);
11458 const char *strend = strptr + olen;
11459 const char *before_suffix = strend - suffixlen;
11460 if (memcmp(before_suffix, suffixptr, suffixlen) != 0)
return 0;
11461 if (!at_char_boundary(strptr, before_suffix, strend, enc))
return 0;
11477rb_str_delete_suffix_bang(
VALUE str,
VALUE suffix)
11479 long olen, suffixlen,
len;
11480 str_modifiable(str);
11482 suffixlen = deleted_suffix_length(str, suffix);
11483 if (suffixlen <= 0)
return Qnil;
11485 olen = RSTRING_LEN(str);
11486 str_modify_keep_cr(str);
11487 len = olen - suffixlen;
11488 STR_SET_LEN(str,
len);
11489 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
11505rb_str_delete_suffix(
VALUE str,
VALUE suffix)
11509 suffixlen = deleted_suffix_length(str, suffix);
11510 if (suffixlen <= 0)
return str_duplicate(
rb_cString, str);
11512 return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
11519 rb_raise(
rb_eTypeError,
"value of %"PRIsVALUE
" must be String", rb_id2str(
id));
11525nil_setter_warning(
ID id)
11527 rb_warn_deprecated(
"non-nil '%"PRIsVALUE
"'", NULL, rb_id2str(
id));
11534 if (!
NIL_P(*var)) {
11535 nil_setter_warning(
id);
11542 val = rb_fs_check(val);
11545 "value of %"PRIsVALUE
" must be String or Regexp",
11549 nil_setter_warning(
id);
11566 str_modifiable(str);
11568 rb_encoding *encoding = rb_to_encoding(enc);
11569 int idx = rb_enc_to_index(encoding);
11576 rb_enc_associate_index(str, idx);
11600 if (STR_EMBED_P(str)) {
11601 str2 = str_alloc_embed(
rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
11606 str_replace_shared_without_enc(str2, str);
11608 if (rb_enc_asciicompat(STR_ENC_GET(str))) {
11638rb_str_valid_encoding_p(
VALUE str)
11658rb_str_is_ascii_only_p(
VALUE str)
11668 static const char ellipsis[] =
"...";
11669 const long ellipsislen =
sizeof(ellipsis) - 1;
11670 rb_encoding *
const enc = rb_enc_get(str);
11671 const long blen = RSTRING_LEN(str);
11672 const char *
const p = RSTRING_PTR(str), *e = p + blen;
11673 VALUE estr, ret = 0;
11676 if (
len * rb_enc_mbminlen(enc) >= blen ||
11680 else if (
len <= ellipsislen ||
11681 !(e = rb_enc_step_back(p, e, e,
len = ellipsislen, enc))) {
11682 if (rb_enc_asciicompat(enc)) {
11684 rb_enc_associate(ret, enc);
11691 else if (ret =
rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
11696 rb_enc_from_encoding(enc), 0,
Qnil);
11703str_compat_and_valid(
VALUE str, rb_encoding *enc)
11709 rb_raise(rb_eArgError,
"replacement must be valid byte sequence '%+"PRIsVALUE
"'", str);
11712 rb_encoding *e = STR_ENC_GET(str);
11715 rb_enc_inspect_name(enc), rb_enc_inspect_name(e));
11721static VALUE enc_str_scrub(rb_encoding *enc,
VALUE str,
VALUE repl,
int cr);
11726 rb_encoding *enc = STR_ENC_GET(str);
11731rb_enc_str_scrub(rb_encoding *enc,
VALUE str,
VALUE repl)
11734 if (enc == STR_ENC_GET(str)) {
11739 return enc_str_scrub(enc, str, repl, cr);
11743enc_str_scrub(rb_encoding *enc,
VALUE str,
VALUE repl,
int cr)
11747 const char *rep, *p, *e, *p1, *sp;
11753 rb_raise(rb_eArgError,
"both of block and replacement given");
11760 if (!
NIL_P(repl)) {
11761 repl = str_compat_and_valid(repl, enc);
11764 if (rb_enc_dummy_p(enc)) {
11767 encidx = rb_enc_to_index(enc);
11769#define DEFAULT_REPLACE_CHAR(str) do { \
11770 RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
11771 rep = replace; replen = (int)sizeof(replace); \
11774 slen = RSTRING_LEN(str);
11775 p = RSTRING_PTR(str);
11776 e = RSTRING_END(str);
11780 if (rb_enc_asciicompat(enc)) {
11786 else if (!
NIL_P(repl)) {
11787 rep = RSTRING_PTR(repl);
11788 replen = RSTRING_LEN(repl);
11791 else if (encidx == rb_utf8_encindex()) {
11792 DEFAULT_REPLACE_CHAR(
"\xEF\xBF\xBD");
11796 DEFAULT_REPLACE_CHAR(
"?");
11801 p = search_nonascii(p, e);
11806 int ret = rb_enc_precise_mbclen(p, e, enc);
11819 long clen = rb_enc_mbmaxlen(enc);
11825 if (e - p < clen) clen = e - p;
11832 for (; clen > 1; clen--) {
11833 ret = rb_enc_precise_mbclen(q, q + clen, enc);
11844 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
11845 str_mod_check(str, sp, slen);
11846 repl = str_compat_and_valid(repl, enc);
11853 p = search_nonascii(p, e);
11879 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
11880 str_mod_check(str, sp, slen);
11881 repl = str_compat_and_valid(repl, enc);
11890 long mbminlen = rb_enc_mbminlen(enc);
11894 else if (!
NIL_P(repl)) {
11895 rep = RSTRING_PTR(repl);
11896 replen = RSTRING_LEN(repl);
11898 else if (encidx == ENCINDEX_UTF_16BE) {
11899 DEFAULT_REPLACE_CHAR(
"\xFF\xFD");
11901 else if (encidx == ENCINDEX_UTF_16LE) {
11902 DEFAULT_REPLACE_CHAR(
"\xFD\xFF");
11904 else if (encidx == ENCINDEX_UTF_32BE) {
11905 DEFAULT_REPLACE_CHAR(
"\x00\x00\xFF\xFD");
11907 else if (encidx == ENCINDEX_UTF_32LE) {
11908 DEFAULT_REPLACE_CHAR(
"\xFD\xFF\x00\x00");
11911 DEFAULT_REPLACE_CHAR(
"?");
11915 int ret = rb_enc_precise_mbclen(p, e, enc);
11924 long clen = rb_enc_mbmaxlen(enc);
11928 if (e - p < clen) clen = e - p;
11929 if (clen <= mbminlen * 2) {
11934 for (; clen > mbminlen; clen-=mbminlen) {
11935 ret = rb_enc_precise_mbclen(q, q + clen, enc);
11945 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
11946 str_mod_check(str, sp, slen);
11947 repl = str_compat_and_valid(repl, enc);
11972 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
11973 str_mod_check(str, sp, slen);
11974 repl = str_compat_and_valid(repl, enc);
11995 VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) :
Qnil;
12014str_scrub_bang(
int argc,
VALUE *argv,
VALUE str)
12016 VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) :
Qnil;
12022static ID id_normalize;
12023static ID id_normalized_p;
12024static VALUE mUnicodeNormalize;
12027unicode_normalize_common(
int argc,
VALUE *argv,
VALUE str,
ID id)
12029 static int UnicodeNormalizeRequired = 0;
12032 if (!UnicodeNormalizeRequired) {
12033 rb_require(
"unicode_normalize/normalize.rb");
12034 UnicodeNormalizeRequired = 1;
12037 if (rb_check_arity(argc, 0, 1)) argv2[1] = argv[0];
12038 return rb_funcallv(mUnicodeNormalize,
id, argc+1, argv2);
12049rb_str_unicode_normalize(
int argc,
VALUE *argv,
VALUE str)
12051 return unicode_normalize_common(argc, argv, str, id_normalize);
12065rb_str_unicode_normalize_bang(
int argc,
VALUE *argv,
VALUE str)
12067 return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
12094rb_str_unicode_normalized_p(
int argc,
VALUE *argv,
VALUE str)
12096 return unicode_normalize_common(argc, argv, str, id_normalized_p);
12228#define sym_equal rb_obj_equal
12231sym_printable(
const char *s,
const char *send, rb_encoding *enc)
12235 int c = rb_enc_precise_mbclen(s, send, enc);
12239 c = rb_enc_mbc_to_codepoint(s, send, enc);
12240 if (!rb_enc_isprint(c, enc))
return FALSE;
12247rb_str_symname_p(
VALUE sym)
12252 rb_encoding *resenc = rb_default_internal_encoding();
12254 if (resenc == NULL) resenc = rb_default_external_encoding();
12255 enc = STR_ENC_GET(sym);
12256 ptr = RSTRING_PTR(sym);
12257 len = RSTRING_LEN(sym);
12258 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) ||
len != (
long)strlen(
ptr) ||
12266rb_str_quote_unprintable(
VALUE str)
12271 rb_encoding *resenc;
12274 resenc = rb_default_internal_encoding();
12275 if (resenc == NULL) resenc = rb_default_external_encoding();
12276 enc = STR_ENC_GET(str);
12277 ptr = RSTRING_PTR(str);
12278 len = RSTRING_LEN(str);
12279 if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
12281 return rb_str_escape(str);
12287rb_id_quote_unprintable(
ID id)
12289 VALUE str = rb_id2str(
id);
12290 if (!rb_str_symname_p(str)) {
12291 return rb_str_escape(str);
12309sym_inspect(
VALUE sym)
12316 if (!rb_str_symname_p(str)) {
12318 len = RSTRING_LEN(str);
12319 rb_str_resize(str,
len + 1);
12320 dest = RSTRING_PTR(str);
12321 memmove(dest + 1, dest,
len);
12324 rb_encoding *enc = STR_ENC_GET(str);
12325 VALUE orig_str = str;
12327 len = RSTRING_LEN(orig_str);
12328 str = rb_enc_str_new(0,
len + 1, enc);
12331 ptr = RSTRING_PTR(orig_str);
12332 dest = RSTRING_PTR(str);
12333 memcpy(dest + 1,
ptr,
len);
12353rb_sym_proc_call(
ID mid,
int argc,
const VALUE *argv,
int kw_splat,
VALUE passed_proc)
12358 rb_raise(rb_eArgError,
"no receiver given");
12461 return rb_str_match(
rb_sym2str(sym), other);
12476sym_match_m(
int argc,
VALUE *argv,
VALUE sym)
12478 return rb_str_match_m(argc, argv,
rb_sym2str(sym));
12491sym_match_m_p(
int argc,
VALUE *argv,
VALUE sym)
12493 return rb_str_match_m_p(argc, argv, sym);
12511 return rb_str_aref_m(argc, argv,
rb_sym2str(sym));
12522sym_length(
VALUE sym)
12536sym_empty(
VALUE sym)
12570sym_downcase(
int argc,
VALUE *argv,
VALUE sym)
12586sym_capitalize(
int argc,
VALUE *argv,
VALUE sym)
12602sym_swapcase(
int argc,
VALUE *argv,
VALUE sym)
12616sym_start_with(
int argc,
VALUE *argv,
VALUE sym)
12618 return rb_str_start_with(argc, argv,
rb_sym2str(sym));
12631sym_end_with(
int argc,
VALUE *argv,
VALUE sym)
12633 return rb_str_end_with(argc, argv,
rb_sym2str(sym));
12645sym_encoding(
VALUE sym)
12651string_for_symbol(
VALUE name)
12656 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a symbol nor a string",
12670 name = string_for_symbol(name);
12671 return rb_intern_str(name);
12680 name = string_for_symbol(name);
12704 return rb_fstring(str);
12710 struct RString fake_str = {RBASIC_INIT};
12711 int encidx = ENCINDEX_US_ASCII;
12714 encidx = ENCINDEX_ASCII_8BIT;
12717 VALUE str = setup_fake_str(&fake_str,
ptr,
len, encidx);
12719 return register_fstring(str,
true,
false);
12731 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
12732 rb_enc_autoload(enc);
12735 struct RString fake_str = {RBASIC_INIT};
12736 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
false);
12740rb_enc_literal_str(
const char *
ptr,
long len, rb_encoding *enc)
12742 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
12743 rb_enc_autoload(enc);
12746 struct RString fake_str = {RBASIC_INIT};
12747 VALUE str = register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
true);
12758#if USE_YJIT || USE_ZJIT
12760rb_jit_str_concat_codepoint(
VALUE str,
VALUE codepoint)
12765 if (RB_LIKELY(code >= 0 && code < 0xff)) {
12766 rb_str_buf_cat_byte(str, (
char) code);
12776fstring_set_class_i(
VALUE *str,
void *data)
12780 return ST_CONTINUE;
12788 rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
12848 sym_ascii =
ID2SYM(rb_intern_const(
"ascii"));
12849 sym_turkic =
ID2SYM(rb_intern_const(
"turkic"));
12850 sym_lithuanian =
ID2SYM(rb_intern_const(
"lithuanian"));
12851 sym_fold =
ID2SYM(rb_intern_const(
"fold"));
12945 id_normalize = rb_intern_const(
"normalize");
12946 id_normalized_p = rb_intern_const(
"normalized?");
12955 rb_gc_register_address(&
rb_fs);
#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.
#define ISSPACE
@old{rb_isspace}
#define ISDIGIT
@old{rb_isdigit}
#define ISALPHA
@old{rb_isalpha}
#define TOLOWER
@old{rb_tolower}
#define ISPRINT
@old{rb_isprint}
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt,...)
Identical to rb_sprintf(), except it additionally takes an encoding.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_module(const char *name)
Defines a top-level module.
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 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 xfree
Old name of ruby_xfree.
#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 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 MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
#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 FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
#define DBL2NUM
Old name of rb_float_new.
#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.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
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.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Encoding conversion main routine.
int rb_enc_str_coderange(VALUE str)
Scans the passed string to collect its code range.
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_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...
#define RGENGC_WB_PROTECTED_STRING
This is a compile-time flag to enable/disable write barrier for struct RString.
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().
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 "defaultexternal" 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 "defaultexternal" 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.
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.
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
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_reg_regsub(VALUE repl, VALUE src, struct re_registers *regs, VALUE rexp)
Substitution.
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.
Defines RBIMPL_ATTR_NONSTRING.
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define RBASIC(obj)
Convenient casting macro.
#define DATA_PTR(obj)
Convenient getter macro.
#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...
#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 TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
struct rb_data_type_struct rb_data_type_t
This is the struct that holds necessary info for a struct.
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.
long len
Length of the string, not including terminating NUL character.
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.
ruby_value_type
C-level type of an object.