Ruby 4.1.0dev (2026-08-16 revision ab454af573614ab5521db4be8f22107914dc9f55)
string.c (ab454af573614ab5521db4be8f22107914dc9f55)
1/**********************************************************************
2
3 string.c -
4
5 $Author$
6 created at: Mon Aug 9 17:12:58 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12**********************************************************************/
13
14#include "ruby/internal/config.h"
15
16#include <ctype.h>
17#include <errno.h>
18#include <math.h>
19
20#ifdef HAVE_UNISTD_H
21# include <unistd.h>
22#endif
23
24#include "debug_counter.h"
25#include "encindex.h"
26#include "id.h"
27#include "internal.h"
28#include "internal/array.h"
29#include "internal/bits.h"
30#include "internal/compar.h"
31#include "internal/compilers.h"
32#include "internal/concurrent_set.h"
33#include "internal/encoding.h"
34#include "internal/error.h"
35#include "internal/gc.h"
36#include "internal/hash.h"
37#include "internal/numeric.h"
38#include "internal/object.h"
39#include "internal/proc.h"
40#include "internal/re.h"
41#include "internal/sanitizers.h"
42#include "internal/string.h"
43#include "internal/transcode.h"
44#include "probes.h"
45#include "ruby/encoding.h"
46#include "ruby/re.h"
47#include "ruby/thread.h"
48#include "ruby/util.h"
49#include "ruby/ractor.h"
50#include "ruby_assert.h"
51#include "shape.h"
52#include "vm_core.h"
53#include "vm_sync.h"
54#include "zjit.h"
56
57#if defined HAVE_CRYPT_R
58# if defined HAVE_CRYPT_H
59# include <crypt.h>
60# endif
61#elif !defined HAVE_CRYPT
62# include "missing/crypt.h"
63# define HAVE_CRYPT_R 1
64#endif
65
66#undef rb_str_new
67#undef rb_usascii_str_new
68#undef rb_utf8_str_new
69#undef rb_enc_str_new
70#undef rb_str_new_cstr
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
78#undef rb_str_buf_cat
79#undef rb_str_buf_cat2
80#undef rb_str_cat2
81#undef rb_str_cat_cstr
82#undef rb_fstring_cstr
83
86
87/* Flags of RString
88 *
89 * 0: STR_SHARED (equal to ELTS_SHARED)
90 * The string is shared. The buffer this string points to is owned by
91 * another string (the shared root).
92 * 1: RSTRING_NOEMBED
93 * The string is not embedded. When a string is embedded, the contents
94 * follow the header. When a string is not embedded, the contents is
95 * on a separately allocated buffer.
96 * 2: STR_CHILLED (will be frozen in a future version)
97 * The string was allocated as a literal in a file without an explicit `frozen_string_literal` comment.
98 * It emits a deprecation warning when mutated for the first time.
99 * 4: STR_PRECOMPUTED_HASH
100 * The string is embedded and has its precomputed hashcode stored
101 * after the terminator.
102 * 5: STR_SHARED_ROOT
103 * Other strings may point to the contents of this string. When this
104 * flag is set, STR_SHARED must not be set.
105 * 6: STR_BORROWED
106 * When RSTRING_NOEMBED is set and klass is 0, this string is unsafe
107 * to be unshared by rb_str_tmp_frozen_release.
108 * 7: STR_TMPLOCK
109 * The pointer to the buffer is passed to a system call such as
110 * read(2). Any modification and realloc is prohibited.
111 * 8-9: ENC_CODERANGE
112 * Stores the coderange of the string.
113 * 10-16: ENCODING
114 * Stores the encoding of the string.
115 * 17: RSTRING_FSTR
116 * The string is a fstring. The string is deduplicated in the fstring
117 * table.
118 * 18: STR_NOFREE
119 * Do not free this string's buffer when the string is reclaimed
120 * by the garbage collector. Used for when the string buffer is a C
121 * string literal.
122 * 19: STR_FAKESTR
123 * The string is not allocated or managed by the garbage collector.
124 * Typically, the string object header (struct RString) is temporarily
125 * allocated on C stack.
126 */
127
128#define RUBY_MAX_CHAR_LEN 16
129#define STR_PRECOMPUTED_HASH FL_USER4
130#define STR_SHARED_ROOT FL_USER5
131#define STR_BORROWED FL_USER6
132#define STR_TMPLOCK FL_USER7
133#define STR_NOFREE FL_USER18
134
135#define STR_SET_NOEMBED(str) do {\
136 FL_SET((str), STR_NOEMBED);\
137 FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\
138} while (0)
139#define STR_SET_EMBED(str) FL_UNSET((str), STR_NOEMBED | STR_SHARED | STR_NOFREE)
140
141#define STR_SET_LEN(str, n) do { \
142 RSTRING(str)->len = (n); \
143} while (0)
144
145#define TERM_LEN(str) (rb_str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
146#define TERM_FILL(ptr, termlen) do {\
147 char *const term_fill_ptr = (ptr);\
148 const int term_fill_len = (termlen);\
149 *term_fill_ptr = '\0';\
150 if (UNLIKELY(term_fill_len > 1))\
151 memset(term_fill_ptr, 0, term_fill_len);\
152} while (0)
153
154#define RESIZE_CAPA(str,capacity) do {\
155 const int termlen = TERM_LEN(str);\
156 RESIZE_CAPA_TERM(str,capacity,termlen);\
157} while (0)
158#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
159 if (STR_EMBED_P(str)) {\
160 if (str_embed_capa(str) < capacity + termlen) {\
161 char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
162 const long tlen = RSTRING_LEN(str);\
163 memcpy(tmp, RSTRING_PTR(str), str_embed_capa(str));\
164 RSTRING(str)->as.heap.ptr = tmp;\
165 RSTRING(str)->len = tlen;\
166 STR_SET_NOEMBED(str);\
167 RSTRING(str)->as.heap.aux.capa = (capacity);\
168 }\
169 }\
170 else {\
171 RUBY_ASSERT(!FL_TEST((str), STR_SHARED)); \
172 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
173 (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
174 RSTRING(str)->as.heap.aux.capa = (capacity);\
175 }\
176} while (0)
177
178#define STR_SET_SHARED(str, shared_str) do { \
179 if (!FL_TEST(str, STR_FAKESTR)) { \
180 RUBY_ASSERT(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \
181 RUBY_ASSERT(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \
182 RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
183 FL_SET((str), STR_SHARED); \
184 rb_gc_register_pinning_obj(str); \
185 FL_SET((shared_str), STR_SHARED_ROOT); \
186 if (RBASIC_CLASS((shared_str)) == 0) /* for CoW-friendliness */ \
187 FL_SET_RAW((shared_str), STR_BORROWED); \
188 } \
189} while (0)
190
191#define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr)
192#define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str))
193/* TODO: include the terminator size in capa. */
194
195#define STR_ENC_GET(str) get_encoding(str)
196
197static inline bool
198zero_filled(const char *s, int n)
199{
200 for (; n > 0; --n) {
201 if (*s++) return false;
202 }
203 return true;
204}
205
206#if !defined SHARABLE_MIDDLE_SUBSTRING
207# define SHARABLE_MIDDLE_SUBSTRING 0
208#endif
209
210static inline bool
211SHARABLE_SUBSTRING_P(VALUE str, long beg, long len)
212{
213#if SHARABLE_MIDDLE_SUBSTRING
214 return true;
215#else
216 long end = beg + len;
217 long source_len = RSTRING_LEN(str);
218 return end == source_len || zero_filled(RSTRING_PTR(str) + end, TERM_LEN(str));
219#endif
220}
221
222static inline long
223str_embed_capa(VALUE str)
224{
225 return rb_obj_shape_slot_size(str) - offsetof(struct RString, as.embed.ary);
226}
227
228bool
229rb_str_reembeddable_p(VALUE str)
230{
231 return !FL_TEST(str, STR_NOFREE|STR_SHARED_ROOT|STR_SHARED);
232}
233
234/* True when other strings read this string's bytes out of its own slot, so the slot
235 * contents must stay valid for as long as the object does. */
236bool
237rb_str_embedded_shared_root_p(VALUE str)
238{
239 return STR_EMBED_P(str) && FL_TEST(str, STR_SHARED_ROOT);
240}
241
242static inline size_t
243rb_str_embed_size(long capa, long termlen)
244{
245 size_t size = offsetof(struct RString, as.embed.ary) + capa + termlen;
246 if (size < sizeof(struct RString)) size = sizeof(struct RString);
247 return size;
248}
249
250size_t
251rb_str_size_as_embedded(VALUE str)
252{
253 size_t real_size;
254 if (STR_EMBED_P(str)) {
255 size_t capa = RSTRING(str)->len;
256 if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) capa += sizeof(st_index_t);
257
258 real_size = rb_str_embed_size(capa, TERM_LEN(str));
259 }
260 /* if the string is not currently embedded, but it can be embedded, how
261 * much space would it require */
262 else if (rb_str_reembeddable_p(str)) {
263 size_t capa = RSTRING(str)->as.heap.aux.capa;
264 if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) capa += sizeof(st_index_t);
265
266 real_size = rb_str_embed_size(capa, TERM_LEN(str));
267 }
268 else {
269 real_size = sizeof(struct RString);
270 }
271
272 return real_size;
273}
274
275static inline bool
276STR_EMBEDDABLE_P(long len, long termlen)
277{
278 return rb_gc_size_allocatable_p(rb_str_embed_size(len, termlen));
279}
280
281/* Substrings and duplicated strings that need a slot larger than this are shared
282 * instead of copied. Larger slots hold fewer objects per page and trigger GC
283 * more often, which outweighs the copy they save; see [Feature #22186] for the
284 * benchmarks. */
285#define STR_COPY_MAX_EMBED_SIZE 256
286
287static VALUE str_replace_shared_without_enc(VALUE str2, VALUE str);
288static VALUE str_new_frozen(VALUE klass, VALUE orig);
289static VALUE str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding);
290static VALUE str_new_static(VALUE klass, const char *ptr, long len, int encindex);
291static VALUE str_new(VALUE klass, const char *ptr, long len);
292static void str_make_independent_expand(VALUE str, long len, long expand, const int termlen);
293static inline void str_modifiable(VALUE str);
294static VALUE rb_str_downcase(int argc, VALUE *argv, VALUE str);
295static inline VALUE str_alloc_embed(VALUE klass, size_t capa);
296
297static inline void
298str_make_independent(VALUE str)
299{
300 long len = RSTRING_LEN(str);
301 int termlen = TERM_LEN(str);
302 str_make_independent_expand((str), len, 0L, termlen);
303}
304
305static inline int str_dependent_p(VALUE str);
306
307void
308rb_str_make_independent(VALUE str)
309{
310 if (str_dependent_p(str)) {
311 str_make_independent(str);
312 }
313}
314
315void
316rb_str_make_embedded(VALUE str)
317{
318 RUBY_ASSERT(rb_str_reembeddable_p(str));
319 RUBY_ASSERT(!STR_EMBED_P(str));
320
321 int termlen = TERM_LEN(str);
322 char *buf = RSTRING(str)->as.heap.ptr;
323 long old_capa = RSTRING(str)->as.heap.aux.capa + termlen;
324 long len = RSTRING(str)->len;
325
326 STR_SET_EMBED(str);
327 STR_SET_LEN(str, len);
328
329 if (len > 0) {
330 memcpy(RSTRING_PTR(str), buf, len);
331 SIZED_FREE_N(buf, old_capa);
332 }
333
334 TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
335}
336
337void
338rb_debug_rstring_null_ptr(const char *func)
339{
340 fprintf(stderr, "%s is returning NULL!! "
341 "SIGSEGV is highly expected to follow immediately.\n"
342 "If you could reproduce, attach your debugger here, "
343 "and look at the passed string.\n",
344 func);
345}
346
347/* symbols for [up|down|swap]case/capitalize options */
348static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
349
350static rb_encoding *
351get_encoding(VALUE str)
352{
353 return rb_enc_from_index(ENCODING_GET(str));
354}
355
356static void
357mustnot_broken(VALUE str)
358{
359 if (is_broken_string(str)) {
360 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
361 }
362}
363
364static void
365mustnot_wchar(VALUE str)
366{
367 rb_encoding *enc = STR_ENC_GET(str);
368 if (rb_enc_mbminlen(enc) > 1) {
369 rb_raise(rb_eArgError, "wide char encoding: %s", rb_enc_name(enc));
370 }
371}
372
373static VALUE register_fstring(VALUE str, bool copy, bool force_precompute_hash);
374
375#if SIZEOF_LONG == SIZEOF_VOIDP
376#define PRECOMPUTED_FAKESTR_HASH 1
377#else
378#endif
379
380static inline bool
381BARE_STRING_P(VALUE str)
382{
383 return RBASIC_CLASS(str) == rb_cString && !rb_obj_shape_has_ivars(str);
384}
385
386static inline st_index_t
387str_do_hash(VALUE str)
388{
389 st_index_t h = rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str));
390 int e = RSTRING_LEN(str) ? ENCODING_GET(str) : 0;
391 if (e && !is_ascii_string(str)) {
392 h = rb_hash_end(rb_hash_uint32(h, (uint32_t)e));
393 }
394 return h;
395}
396
397static VALUE
398str_store_precomputed_hash(VALUE str, st_index_t hash)
399{
400 RUBY_ASSERT(!FL_TEST_RAW(str, STR_PRECOMPUTED_HASH));
401 RUBY_ASSERT(STR_EMBED_P(str));
402
403#if RUBY_DEBUG
404 size_t used_bytes = (RSTRING_LEN(str) + TERM_LEN(str));
405 size_t free_bytes = str_embed_capa(str) - used_bytes;
406 RUBY_ASSERT(free_bytes >= sizeof(st_index_t));
407#endif
408
409 memcpy(RSTRING_END(str) + TERM_LEN(str), &hash, sizeof(hash));
410
411 FL_SET(str, STR_PRECOMPUTED_HASH);
412
413 return str;
414}
415
416VALUE
417rb_fstring(VALUE str)
418{
419 VALUE fstr;
420 int bare;
421
422 Check_Type(str, T_STRING);
423
424 if (FL_TEST(str, RSTRING_FSTR))
425 return str;
426
427 bare = BARE_STRING_P(str);
428 if (!bare) {
429 if (STR_EMBED_P(str)) {
430 OBJ_FREEZE(str);
431 return str;
432 }
433
434 if (FL_TEST_RAW(str, STR_SHARED_ROOT | STR_SHARED) == STR_SHARED_ROOT) {
436 return str;
437 }
438 }
439
440 if (!FL_TEST_RAW(str, FL_FREEZE | STR_NOFREE | STR_CHILLED))
441 rb_str_resize(str, RSTRING_LEN(str));
442
443 fstr = register_fstring(str, false, false);
444
445 if (!bare) {
446 str_replace_shared_without_enc(str, fstr);
447 OBJ_FREEZE(str);
448 return str;
449 }
450 return fstr;
451}
452
453static VALUE fstring_table_obj;
454
455static VALUE
456fstring_concurrent_set_hash(VALUE str)
457{
458#ifdef PRECOMPUTED_FAKESTR_HASH
459 st_index_t h;
460 if (FL_TEST_RAW(str, STR_FAKESTR)) {
461 // register_fstring precomputes the hash and stores it in capa for fake strings
462 h = (st_index_t)RSTRING(str)->as.heap.aux.capa;
463 }
464 else {
465 h = rb_str_hash(str);
466 }
467 // rb_str_hash doesn't include the encoding for ascii only strings, so
468 // we add it to avoid common collisions between `:sym.name` (ASCII) and `"sym"` (UTF-8)
469 return (VALUE)rb_hash_end(rb_hash_uint32(h, (uint32_t)ENCODING_GET_INLINED(str)));
470#else
471 return (VALUE)rb_str_hash(str);
472#endif
473}
474
475static bool
476fstring_concurrent_set_cmp(VALUE a, VALUE b)
477{
478 long alen, blen;
479 const char *aptr, *bptr;
480
483
484 RSTRING_GETMEM(a, aptr, alen);
485 RSTRING_GETMEM(b, bptr, blen);
486 return (alen == blen &&
487 ENCODING_GET(a) == ENCODING_GET(b) &&
488 memcmp(aptr, bptr, alen) == 0);
489}
490
492 bool copy;
493 bool force_precompute_hash;
494};
495
496static VALUE
497fstring_concurrent_set_create(VALUE str, void *data)
498{
499 struct fstr_create_arg *arg = data;
500
501 // Unless the string is empty or binary, its coderange has been precomputed.
502 int coderange = ENC_CODERANGE(str);
503
504 if (FL_TEST_RAW(str, STR_FAKESTR)) {
505 if (arg->copy) {
506 VALUE new_str;
507 long len = RSTRING_LEN(str);
508 long capa = len + sizeof(st_index_t);
509 int term_len = TERM_LEN(str);
510
511 if (arg->force_precompute_hash && STR_EMBEDDABLE_P(capa, term_len)) {
512 new_str = str_alloc_embed(rb_cString, capa + term_len);
513 memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str), len);
514 STR_SET_LEN(new_str, RSTRING_LEN(str));
515 TERM_FILL(RSTRING_END(new_str), TERM_LEN(str));
516 rb_enc_copy(new_str, str);
517 str_store_precomputed_hash(new_str, str_do_hash(str));
518 }
519 else {
520 new_str = str_new(rb_cString, RSTRING(str)->as.heap.ptr, RSTRING(str)->len);
521 rb_enc_copy(new_str, str);
522#ifdef PRECOMPUTED_FAKESTR_HASH
523 if (rb_str_capacity(new_str) >= RSTRING_LEN(str) + term_len + sizeof(st_index_t)) {
524 str_store_precomputed_hash(new_str, (st_index_t)RSTRING(str)->as.heap.aux.capa);
525 }
526#endif
527 }
528 str = new_str;
529 }
530 else {
531 str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr,
532 RSTRING(str)->len,
533 ENCODING_GET(str));
534 }
535 OBJ_FREEZE(str);
536 }
537 else {
538 if (!OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
539 str = str_new_frozen(rb_cString, str);
540 }
541 if (STR_SHARED_P(str)) { /* str should not be shared */
542 /* shared substring */
543 str_make_independent(str);
545 }
546 if (!BARE_STRING_P(str)) {
547 str = str_new_frozen(rb_cString, str);
548 }
549 }
550
551 ENC_CODERANGE_SET(str, coderange);
552 RBASIC(str)->flags |= RSTRING_FSTR;
553 if (!RB_OBJ_SHAREABLE_P(str)) {
554 RB_OBJ_SET_SHAREABLE(str);
555 }
556 RUBY_ASSERT((rb_gc_verify_shareable(str), 1));
559 RUBY_ASSERT(!FL_TEST_RAW(str, STR_FAKESTR));
560 RUBY_ASSERT(!rb_obj_shape_has_ivars(str));
562 RUBY_ASSERT(!rb_objspace_garbage_object_p(str));
563
564 return str;
565}
566
567static const struct rb_concurrent_set_funcs fstring_concurrent_set_funcs = {
568 .hash = fstring_concurrent_set_hash,
569 .cmp = fstring_concurrent_set_cmp,
570 .create = fstring_concurrent_set_create,
571 .free = NULL,
572};
573
574void
575Init_fstring_table(void)
576{
577 fstring_table_obj = rb_concurrent_set_new(&fstring_concurrent_set_funcs, 8192);
578 rb_gc_register_address(&fstring_table_obj);
579}
580
581static VALUE
582register_fstring(VALUE str, bool copy, bool force_precompute_hash)
583{
584 struct fstr_create_arg args = {
585 .copy = copy,
586 .force_precompute_hash = force_precompute_hash
587 };
588
589#if SIZEOF_VOIDP == SIZEOF_LONG
590 if (FL_TEST_RAW(str, STR_FAKESTR)) {
591 // if the string hasn't been interned, we'll need the hash twice, so we
592 // compute it once and store it in capa
593 RSTRING(str)->as.heap.aux.capa = (long)str_do_hash(str);
594 }
595#endif
596
597 VALUE result = rb_concurrent_set_find_or_insert(&fstring_table_obj, str, &args);
598
599 RUBY_ASSERT(!rb_objspace_garbage_object_p(result));
601 RUBY_ASSERT(OBJ_FROZEN(result));
603 RUBY_ASSERT((rb_gc_verify_shareable(result), 1));
604 RUBY_ASSERT(!FL_TEST_RAW(result, STR_FAKESTR));
606
607 return result;
608}
609
610bool
611rb_obj_is_fstring_table(VALUE obj)
612{
613 ASSERT_vm_locking();
614
615 return obj == fstring_table_obj;
616}
617
618void
619rb_gc_free_fstring(VALUE obj)
620{
621 ASSERT_vm_locking_with_barrier();
622
623 RUBY_ASSERT(FL_TEST(obj, RSTRING_FSTR));
625 RUBY_ASSERT(!FL_TEST(obj, STR_SHARED));
626
627 rb_concurrent_set_delete_by_identity(fstring_table_obj, obj);
628
629 RB_DEBUG_COUNTER_INC(obj_str_fstr);
630
631 FL_UNSET(obj, RSTRING_FSTR);
632}
633
634void
635rb_fstring_foreach_with_replace(int (*callback)(VALUE *str, void *data), void *data)
636{
637 if (fstring_table_obj) {
638 rb_concurrent_set_foreach_with_replace(fstring_table_obj, callback, data);
639 }
640}
641
642static VALUE
643setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx)
644{
645 fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR;
646 RBASIC_SET_FULL_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
647
648 if (!name) {
650 name = "";
651 }
652
653 ENCODING_SET_INLINED((VALUE)fake_str, encidx);
654
655 RBASIC_SET_CLASS_RAW((VALUE)fake_str, rb_cString);
656 fake_str->len = len;
657 fake_str->as.heap.ptr = (char *)name;
658 fake_str->as.heap.aux.capa = len;
659 return (VALUE)fake_str;
660}
661
662/*
663 * set up a fake string which refers a static string literal.
664 */
665VALUE
666rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
667{
668 return setup_fake_str(fake_str, name, len, rb_enc_to_index(enc));
669}
670
671/*
672 * rb_fstring_new and rb_fstring_cstr family create or lookup a frozen
673 * shared string which refers a static string literal. `ptr` must
674 * point a constant string.
675 */
676VALUE
677rb_fstring_new(const char *ptr, long len)
678{
679 struct RString fake_str = {RBASIC_INIT};
680 return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), false, false);
681}
682
683VALUE
684rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc)
685{
686 struct RString fake_str = {RBASIC_INIT};
687 return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), false, false);
688}
689
690VALUE
691rb_fstring_cstr(const char *ptr)
692{
693 return rb_fstring_new(ptr, strlen(ptr));
694}
695
696static inline bool
697single_byte_optimizable(VALUE str)
698{
699 int encindex = ENCODING_GET(str);
700 switch (encindex) {
701 case ENCINDEX_ASCII_8BIT:
702 case ENCINDEX_US_ASCII:
703 return true;
704 case ENCINDEX_UTF_8:
705 // For UTF-8 it's worth scanning the string coderange when unknown.
706 return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT;
707 }
708 /* Conservative. It may be ENC_CODERANGE_UNKNOWN. */
709 if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) {
710 return true;
711 }
712
713 if (rb_enc_mbmaxlen(rb_enc_from_index(encindex)) == 1) {
714 return true;
715 }
716
717 /* Conservative. Possibly single byte.
718 * "\xa1" in Shift_JIS for example. */
719 return false;
720}
721
723
724static inline const char *
725search_nonascii(const char *p, const char *e)
726{
727 const char *s, *t;
728
729 if (p < e && !ISASCII(*p)) {
730 return p;
731 }
732
733#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
734# if SIZEOF_UINTPTR_T == 8
735# define NONASCII_MASK UINT64_C(0x8080808080808080)
736# elif SIZEOF_UINTPTR_T == 4
737# define NONASCII_MASK UINT32_C(0x80808080)
738# else
739# error "don't know what to do."
740# endif
741#else
742# if SIZEOF_UINTPTR_T == 8
743# define NONASCII_MASK ((uintptr_t)0x80808080UL << 32 | (uintptr_t)0x80808080UL)
744# elif SIZEOF_UINTPTR_T == 4
745# define NONASCII_MASK 0x80808080UL /* or...? */
746# else
747# error "don't know what to do."
748# endif
749#endif
750
751 if (UNALIGNED_WORD_ACCESS || e - p >= SIZEOF_VOIDP) {
752#if !UNALIGNED_WORD_ACCESS
753 if ((uintptr_t)p % SIZEOF_VOIDP) {
754 int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
755 p += l;
756 switch (l) {
757 default: UNREACHABLE;
758#if SIZEOF_VOIDP > 4
759 case 7: if (p[-7]&0x80) return p-7;
760 case 6: if (p[-6]&0x80) return p-6;
761 case 5: if (p[-5]&0x80) return p-5;
762 case 4: if (p[-4]&0x80) return p-4;
763#endif
764 case 3: if (p[-3]&0x80) return p-3;
765 case 2: if (p[-2]&0x80) return p-2;
766 case 1: if (p[-1]&0x80) return p-1;
767 case 0: break;
768 }
769 }
770#endif
771#if defined(HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED) &&! UNALIGNED_WORD_ACCESS
772#define aligned_ptr(value) \
773 __builtin_assume_aligned((value), sizeof(uintptr_t))
774#else
775#define aligned_ptr(value) (value)
776#endif
777 s = aligned_ptr(p);
778 t = (e - (SIZEOF_VOIDP-1));
779#undef aligned_ptr
780 for (;s < t; s += sizeof(uintptr_t)) {
781 uintptr_t word;
782 memcpy(&word, s, sizeof(word));
783 if (word & NONASCII_MASK) {
784#ifdef WORDS_BIGENDIAN
785 return (const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
786#else
787 return (const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
788#endif
789 }
790 }
791 p = (const char *)s;
792 }
793
794 switch (e - p) {
795 default: UNREACHABLE;
796#if SIZEOF_VOIDP > 4
797 case 7: if (e[-7]&0x80) return e-7;
798 case 6: if (e[-6]&0x80) return e-6;
799 case 5: if (e[-5]&0x80) return e-5;
800 case 4: if (e[-4]&0x80) return e-4;
801#endif
802 case 3: if (e[-3]&0x80) return e-3;
803 case 2: if (e[-2]&0x80) return e-2;
804 case 1: if (e[-1]&0x80) return e-1;
805 case 0: return NULL;
806 }
807}
808
809static int
810coderange_scan(const char *p, long len, rb_encoding *enc)
811{
812 const char *e = p + len;
813
814 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
815 /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
816 p = search_nonascii(p, e);
818 }
819
820 if (rb_enc_asciicompat(enc)) {
821 p = search_nonascii(p, e);
822 if (!p) return ENC_CODERANGE_7BIT;
823 for (;;) {
824 int ret = rb_enc_precise_mbclen(p, e, enc);
826 p += MBCLEN_CHARFOUND_LEN(ret);
827 if (p == e) break;
828 p = search_nonascii(p, e);
829 if (!p) break;
830 }
831 }
832 else {
833 while (p < e) {
834 int ret = rb_enc_precise_mbclen(p, e, enc);
836 p += MBCLEN_CHARFOUND_LEN(ret);
837 }
838 }
839 return ENC_CODERANGE_VALID;
840}
841
842long
843rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding *enc, int *cr)
844{
845 const char *p = s;
846
847 if (*cr == ENC_CODERANGE_BROKEN)
848 return e - s;
849
850 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
851 /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
852 if (*cr == ENC_CODERANGE_VALID) return e - s;
853 p = search_nonascii(p, e);
855 return e - s;
856 }
857 else if (rb_enc_asciicompat(enc)) {
858 p = search_nonascii(p, e);
859 if (!p) {
860 if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT;
861 return e - s;
862 }
863 for (;;) {
864 int ret = rb_enc_precise_mbclen(p, e, enc);
865 if (!MBCLEN_CHARFOUND_P(ret)) {
867 return p - s;
868 }
869 p += MBCLEN_CHARFOUND_LEN(ret);
870 if (p == e) break;
871 p = search_nonascii(p, e);
872 if (!p) break;
873 }
874 }
875 else {
876 while (p < e) {
877 int ret = rb_enc_precise_mbclen(p, e, enc);
878 if (!MBCLEN_CHARFOUND_P(ret)) {
880 return p - s;
881 }
882 p += MBCLEN_CHARFOUND_LEN(ret);
883 }
884 }
886 return e - s;
887}
888
889static inline void
890str_enc_copy(VALUE str1, VALUE str2)
891{
892 rb_enc_set_index(str1, ENCODING_GET(str2));
893}
894
895/* Like str_enc_copy, but does not check frozen status of str1.
896 * You should use this only if you're certain that str1 is not frozen. */
897static inline void
898str_enc_copy_direct(VALUE str1, VALUE str2)
899{
900 int inlined_encoding = RB_ENCODING_GET_INLINED(str2);
901 if (inlined_encoding == ENCODING_INLINE_MAX) {
902 rb_enc_set_index(str1, rb_enc_get_index(str2));
903 }
904 else {
905 ENCODING_SET_INLINED(str1, inlined_encoding);
906 }
907}
908
909static void
910rb_enc_cr_str_copy_for_substr(VALUE dest, VALUE src)
911{
912 /* this function is designed for copying encoding and coderange
913 * from src to new string "dest" which is made from the part of src.
914 */
915 str_enc_copy(dest, src);
916 if (RSTRING_LEN(dest) == 0) {
917 if (!rb_enc_asciicompat(STR_ENC_GET(src)))
919 else
921 return;
922 }
923 switch (ENC_CODERANGE(src)) {
926 break;
928 if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
929 search_nonascii(RSTRING_PTR(dest), RSTRING_END(dest)))
931 else
933 break;
934 default:
935 break;
936 }
937}
938
939static void
940rb_enc_cr_str_exact_copy(VALUE dest, VALUE src)
941{
942 str_enc_copy(dest, src);
944}
945
946static int
947enc_coderange_scan(VALUE str, rb_encoding *enc)
948{
949 return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc);
950}
951
952int
953rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc)
954{
955 return enc_coderange_scan(str, enc);
956}
957
958int
959rbimpl_enc_str_coderange_scan(VALUE str)
960{
961 int cr = enc_coderange_scan(str, get_encoding(str));
962 ENC_CODERANGE_SET(str, cr);
963 return cr;
964}
965
966#undef rb_enc_str_coderange
967int
968rb_enc_str_coderange(VALUE str)
969{
970 int cr = ENC_CODERANGE(str);
971
972 if (cr == ENC_CODERANGE_UNKNOWN) {
973 cr = rbimpl_enc_str_coderange_scan(str);
974 }
975 return cr;
976}
977#define rb_enc_str_coderange rb_enc_str_coderange_inline
978
979static inline bool
980rb_enc_str_asciicompat(VALUE str)
981{
982 int encindex = ENCODING_GET_INLINED(str);
983 return rb_str_encindex_fastpath(encindex) || rb_enc_asciicompat(rb_enc_get_from_index(encindex));
984}
985
986int
988{
989 switch(ENC_CODERANGE(str)) {
991 return rb_enc_str_asciicompat(str) && is_ascii_string(str);
993 return true;
994 default:
995 return false;
996 }
997}
998
999static inline void
1000str_mod_check(VALUE s, const char *p, long len)
1001{
1002 if (RSTRING_PTR(s) != p || RSTRING_LEN(s) != len){
1003 rb_raise(rb_eRuntimeError, "string modified");
1004 }
1005}
1006
1007static size_t
1008str_capacity(VALUE str, const int termlen)
1009{
1010 if (STR_EMBED_P(str)) {
1011 return str_embed_capa(str) - termlen;
1012 }
1013 else if (FL_ANY_RAW(str, STR_SHARED|STR_NOFREE)) {
1014 return RSTRING(str)->len;
1015 }
1016 else {
1017 return RSTRING(str)->as.heap.aux.capa;
1018 }
1019}
1020
1021size_t
1023{
1024 return str_capacity(str, TERM_LEN(str));
1025}
1026
1027static inline void
1028must_not_null(const char *ptr)
1029{
1030 if (!ptr) {
1031 rb_raise(rb_eArgError, "NULL pointer given");
1032 }
1033}
1034
1035static inline VALUE
1036str_alloc_embed(VALUE klass, size_t capa)
1037{
1038 size_t size = rb_str_embed_size(capa, 0);
1039 RUBY_ASSERT(size > 0);
1040 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
1041
1042 NEWOBJ_OF(str, struct RString, klass, T_STRING, size);
1043
1044 str->len = 0;
1045 str->as.embed.ary[0] = 0;
1046
1047 return (VALUE)str;
1048}
1049
1050static inline VALUE
1051str_alloc_heap(VALUE klass)
1052{
1053 NEWOBJ_OF(str, struct RString, klass, T_STRING | STR_NOEMBED, sizeof(struct RString));
1054
1055 str->len = 0;
1056 str->as.heap.aux.capa = 0;
1057 str->as.heap.ptr = NULL;
1058
1059 return (VALUE)str;
1060}
1061
1062static inline VALUE
1063empty_str_alloc(VALUE klass)
1064{
1065 RUBY_DTRACE_CREATE_HOOK(STRING, 0);
1066 VALUE str = str_alloc_embed(klass, 0);
1067 memset(RSTRING(str)->as.embed.ary, 0, str_embed_capa(str));
1069 return str;
1070}
1071
1072static VALUE
1073str_enc_new(VALUE klass, const char *ptr, long len, rb_encoding *enc)
1074{
1075 VALUE str;
1076
1077 if (len < 0) {
1078 rb_raise(rb_eArgError, "negative string size (or size too big)");
1079 }
1080
1081 if (enc == NULL) {
1082 enc = rb_ascii8bit_encoding();
1083 }
1084
1085 RUBY_DTRACE_CREATE_HOOK(STRING, len);
1086
1087 int termlen = rb_enc_mbminlen(enc);
1088
1089 if (STR_EMBEDDABLE_P(len, termlen)) {
1090 str = str_alloc_embed(klass, len + termlen);
1091 if (len == 0) {
1092 ENC_CODERANGE_SET(str, rb_enc_asciicompat(enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);
1093 }
1094 }
1095 else {
1096 str = str_alloc_heap(klass);
1097 RSTRING(str)->as.heap.aux.capa = len;
1098 /* :FIXME: @shyouhei guesses `len + termlen` is guaranteed to never
1099 * integer overflow. If we can STATIC_ASSERT that, the following
1100 * mul_add_mul can be reverted to a simple ALLOC_N. */
1101 RSTRING(str)->as.heap.ptr =
1102 rb_xmalloc_mul_add_mul(sizeof(char), len, sizeof(char), termlen);
1103 }
1104
1105 rb_enc_raw_set(str, enc);
1106
1107 if (ptr) {
1108 memcpy(RSTRING_PTR(str), ptr, len);
1109 }
1110 else {
1111 memset(RSTRING_PTR(str), 0, len);
1112 }
1113
1114 STR_SET_LEN(str, len);
1115 TERM_FILL(RSTRING_PTR(str) + len, termlen);
1116 return str;
1117}
1118
1119static VALUE
1120str_new(VALUE klass, const char *ptr, long len)
1121{
1122 return str_enc_new(klass, ptr, len, rb_ascii8bit_encoding());
1123}
1124
1125VALUE
1126rb_str_new(const char *ptr, long len)
1127{
1128 return str_new(rb_cString, ptr, len);
1129}
1130
1131VALUE
1132rb_usascii_str_new(const char *ptr, long len)
1133{
1134 return str_enc_new(rb_cString, ptr, len, rb_usascii_encoding());
1135}
1136
1137VALUE
1138rb_utf8_str_new(const char *ptr, long len)
1139{
1140 return str_enc_new(rb_cString, ptr, len, rb_utf8_encoding());
1141}
1142
1143VALUE
1144rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
1145{
1146 return str_enc_new(rb_cString, ptr, len, enc);
1147}
1148
1149VALUE
1151{
1152 must_not_null(ptr);
1153 /* rb_str_new_cstr() can take pointer from non-malloc-generated
1154 * memory regions, and that cannot be detected by the MSAN. Just
1155 * trust the programmer that the argument passed here is a sane C
1156 * string. */
1157 __msan_unpoison_string(ptr);
1158 return rb_str_new(ptr, strlen(ptr));
1159}
1160
1161VALUE
1163{
1164 return rb_enc_str_new_cstr(ptr, rb_usascii_encoding());
1165}
1166
1167VALUE
1169{
1170 return rb_enc_str_new_cstr(ptr, rb_utf8_encoding());
1171}
1172
1173VALUE
1175{
1176 must_not_null(ptr);
1177 if (rb_enc_mbminlen(enc) != 1) {
1178 rb_raise(rb_eArgError, "wchar encoding given");
1179 }
1180 return rb_enc_str_new(ptr, strlen(ptr), enc);
1181}
1182
1183static VALUE
1184str_new_static(VALUE klass, const char *ptr, long len, int encindex)
1185{
1186 VALUE str;
1187
1188 if (len < 0) {
1189 rb_raise(rb_eArgError, "negative string size (or size too big)");
1190 }
1191
1192 if (!ptr) {
1193 str = str_enc_new(klass, ptr, len, rb_enc_from_index(encindex));
1194 }
1195 else {
1196 RUBY_DTRACE_CREATE_HOOK(STRING, len);
1197 str = str_alloc_heap(klass);
1198 RSTRING(str)->len = len;
1199 RSTRING(str)->as.heap.ptr = (char *)ptr;
1200 RSTRING(str)->as.heap.aux.capa = len;
1201 RBASIC(str)->flags |= STR_NOFREE;
1202 rb_enc_associate_index(str, encindex);
1203 }
1204 return str;
1205}
1206
1207VALUE
1208rb_str_new_static(const char *ptr, long len)
1209{
1210 return str_new_static(rb_cString, ptr, len, 0);
1211}
1212
1213VALUE
1215{
1216 return str_new_static(rb_cString, ptr, len, ENCINDEX_US_ASCII);
1217}
1218
1219VALUE
1221{
1222 return str_new_static(rb_cString, ptr, len, ENCINDEX_UTF_8);
1223}
1224
1225VALUE
1227{
1228 return str_new_static(rb_cString, ptr, len, rb_enc_to_index(enc));
1229}
1230
1231static VALUE str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
1232 rb_encoding *from, rb_encoding *to,
1233 int ecflags, VALUE ecopts);
1234
1235static inline bool
1236is_enc_ascii_string(VALUE str, rb_encoding *enc)
1237{
1238 int encidx = rb_enc_to_index(enc);
1239 if (rb_enc_get_index(str) == encidx)
1240 return is_ascii_string(str);
1241 return enc_coderange_scan(str, enc) == ENC_CODERANGE_7BIT;
1242}
1243
1244VALUE
1245rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
1246{
1247 long len;
1248 const char *ptr;
1249 VALUE newstr;
1250
1251 if (!to) return str;
1252 if (!from) from = rb_enc_get(str);
1253 if (from == to) return str;
1254 if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) ||
1255 rb_is_ascii8bit_enc(to)) {
1256 if (STR_ENC_GET(str) != to) {
1257 str = rb_str_dup(str);
1258 rb_enc_associate(str, to);
1259 }
1260 return str;
1261 }
1262
1263 RSTRING_GETMEM(str, ptr, len);
1264 newstr = str_cat_conv_enc_opts(rb_str_buf_new(len), 0, ptr, len,
1265 from, to, ecflags, ecopts);
1266 if (NIL_P(newstr)) {
1267 /* some error, return original */
1268 return str;
1269 }
1270 return newstr;
1271}
1272
1273VALUE
1274rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
1275 rb_encoding *from, int ecflags, VALUE ecopts)
1276{
1277 long olen;
1278
1279 olen = RSTRING_LEN(newstr);
1280 if (ofs < -olen || olen < ofs)
1281 rb_raise(rb_eIndexError, "index %ld out of string", ofs);
1282 if (ofs < 0) ofs += olen;
1283 if (!from) {
1284 STR_SET_LEN(newstr, ofs);
1285 return rb_str_cat(newstr, ptr, len);
1286 }
1287
1288 rb_str_modify(newstr);
1289 return str_cat_conv_enc_opts(newstr, ofs, ptr, len, from,
1290 rb_enc_get(newstr),
1291 ecflags, ecopts);
1292}
1293
1294VALUE
1295rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc)
1296{
1297 STR_SET_LEN(str, 0);
1298 rb_enc_associate(str, enc);
1299 rb_str_cat(str, ptr, len);
1300 return str;
1301}
1302
1303static VALUE
1304str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
1305 rb_encoding *from, rb_encoding *to,
1306 int ecflags, VALUE ecopts)
1307{
1308 rb_econv_t *ec;
1310 long olen;
1311 VALUE econv_wrapper;
1312 const unsigned char *start, *sp;
1313 unsigned char *dest, *dp;
1314 size_t converted_output = (size_t)ofs;
1315
1316 olen = rb_str_capacity(newstr);
1317
1318 econv_wrapper = rb_obj_alloc(rb_cEncodingConverter);
1319 RBASIC_CLEAR_CLASS(econv_wrapper);
1320 ec = rb_econv_open_opts(from->name, to->name, ecflags, ecopts);
1321 if (!ec) return Qnil;
1322 DATA_PTR(econv_wrapper) = ec;
1323
1324 sp = (unsigned char*)ptr;
1325 start = sp;
1326 while ((dest = (unsigned char*)RSTRING_PTR(newstr)),
1327 (dp = dest + converted_output),
1328 (ret = rb_econv_convert(ec, &sp, start + len, &dp, dest + olen, 0)),
1330 /* destination buffer short */
1331 size_t converted_input = sp - start;
1332 size_t rest = len - converted_input;
1333 converted_output = dp - dest;
1334 rb_str_set_len(newstr, converted_output);
1335 if (converted_input && converted_output &&
1336 rest < (LONG_MAX / converted_output)) {
1337 rest = (rest * converted_output) / converted_input;
1338 }
1339 else {
1340 rest = olen;
1341 }
1342 olen += rest < 2 ? 2 : rest;
1343 rb_str_resize(newstr, olen);
1344 }
1345 DATA_PTR(econv_wrapper) = 0;
1346 RB_GC_GUARD(econv_wrapper);
1347 rb_econv_close(ec);
1348 switch (ret) {
1349 case econv_finished:
1350 len = dp - (unsigned char*)RSTRING_PTR(newstr);
1351 rb_str_set_len(newstr, len);
1352 rb_enc_associate(newstr, to);
1353 return newstr;
1354
1355 default:
1356 return Qnil;
1357 }
1358}
1359
1360VALUE
1362{
1363 return rb_str_conv_enc_opts(str, from, to, 0, Qnil);
1364}
1365
1366VALUE
1368{
1369 rb_encoding *ienc;
1370 VALUE str;
1371 const int eidx = rb_enc_to_index(eenc);
1372
1373 if (!ptr) {
1374 return rb_enc_str_new(ptr, len, eenc);
1375 }
1376
1377 /* ASCII-8BIT case, no conversion */
1378 if ((eidx == rb_ascii8bit_encindex()) ||
1379 (eidx == rb_usascii_encindex() && search_nonascii(ptr, ptr + len))) {
1380 return rb_str_new(ptr, len);
1381 }
1382 /* no default_internal or same encoding, no conversion */
1383 ienc = rb_default_internal_encoding();
1384 if (!ienc || eenc == ienc) {
1385 return rb_enc_str_new(ptr, len, eenc);
1386 }
1387 /* ASCII compatible, and ASCII only string, no conversion in
1388 * default_internal */
1389 if ((eidx == rb_ascii8bit_encindex()) ||
1390 (eidx == rb_usascii_encindex()) ||
1391 (rb_enc_asciicompat(eenc) && !search_nonascii(ptr, ptr + len))) {
1392 return rb_enc_str_new(ptr, len, ienc);
1393 }
1394 /* convert from the given encoding to default_internal */
1395 str = rb_enc_str_new(NULL, 0, ienc);
1396 /* when the conversion failed for some reason, just ignore the
1397 * default_internal and result in the given encoding as-is. */
1398 if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, eenc, 0, Qnil))) {
1399 rb_str_initialize(str, ptr, len, eenc);
1400 }
1401 return str;
1402}
1403
1404VALUE
1405rb_external_str_with_enc(VALUE str, rb_encoding *eenc)
1406{
1407 int eidx = rb_enc_to_index(eenc);
1408 if (eidx == rb_usascii_encindex() &&
1409 !is_ascii_string(str)) {
1410 rb_enc_associate_index(str, rb_ascii8bit_encindex());
1411 return str;
1412 }
1413 rb_enc_associate_index(str, eidx);
1414 return rb_str_conv_enc(str, eenc, rb_default_internal_encoding());
1415}
1416
1417VALUE
1418rb_external_str_new(const char *ptr, long len)
1419{
1420 return rb_external_str_new_with_enc(ptr, len, rb_default_external_encoding());
1421}
1422
1423VALUE
1425{
1426 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_default_external_encoding());
1427}
1428
1429VALUE
1430rb_locale_str_new(const char *ptr, long len)
1431{
1432 return rb_external_str_new_with_enc(ptr, len, rb_locale_encoding());
1433}
1434
1435VALUE
1437{
1438 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_locale_encoding());
1439}
1440
1441VALUE
1443{
1444 return rb_external_str_new_with_enc(ptr, len, rb_filesystem_encoding());
1445}
1446
1447VALUE
1449{
1450 return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_filesystem_encoding());
1451}
1452
1453VALUE
1455{
1456 return rb_str_export_to_enc(str, rb_default_external_encoding());
1457}
1458
1459VALUE
1461{
1462 return rb_str_export_to_enc(str, rb_locale_encoding());
1463}
1464
1465VALUE
1467{
1468 return rb_str_conv_enc(str, STR_ENC_GET(str), enc);
1469}
1470
1471static VALUE
1472str_replace_shared_without_enc(VALUE str2, VALUE str)
1473{
1474 const int termlen = TERM_LEN(str);
1475 char *ptr;
1476 long len;
1477
1478 RSTRING_GETMEM(str, ptr, len);
1479 if (str_embed_capa(str2) >= len + termlen) {
1480 char *ptr2 = RSTRING(str2)->as.embed.ary;
1481 STR_SET_EMBED(str2);
1482 memcpy(ptr2, RSTRING_PTR(str), len);
1483 TERM_FILL(ptr2+len, termlen);
1484 }
1485 else {
1486 VALUE root;
1487 if (STR_SHARED_P(str)) {
1488 root = RSTRING(str)->as.heap.aux.shared;
1489 RSTRING_GETMEM(str, ptr, len);
1490 }
1491 else {
1492 root = rb_str_new_frozen(str);
1493 RSTRING_GETMEM(root, ptr, len);
1494 }
1495 RUBY_ASSERT(OBJ_FROZEN(root));
1496
1497 if (!STR_EMBED_P(str2) && !FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) {
1498 if (FL_TEST_RAW(str2, STR_SHARED_ROOT)) {
1499 rb_fatal("about to free a possible shared root");
1500 }
1501 char *ptr2 = STR_HEAP_PTR(str2);
1502 if (ptr2 != ptr) {
1503 SIZED_FREE_N(ptr2, STR_HEAP_SIZE(str2));
1504 }
1505 }
1506 FL_SET(str2, STR_NOEMBED);
1507 RSTRING(str2)->as.heap.ptr = ptr;
1508 STR_SET_SHARED(str2, root);
1509 }
1510
1511 STR_SET_LEN(str2, len);
1512
1513 return str2;
1514}
1515
1516static VALUE
1517str_replace_shared(VALUE str2, VALUE str)
1518{
1519 str_replace_shared_without_enc(str2, str);
1520 rb_enc_cr_str_exact_copy(str2, str);
1521 return str2;
1522}
1523
1524static VALUE
1525str_new_shared(VALUE klass, VALUE str)
1526{
1527 return str_replace_shared(str_alloc_heap(klass), str);
1528}
1529
1530VALUE
1532{
1533 return str_new_shared(rb_obj_class(str), str);
1534}
1535
1536VALUE
1538{
1539 if (RB_FL_TEST_RAW(orig, FL_FREEZE | STR_CHILLED) == FL_FREEZE) return orig;
1540 return str_new_frozen(rb_obj_class(orig), orig);
1541}
1542
1543static VALUE
1544rb_str_new_frozen_String(VALUE orig)
1545{
1546 if (OBJ_FROZEN(orig) && rb_obj_class(orig) == rb_cString) return orig;
1547 return str_new_frozen(rb_cString, orig);
1548}
1549
1550
1551VALUE
1552rb_str_frozen_bare_string(VALUE orig)
1553{
1554 if (RB_LIKELY(BARE_STRING_P(orig) && OBJ_FROZEN_RAW(orig))) return orig;
1555 return str_new_frozen(rb_cString, orig);
1556}
1557
1558VALUE
1559rb_str_tmp_frozen_acquire(VALUE orig)
1560{
1561 if (OBJ_FROZEN_RAW(orig)) return orig;
1562 return str_new_frozen_buffer(0, orig, FALSE);
1563}
1564
1565VALUE
1566rb_str_tmp_frozen_no_embed_acquire(VALUE orig)
1567{
1568 if (OBJ_FROZEN_RAW(orig) && !STR_EMBED_P(orig) && !rb_str_reembeddable_p(orig)) return orig;
1569 if (STR_SHARED_P(orig) && !STR_EMBED_P(RSTRING(orig)->as.heap.aux.shared)) return rb_str_tmp_frozen_acquire(orig);
1570
1571 VALUE str = str_alloc_heap(0);
1572 OBJ_FREEZE(str);
1573 /* Always set the STR_SHARED_ROOT to ensure it does not get re-embedded. */
1574 FL_SET(str, STR_SHARED_ROOT);
1575
1576 size_t capa = str_capacity(orig, TERM_LEN(orig));
1577
1578 /* If the string is embedded then we want to create a copy that is heap
1579 * allocated. If the string is shared then the shared root must be
1580 * embedded, so we want to create a copy. If the string is a shared root
1581 * then it must be embedded, so we want to create a copy. */
1582 if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
1583 RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(sizeof(char), capa, sizeof(char), TERM_LEN(orig));
1584 memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), capa);
1585 }
1586 else {
1587 /* orig must be heap allocated and not shared, so we can safely transfer
1588 * the pointer to str. */
1589 RSTRING(str)->as.heap.ptr = RSTRING(orig)->as.heap.ptr;
1590 RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
1591 RBASIC(orig)->flags &= ~STR_NOFREE;
1592 STR_SET_SHARED(orig, str);
1593 if (RB_OBJ_SHAREABLE_P(orig)) {
1594 RB_OBJ_SET_SHAREABLE(str);
1595 RUBY_ASSERT((rb_gc_verify_shareable(str), 1));
1596 }
1597 }
1598
1599 RSTRING(str)->len = RSTRING(orig)->len;
1600 RSTRING(str)->as.heap.aux.capa = capa + (TERM_LEN(orig) - TERM_LEN(str));
1601
1602 return str;
1603}
1604
1605void
1606rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
1607{
1608 if (RBASIC_CLASS(tmp) != 0)
1609 return;
1610
1611 if (STR_EMBED_P(tmp)) {
1613 }
1614 else if (FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_TMPLOCK &&
1615 !OBJ_FROZEN_RAW(orig)) {
1616 VALUE shared = RSTRING(orig)->as.heap.aux.shared;
1617
1618 if (shared == tmp && !FL_TEST_RAW(tmp, STR_BORROWED)) {
1619 RUBY_ASSERT(RSTRING(orig)->as.heap.ptr == RSTRING(tmp)->as.heap.ptr);
1620 RUBY_ASSERT(RSTRING_LEN(orig) == RSTRING_LEN(tmp));
1621
1622 /* Unshare orig since the root (tmp) only has this one child. */
1623 FL_UNSET_RAW(orig, STR_SHARED);
1624 RSTRING(orig)->as.heap.aux.capa = RSTRING(tmp)->as.heap.aux.capa;
1625 RBASIC(orig)->flags |= RBASIC(tmp)->flags & STR_NOFREE;
1627
1628 /* Make tmp embedded and empty so it is safe for sweeping. */
1629 STR_SET_EMBED(tmp);
1630 STR_SET_LEN(tmp, 0);
1631 }
1632 }
1633}
1634
1635static VALUE
1636str_new_frozen(VALUE klass, VALUE orig)
1637{
1638 return str_new_frozen_buffer(klass, orig, TRUE);
1639}
1640
1641static VALUE
1642heap_str_make_shared(VALUE klass, VALUE orig)
1643{
1644 RUBY_ASSERT(!STR_EMBED_P(orig));
1645 RUBY_ASSERT(!STR_SHARED_P(orig));
1647
1648 VALUE str = str_alloc_heap(klass);
1649 STR_SET_LEN(str, RSTRING_LEN(orig));
1650 RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
1651 RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa;
1652 RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
1653 RBASIC(orig)->flags &= ~STR_NOFREE;
1654 STR_SET_SHARED(orig, str);
1655 if (klass == 0)
1656 FL_UNSET_RAW(str, STR_BORROWED);
1657 return str;
1658}
1659
1660static VALUE
1661str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
1662{
1663 VALUE str;
1664
1665 long len = RSTRING_LEN(orig);
1666 rb_encoding *enc = copy_encoding ? STR_ENC_GET(orig) : rb_ascii8bit_encoding();
1667 int termlen = copy_encoding ? TERM_LEN(orig) : 1;
1668
1669 if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(len, termlen)) {
1670 str = str_enc_new(klass, RSTRING_PTR(orig), len, enc);
1671 RUBY_ASSERT(STR_EMBED_P(str));
1672 }
1673 else {
1674 if (FL_TEST_RAW(orig, STR_SHARED)) {
1675 VALUE shared = RSTRING(orig)->as.heap.aux.shared;
1676 long ofs = RSTRING(orig)->as.heap.ptr - RSTRING_PTR(shared);
1677 long rest = RSTRING_LEN(shared) - ofs - RSTRING_LEN(orig);
1678 RUBY_ASSERT(ofs >= 0);
1679 RUBY_ASSERT(rest >= 0);
1680 RUBY_ASSERT(ofs + rest <= RSTRING_LEN(shared));
1682
1683 if ((ofs > 0) || (rest > 0) ||
1684 (klass != RBASIC(shared)->klass) ||
1685 ENCODING_GET(shared) != ENCODING_GET(orig)) {
1686 str = str_new_shared(klass, shared);
1687 RUBY_ASSERT(!STR_EMBED_P(str));
1688 RSTRING(str)->as.heap.ptr += ofs;
1689 STR_SET_LEN(str, RSTRING_LEN(str) - (ofs + rest));
1690 }
1691 else {
1692 if (RBASIC_CLASS(shared) == 0)
1693 FL_SET_RAW(shared, STR_BORROWED);
1694 return shared;
1695 }
1696 }
1697 else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
1698 str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig));
1699 STR_SET_EMBED(str);
1700 memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
1701 STR_SET_LEN(str, RSTRING_LEN(orig));
1702 ENC_CODERANGE_SET(str, ENC_CODERANGE(orig));
1703 TERM_FILL(RSTRING_END(str), TERM_LEN(orig));
1704 }
1705 else {
1706 if (RB_OBJ_SHAREABLE_P(orig)) {
1707 str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
1708 }
1709 else {
1710 str = heap_str_make_shared(klass, orig);
1711 }
1712 }
1713 }
1714
1715 if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
1716 OBJ_FREEZE(str);
1717 return str;
1718}
1719
1720VALUE
1721rb_str_new_with_class(VALUE obj, const char *ptr, long len)
1722{
1723 return str_enc_new(rb_obj_class(obj), ptr, len, STR_ENC_GET(obj));
1724}
1725
1726static VALUE
1727str_new_empty_String(VALUE str)
1728{
1729 VALUE v = rb_str_new(0, 0);
1730 rb_enc_copy(v, str);
1731 return v;
1732}
1733
1734#define STR_BUF_MIN_SIZE 63
1735
1736VALUE
1738{
1739 if (STR_EMBEDDABLE_P(capa, 1)) {
1740 return str_alloc_embed(rb_cString, capa + 1);
1741 }
1742
1743 VALUE str = str_alloc_heap(rb_cString);
1744
1745 RSTRING(str)->as.heap.aux.capa = capa;
1746 RSTRING(str)->as.heap.ptr = ALLOC_N(char, (size_t)capa + 1);
1747 RSTRING(str)->as.heap.ptr[0] = '\0';
1748
1749 return str;
1750}
1751
1752VALUE
1754{
1755 VALUE str;
1756 long len = strlen(ptr);
1757
1758 str = rb_str_buf_new(len);
1759 rb_str_buf_cat(str, ptr, len);
1760
1761 return str;
1762}
1763
1764VALUE
1766{
1767 return str_new(0, 0, len);
1768}
1769
1770void
1772{
1773 if (STR_EMBED_P(str)) {
1774 RB_DEBUG_COUNTER_INC(obj_str_embed);
1775 }
1776 else if (FL_TEST(str, STR_SHARED | STR_NOFREE)) {
1777 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_SHARED));
1778 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared, FL_TEST(str, STR_NOFREE));
1779 }
1780 else {
1781 RB_DEBUG_COUNTER_INC(obj_str_ptr);
1782 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
1783 }
1784}
1785
1786size_t
1787rb_str_memsize(VALUE str)
1788{
1789 if (FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
1790 return STR_HEAP_SIZE(str);
1791 }
1792 else {
1793 return 0;
1794 }
1795}
1796
1797VALUE
1799{
1800 return rb_convert_type_with_id(str, T_STRING, "String", idTo_str);
1801}
1802
1803static inline void str_discard(VALUE str);
1804static void str_shared_replace(VALUE str, VALUE str2);
1805
1806void
1808{
1809 if (str != str2) str_shared_replace(str, str2);
1810}
1811
1812static void
1813str_shared_replace(VALUE str, VALUE str2)
1814{
1815 rb_encoding *enc;
1816 int cr;
1817 int termlen;
1818
1819 RUBY_ASSERT(str2 != str);
1820 enc = STR_ENC_GET(str2);
1821 cr = ENC_CODERANGE(str2);
1822 str_discard(str);
1823 termlen = rb_enc_mbminlen(enc);
1824
1825 STR_SET_LEN(str, RSTRING_LEN(str2));
1826
1827 if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) {
1828 STR_SET_EMBED(str);
1829 memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (size_t)RSTRING_LEN(str2) + termlen);
1830 rb_enc_associate(str, enc);
1831 ENC_CODERANGE_SET(str, cr);
1832 }
1833 else {
1834 if (STR_EMBED_P(str2)) {
1835 RUBY_ASSERT(!FL_TEST(str2, STR_SHARED));
1836 long len = RSTRING_LEN(str2);
1837 RUBY_ASSERT(len + termlen <= str_embed_capa(str2));
1838
1839 char *new_ptr = ALLOC_N(char, len + termlen);
1840 memcpy(new_ptr, RSTRING(str2)->as.embed.ary, len + termlen);
1841 RSTRING(str2)->as.heap.ptr = new_ptr;
1842 STR_SET_LEN(str2, len);
1843 RSTRING(str2)->as.heap.aux.capa = len;
1844 STR_SET_NOEMBED(str2);
1845 }
1846
1847 STR_SET_NOEMBED(str);
1848 FL_UNSET(str, STR_SHARED);
1849 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1850
1851 if (FL_TEST(str2, STR_SHARED)) {
1852 VALUE shared = RSTRING(str2)->as.heap.aux.shared;
1853 STR_SET_SHARED(str, shared);
1854 }
1855 else {
1856 RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
1857 }
1858
1859 /* abandon str2 */
1860 STR_SET_EMBED(str2);
1861 RSTRING_PTR(str2)[0] = 0;
1862 STR_SET_LEN(str2, 0);
1863 rb_enc_associate(str, enc);
1864 ENC_CODERANGE_SET(str, cr);
1865 }
1866}
1867
1868VALUE
1870{
1871 VALUE str;
1872
1873 if (RB_TYPE_P(obj, T_STRING)) {
1874 return obj;
1875 }
1876 str = rb_funcall(obj, idTo_s, 0);
1877 return rb_obj_as_string_result(str, obj);
1878}
1879
1880VALUE
1881rb_obj_as_string_result(VALUE str, VALUE obj)
1882{
1883 if (!RB_TYPE_P(str, T_STRING))
1884 return rb_any_to_s(obj);
1885 return str;
1886}
1887
1888static VALUE
1889str_replace(VALUE str, VALUE str2)
1890{
1891 long len;
1892
1893 len = RSTRING_LEN(str2);
1894 if (STR_SHARED_P(str2)) {
1895 VALUE shared = RSTRING(str2)->as.heap.aux.shared;
1897 STR_SET_NOEMBED(str);
1898 STR_SET_LEN(str, len);
1899 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1900 STR_SET_SHARED(str, shared);
1901 rb_enc_cr_str_exact_copy(str, str2);
1902 }
1903 else {
1904 str_replace_shared(str, str2);
1905 }
1906
1907 return str;
1908}
1909
1910static inline VALUE
1911ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t capa)
1912{
1913 size_t size = rb_str_embed_size(capa, 0);
1914 RUBY_ASSERT(size > 0);
1915 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
1916
1917 EC_NEWOBJ_OF(str, struct RString, klass, T_STRING, size, ec);
1918
1919 str->len = 0;
1920
1921 return (VALUE)str;
1922}
1923
1924static inline VALUE
1925ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass)
1926{
1927 EC_NEWOBJ_OF(str, struct RString, klass, T_STRING | STR_NOEMBED, sizeof(struct RString), ec);
1928
1929 str->as.heap.aux.capa = 0;
1930 str->as.heap.ptr = NULL;
1931
1932 return (VALUE)str;
1933}
1934
1935static inline void
1936str_duplicate_setup_encoding(VALUE str, VALUE dup, VALUE flags)
1937{
1938 int encidx = 0;
1939 if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX<<ENCODING_SHIFT)) {
1940 encidx = rb_enc_get_index(str);
1941 flags &= ~ENCODING_MASK;
1942 }
1943 FL_SET_RAW(dup, flags & ~FL_FREEZE);
1944 if (encidx) rb_enc_associate_index(dup, encidx);
1945}
1946
1947static const VALUE flag_mask = ENC_CODERANGE_MASK | ENCODING_MASK | FL_FREEZE;
1948
1949static inline void
1950str_duplicate_setup_embed(VALUE klass, VALUE str, VALUE dup)
1951{
1952 VALUE flags = FL_TEST_RAW(str, flag_mask);
1953 long len = RSTRING_LEN(str);
1954
1955 RUBY_ASSERT(STR_EMBED_P(dup));
1956 RUBY_ASSERT(str_embed_capa(dup) >= len + TERM_LEN(str));
1957 MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + TERM_LEN(str));
1958 STR_SET_LEN(dup, RSTRING_LEN(str));
1959 str_duplicate_setup_encoding(str, dup, flags);
1960}
1961
1962static inline void
1963str_duplicate_setup_heap(VALUE klass, VALUE str, VALUE dup)
1964{
1965 VALUE flags = FL_TEST_RAW(str, flag_mask);
1966 VALUE root = str;
1967 if (FL_TEST_RAW(str, STR_SHARED)) {
1968 root = RSTRING(str)->as.heap.aux.shared;
1969 }
1970 else if (UNLIKELY(!OBJ_FROZEN_RAW(str))) {
1971 root = str = str_new_frozen(klass, str);
1972 flags = FL_TEST_RAW(str, flag_mask);
1973 }
1974 RUBY_ASSERT(!STR_SHARED_P(root));
1976
1977 RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
1978 FL_SET_RAW(dup, RSTRING_NOEMBED);
1979 STR_SET_SHARED(dup, root);
1980 flags |= RSTRING_NOEMBED | STR_SHARED;
1981
1982 STR_SET_LEN(dup, RSTRING_LEN(str));
1983 str_duplicate_setup_encoding(str, dup, flags);
1984}
1985
1986static inline VALUE
1987str_duplicate(VALUE klass, VALUE str)
1988{
1989 VALUE dup;
1990 if (STR_EMBED_P(str) && rb_str_embed_size(RSTRING_LEN(str), 1) <= STR_COPY_MAX_EMBED_SIZE) {
1991 dup = str_alloc_embed(klass, RSTRING_LEN(str) + TERM_LEN(str));
1992
1993 str_duplicate_setup_embed(klass, str, dup);
1994 }
1995 else {
1996 dup = str_alloc_heap(klass);
1997
1998 str_duplicate_setup_heap(klass, str, dup);
1999 }
2000
2001 return dup;
2002}
2003
2004VALUE
2006{
2007 return str_duplicate(rb_obj_class(str), str);
2008}
2009
2010/* :nodoc: */
2011VALUE
2012rb_str_dup_m(VALUE str)
2013{
2014 if (LIKELY(BARE_STRING_P(str))) {
2015 return str_duplicate(rb_cString, str);
2016 }
2017 else {
2018 return rb_obj_dup(str);
2019 }
2020}
2021
2022VALUE
2024{
2025 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2026 return str_duplicate(rb_cString, str);
2027}
2028
2029VALUE
2030rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled)
2031{
2032 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2033 VALUE new_str, klass = rb_cString;
2034
2035 if (!(chilled && RTEST(rb_ivar_defined(str, id_debug_created_info))) && STR_EMBED_P(str)) {
2036 new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
2037 str_duplicate_setup_embed(klass, str, new_str);
2038 }
2039 else {
2040 new_str = ec_str_alloc_heap(ec, klass);
2041 str_duplicate_setup_heap(klass, str, new_str);
2042 }
2043 if (chilled) {
2044 FL_SET_RAW(new_str, STR_CHILLED);
2045 }
2046 return new_str;
2047}
2048
2049#if USE_ZJIT
2050bool
2051rb_zjit_str_resurrect_fastpath(VALUE str, bool chilled, size_t *size_out,
2052 VALUE *flags_out,
2053 long *len_out, size_t *byte_size_out)
2054{
2055 if (chilled && RTEST(rb_ivar_defined(str, id_debug_created_info))) return false;
2056
2057 if (!STR_EMBED_P(str)) return false;
2058
2059 long len = RSTRING_LEN(str);
2060 long termlen = TERM_LEN(str);
2061 size_t size = rb_str_embed_size(len + termlen, 0);
2062 if (!rb_gc_size_allocatable_p(size)) return false;
2063
2064 VALUE flags = FL_TEST_RAW(str, flag_mask);
2065
2066 if ((flags & ENCODING_MASK) == ((VALUE)ENCODING_INLINE_MAX << ENCODING_SHIFT)) {
2067 return false;
2068 }
2069
2070 flags &= ~FL_FREEZE;
2071 flags |= T_STRING;
2072 if (chilled) flags |= STR_CHILLED;
2073
2074 *size_out = size;
2075 *flags_out = flags;
2076 *len_out = len;
2077 *byte_size_out = (size_t)(len + termlen);
2078 return true;
2079}
2080#endif
2081
2082VALUE
2083rb_str_with_debug_created_info(VALUE str, VALUE path, int line)
2084{
2085 VALUE debug_info = rb_ary_new_from_args(2, path, INT2FIX(line));
2086 if (OBJ_FROZEN_RAW(str)) str = rb_str_dup(str);
2087 rb_ivar_set(str, id_debug_created_info, rb_ary_freeze(debug_info));
2088 FL_SET_RAW(str, STR_CHILLED);
2089 return rb_str_freeze(str);
2090}
2091
2092/*
2093 * The documentation block below uses an include (instead of inline text)
2094 * because the included text has non-ASCII characters (which are not allowed in a C file).
2095 */
2096
2097/*
2098 *
2099 * call-seq:
2100 * String.new(string = ''.encode(Encoding::ASCII_8BIT) , **options) -> new_string
2101 *
2102 * :include: doc/string/new.rdoc
2103 *
2104 */
2105
2106static VALUE
2107rb_str_init(int argc, VALUE *argv, VALUE str)
2108{
2109 static ID keyword_ids[2];
2110 VALUE orig, opt, venc, vcapa;
2111 VALUE kwargs[2];
2112 rb_encoding *enc = 0;
2113 int n;
2114
2115 if (!keyword_ids[0]) {
2116 keyword_ids[0] = rb_id_encoding();
2117 CONST_ID(keyword_ids[1], "capacity");
2118 }
2119
2120 n = rb_scan_args(argc, argv, "01:", &orig, &opt);
2121 if (!NIL_P(opt)) {
2122 rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
2123 venc = kwargs[0];
2124 vcapa = kwargs[1];
2125 if (!UNDEF_P(venc) && !NIL_P(venc)) {
2126 enc = rb_to_encoding(venc);
2127 }
2128 if (!UNDEF_P(vcapa) && !NIL_P(vcapa)) {
2129 long capa = NUM2LONG(vcapa);
2130 long len = 0;
2131 int termlen = enc ? rb_enc_mbminlen(enc) : 1;
2132
2133 if (capa < STR_BUF_MIN_SIZE) {
2134 capa = STR_BUF_MIN_SIZE;
2135 }
2136 if (n == 1) {
2137 StringValue(orig);
2138 len = RSTRING_LEN(orig);
2139 if (capa < len) {
2140 capa = len;
2141 }
2142 if (orig == str) n = 0;
2143 }
2144 str_modifiable(str);
2145 if (STR_EMBED_P(str) || FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2146 /* make noembed always */
2147 const size_t size = (size_t)capa + termlen;
2148 const char *const old_ptr = RSTRING_PTR(str);
2149 const size_t osize = RSTRING_LEN(str) + TERM_LEN(str);
2150 char *new_ptr = ALLOC_N(char, size);
2151 if (STR_EMBED_P(str)) RUBY_ASSERT((long)osize <= str_embed_capa(str));
2152 memcpy(new_ptr, old_ptr, osize < size ? osize : size);
2153 FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE);
2154 RSTRING(str)->as.heap.ptr = new_ptr;
2155 }
2156 else if (STR_HEAP_SIZE(str) != (size_t)capa + termlen) {
2157 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
2158 (size_t)capa + termlen, STR_HEAP_SIZE(str));
2159 }
2160 STR_SET_LEN(str, len);
2161 TERM_FILL(&RSTRING(str)->as.heap.ptr[len], termlen);
2162 if (n == 1) {
2163 memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), len);
2164 rb_enc_cr_str_exact_copy(str, orig);
2165 }
2166 FL_SET(str, STR_NOEMBED);
2167 RSTRING(str)->as.heap.aux.capa = capa;
2168 }
2169 else if (n == 1) {
2170 rb_str_replace(str, orig);
2171 }
2172 if (enc) {
2173 rb_enc_associate(str, enc);
2175 }
2176 }
2177 else if (n == 1) {
2178 rb_str_replace(str, orig);
2179 }
2180 return str;
2181}
2182
2183/* :nodoc: */
2184static VALUE
2185rb_str_s_new(int argc, VALUE *argv, VALUE klass)
2186{
2187 if (klass != rb_cString) {
2188 return rb_class_new_instance_pass_kw(argc, argv, klass);
2189 }
2190
2191 static ID keyword_ids[2];
2192 VALUE orig, opt, encoding = Qnil, capacity = Qnil;
2193 VALUE kwargs[2];
2194 rb_encoding *enc = NULL;
2195
2196 int n = rb_scan_args(argc, argv, "01:", &orig, &opt);
2197 if (NIL_P(opt)) {
2198 return rb_class_new_instance_pass_kw(argc, argv, klass);
2199 }
2200
2201 keyword_ids[0] = rb_id_encoding();
2202 CONST_ID(keyword_ids[1], "capacity");
2203 rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
2204 encoding = kwargs[0];
2205 capacity = kwargs[1];
2206
2207 if (n == 1) {
2208 orig = StringValue(orig);
2209 }
2210 else {
2211 orig = Qnil;
2212 }
2213
2214 if (UNDEF_P(encoding)) {
2215 if (!NIL_P(orig)) {
2216 encoding = rb_obj_encoding(orig);
2217 }
2218 }
2219
2220 if (!UNDEF_P(encoding)) {
2221 enc = rb_to_encoding(encoding);
2222 }
2223
2224 // If capacity is nil, we're basically just duping `orig`.
2225 if (UNDEF_P(capacity)) {
2226 if (NIL_P(orig)) {
2227 VALUE empty_str = str_new(klass, "", 0);
2228 if (enc) {
2229 rb_enc_associate(empty_str, enc);
2230 }
2231 return empty_str;
2232 }
2233 VALUE copy = str_duplicate(klass, orig);
2234 rb_enc_associate(copy, enc);
2235 ENC_CODERANGE_CLEAR(copy);
2236 return copy;
2237 }
2238
2239 long capa = 0;
2240 capa = NUM2LONG(capacity);
2241 if (capa < 0) {
2242 capa = 0;
2243 }
2244
2245 if (!NIL_P(orig)) {
2246 long orig_capa = rb_str_capacity(orig);
2247 if (orig_capa > capa) {
2248 capa = orig_capa;
2249 }
2250 }
2251
2252 VALUE str = str_enc_new(klass, NULL, capa, enc);
2253 STR_SET_LEN(str, 0);
2254 TERM_FILL(RSTRING_PTR(str), enc ? rb_enc_mbmaxlen(enc) : 1);
2255
2256 if (!NIL_P(orig)) {
2257 rb_str_buf_append(str, orig);
2258 }
2259
2260 return str;
2261}
2262
2263#ifdef NONASCII_MASK
2264#define is_utf8_lead_byte(c) (((c)&0xC0) != 0x80)
2265
2266/*
2267 * UTF-8 leading bytes have either 0xxxxxxx or 11xxxxxx
2268 * bit representation. (see https://en.wikipedia.org/wiki/UTF-8)
2269 * Therefore, the following pseudocode can detect UTF-8 leading bytes.
2270 *
2271 * if (!(byte & 0x80))
2272 * byte |= 0x40; // turn on bit6
2273 * return ((byte>>6) & 1); // bit6 represent whether this byte is leading or not.
2274 *
2275 * This function calculates whether a byte is leading or not for all bytes
2276 * in the argument word by concurrently using the above logic, and then
2277 * adds up the number of leading bytes in the word.
2278 */
2279static inline uintptr_t
2280count_utf8_lead_bytes_with_word(const uintptr_t *s)
2281{
2282 uintptr_t d = *s;
2283
2284 /* Transform so that bit0 indicates whether we have a UTF-8 leading byte or not. */
2285 d = (d>>6) | (~d>>7);
2286 d &= NONASCII_MASK >> 7;
2287
2288 /* Gather all bytes. */
2289#if defined(HAVE_BUILTIN___BUILTIN_POPCOUNT) && defined(__POPCNT__)
2290 /* use only if it can use POPCNT */
2291 return rb_popcount_intptr(d);
2292#else
2293 d += (d>>8);
2294 d += (d>>16);
2295# if SIZEOF_VOIDP == 8
2296 d += (d>>32);
2297# endif
2298 return (d&0xF);
2299#endif
2300}
2301#endif
2302
2303static inline long
2304enc_strlen(const char *p, const char *e, rb_encoding *enc, int cr)
2305{
2306 long c;
2307 const char *q;
2308
2309 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
2310 long diff = (long)(e - p);
2311 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2312 }
2313#ifdef NONASCII_MASK
2314 else if (cr == ENC_CODERANGE_VALID && enc == rb_utf8_encoding()) {
2315 uintptr_t len = 0;
2316 if ((int)sizeof(uintptr_t) * 2 < e - p) {
2317 const uintptr_t *s, *t;
2318 const uintptr_t lowbits = sizeof(uintptr_t) - 1;
2319 s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
2320 t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
2321 while (p < (const char *)s) {
2322 if (is_utf8_lead_byte(*p)) len++;
2323 p++;
2324 }
2325 while (s < t) {
2326 len += count_utf8_lead_bytes_with_word(s);
2327 s++;
2328 }
2329 p = (const char *)s;
2330 }
2331 while (p < e) {
2332 if (is_utf8_lead_byte(*p)) len++;
2333 p++;
2334 }
2335 return (long)len;
2336 }
2337#endif
2338 else if (rb_enc_asciicompat(enc)) {
2339 c = 0;
2340 if (ENC_CODERANGE_CLEAN_P(cr)) {
2341 while (p < e) {
2342 q = search_nonascii(p, e);
2343 if (!q)
2344 return c + (e - p);
2345 c += q - p;
2346 p = q;
2347 p += rb_enc_fast_mbclen(p, e, enc);
2348 c++;
2349 }
2350 }
2351 else {
2352 while (p < e) {
2353 q = search_nonascii(p, e);
2354 if (!q)
2355 return c + (e - p);
2356 c += q - p;
2357 p = q;
2358 p += rb_enc_mbclen(p, e, enc);
2359 c++;
2360 }
2361 }
2362 return c;
2363 }
2364
2365 for (c=0; p<e; c++) {
2366 p += rb_enc_mbclen(p, e, enc);
2367 }
2368 return c;
2369}
2370
2371long
2372rb_enc_strlen(const char *p, const char *e, rb_encoding *enc)
2373{
2374 return enc_strlen(p, e, enc, ENC_CODERANGE_UNKNOWN);
2375}
2376
2377/* To get strlen with cr
2378 * Note that given cr is not used.
2379 */
2380long
2381rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr)
2382{
2383 long c;
2384 const char *q;
2385 int ret;
2386
2387 *cr = 0;
2388 if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
2389 long diff = (long)(e - p);
2390 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2391 }
2392 else if (rb_enc_asciicompat(enc)) {
2393 c = 0;
2394 while (p < e) {
2395 q = search_nonascii(p, e);
2396 if (!q) {
2397 if (!*cr) *cr = ENC_CODERANGE_7BIT;
2398 return c + (e - p);
2399 }
2400 c += q - p;
2401 p = q;
2402 ret = rb_enc_precise_mbclen(p, e, enc);
2403 if (MBCLEN_CHARFOUND_P(ret)) {
2404 *cr |= ENC_CODERANGE_VALID;
2405 p += MBCLEN_CHARFOUND_LEN(ret);
2406 }
2407 else {
2409 p++;
2410 }
2411 c++;
2412 }
2413 if (!*cr) *cr = ENC_CODERANGE_7BIT;
2414 return c;
2415 }
2416
2417 for (c=0; p<e; c++) {
2418 ret = rb_enc_precise_mbclen(p, e, enc);
2419 if (MBCLEN_CHARFOUND_P(ret)) {
2420 *cr |= ENC_CODERANGE_VALID;
2421 p += MBCLEN_CHARFOUND_LEN(ret);
2422 }
2423 else {
2425 if (p + rb_enc_mbminlen(enc) <= e)
2426 p += rb_enc_mbminlen(enc);
2427 else
2428 p = e;
2429 }
2430 }
2431 if (!*cr) *cr = ENC_CODERANGE_7BIT;
2432 return c;
2433}
2434
2435/* enc must be str's enc or rb_enc_check(str, str2) */
2436static long
2437str_strlen(VALUE str, rb_encoding *enc)
2438{
2439 const char *p, *e;
2440 int cr;
2441
2442 if (single_byte_optimizable(str)) return RSTRING_LEN(str);
2443 if (!enc) enc = STR_ENC_GET(str);
2444 p = RSTRING_PTR(str);
2445 e = RSTRING_END(str);
2446 cr = ENC_CODERANGE(str);
2447
2448 if (cr == ENC_CODERANGE_UNKNOWN) {
2449 long n = rb_enc_strlen_cr(p, e, enc, &cr);
2450 if (cr) ENC_CODERANGE_SET(str, cr);
2451 return n;
2452 }
2453 else {
2454 return enc_strlen(p, e, enc, cr);
2455 }
2456}
2457
2458long
2460{
2461 return str_strlen(str, NULL);
2462}
2463
2464/*
2465 * call-seq:
2466 * length -> integer
2467 *
2468 * :include: doc/string/length.rdoc
2469 *
2470 */
2471
2472VALUE
2474{
2475 return LONG2NUM(str_strlen(str, NULL));
2476}
2477
2478/*
2479 * call-seq:
2480 * bytesize -> integer
2481 *
2482 * :include: doc/string/bytesize.rdoc
2483 *
2484 */
2485
2486VALUE
2487rb_str_bytesize(VALUE str)
2488{
2489 return LONG2NUM(RSTRING_LEN(str));
2490}
2491
2492/*
2493 * call-seq:
2494 * empty? -> true or false
2495 *
2496 * Returns whether the length of +self+ is zero:
2497 *
2498 * 'hello'.empty? # => false
2499 * ' '.empty? # => false
2500 * ''.empty? # => true
2501 *
2502 * Related: see {Querying}[rdoc-ref:String@Querying].
2503 */
2504
2505static VALUE
2506rb_str_empty(VALUE str)
2507{
2508 return RBOOL(RSTRING_LEN(str) == 0);
2509}
2510
2511/*
2512 * call-seq:
2513 * self + other_string -> new_string
2514 *
2515 * Returns a new string containing +other_string+ concatenated to +self+:
2516 *
2517 * 'Hello from ' + self.to_s # => "Hello from main"
2518 *
2519 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
2520 */
2521
2522VALUE
2524{
2525 VALUE str3;
2526 rb_encoding *enc;
2527 const char *ptr1, *ptr2;
2528 char *ptr3;
2529 long len1, len2;
2530 int termlen;
2531
2532 StringValue(str2);
2533 enc = rb_enc_check_str(str1, str2);
2534 RSTRING_GETMEM(str1, ptr1, len1);
2535 RSTRING_GETMEM(str2, ptr2, len2);
2536 termlen = rb_enc_mbminlen(enc);
2537 if (len1 > LONG_MAX - len2) {
2538 rb_raise(rb_eArgError, "string size too big");
2539 }
2540 str3 = str_enc_new(rb_cString, 0, len1+len2, enc);
2541 ptr3 = RSTRING_PTR(str3);
2542 memcpy(ptr3, ptr1, len1);
2543 memcpy(ptr3+len1, ptr2, len2);
2544 TERM_FILL(&ptr3[len1+len2], termlen);
2545
2546 ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
2548 RB_GC_GUARD(str1);
2549 RB_GC_GUARD(str2);
2550 return str3;
2551}
2552
2553/* A variant of rb_str_plus that does not raise but return Qundef instead. */
2554VALUE
2555rb_str_opt_plus(VALUE str1, VALUE str2)
2556{
2559 long len1, len2;
2560 MAYBE_UNUSED(char) *ptr1, *ptr2;
2561 RSTRING_GETMEM(str1, ptr1, len1);
2562 RSTRING_GETMEM(str2, ptr2, len2);
2563 int enc1 = rb_enc_get_index(str1);
2564 int enc2 = rb_enc_get_index(str2);
2565
2566 if (enc1 < 0) {
2567 return Qundef;
2568 }
2569 else if (enc2 < 0) {
2570 return Qundef;
2571 }
2572 else if (enc1 != enc2) {
2573 return Qundef;
2574 }
2575 else if (len1 > LONG_MAX - len2) {
2576 return Qundef;
2577 }
2578 else {
2579 return rb_str_plus(str1, str2);
2580 }
2581
2582}
2583
2584/*
2585 * call-seq:
2586 * self * n -> new_string
2587 *
2588 * Returns a new string containing +n+ copies of +self+:
2589 *
2590 * 'Ho!' * 3 # => "Ho!Ho!Ho!"
2591 * 'No!' * 0 # => ""
2592 *
2593 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
2594 */
2595
2596VALUE
2598{
2599 VALUE str2;
2600 long n, len;
2601 char *ptr2;
2602 int termlen;
2603
2604 if (times == INT2FIX(1)) {
2605 return str_duplicate(rb_cString, str);
2606 }
2607 if (times == INT2FIX(0)) {
2608 str2 = str_alloc_embed(rb_cString, 0);
2609 rb_enc_copy(str2, str);
2610 return str2;
2611 }
2612 len = NUM2LONG(times);
2613 if (len < 0) {
2614 rb_raise(rb_eArgError, "negative argument");
2615 }
2616 if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
2617 if (STR_EMBEDDABLE_P(len, 1)) {
2618 str2 = str_alloc_embed(rb_cString, len + 1);
2619 memset(RSTRING_PTR(str2), 0, len + 1);
2620 }
2621 else {
2622 str2 = str_alloc_heap(rb_cString);
2623 RSTRING(str2)->as.heap.aux.capa = len;
2624 RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
2625 }
2626 STR_SET_LEN(str2, len);
2627 rb_enc_copy(str2, str);
2628 return str2;
2629 }
2630 if (len && LONG_MAX/len < RSTRING_LEN(str)) {
2631 rb_raise(rb_eArgError, "argument too big");
2632 }
2633
2634 len *= RSTRING_LEN(str);
2635 termlen = TERM_LEN(str);
2636 str2 = str_enc_new(rb_cString, 0, len, STR_ENC_GET(str));
2637 ptr2 = RSTRING_PTR(str2);
2638 if (len) {
2639 n = RSTRING_LEN(str);
2640 memcpy(ptr2, RSTRING_PTR(str), n);
2641 while (n <= len/2) {
2642 memcpy(ptr2 + n, ptr2, n);
2643 n *= 2;
2644 }
2645 memcpy(ptr2 + n, ptr2, len-n);
2646 }
2647 STR_SET_LEN(str2, len);
2648 TERM_FILL(&ptr2[len], termlen);
2649 rb_enc_cr_str_copy_for_substr(str2, str);
2650
2651 return str2;
2652}
2653
2654/*
2655 * call-seq:
2656 * self % object -> new_string
2657 *
2658 * Returns the result of formatting +object+ into the format specifications
2659 * contained in +self+
2660 * (see {Format Specifications}[rdoc-ref:language/format_specifications.rdoc]):
2661 *
2662 * '%05d' % 123 # => "00123"
2663 *
2664 * If +self+ contains multiple format specifications,
2665 * +object+ must be an array or hash containing the objects to be formatted:
2666 *
2667 * '%-5s: %016x' % [ 'ID', self.object_id ] # => "ID : 00002b054ec93168"
2668 * 'foo = %{foo}' % {foo: 'bar'} # => "foo = bar"
2669 * 'foo = %{foo}, baz = %{baz}' % {foo: 'bar', baz: 'bat'} # => "foo = bar, baz = bat"
2670 *
2671 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
2672 */
2673
2674static VALUE
2675rb_str_format_m(VALUE str, VALUE arg)
2676{
2677 VALUE tmp = rb_check_array_type(arg);
2678
2679 if (!NIL_P(tmp)) {
2680 VALUE result = rb_str_format(RARRAY_LENINT(tmp), RARRAY_CONST_PTR(tmp), str);
2681 RB_GC_GUARD(tmp);
2682 return result;
2683 }
2684 return rb_str_format(1, &arg, str);
2685}
2686
2687static inline void
2688rb_check_lockedtmp(VALUE str)
2689{
2690 if (FL_TEST(str, STR_TMPLOCK)) {
2691 rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
2692 }
2693}
2694
2695// If none of these flags are set, we know we have an modifiable string.
2696// If any is set, we need to do more detailed checks.
2697#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
2698static inline void
2699str_modifiable(VALUE str)
2700{
2701 RUBY_ASSERT(ruby_thread_has_gvl_p());
2702
2703 if (RB_UNLIKELY(FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
2704 if (CHILLED_STRING_P(str)) {
2705 CHILLED_STRING_MUTATED(str);
2706 }
2707 rb_check_lockedtmp(str);
2708 rb_check_frozen(str);
2709 }
2710}
2711
2712static inline int
2713str_dependent_p(VALUE str)
2714{
2715 if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2716 return FALSE;
2717 }
2718 else {
2719 return TRUE;
2720 }
2721}
2722
2723// If none of these flags are set, we know we have an independent string.
2724// If any is set, we need to do more detailed checks.
2725#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
2726static inline int
2727str_independent(VALUE str)
2728{
2729 RUBY_ASSERT(ruby_thread_has_gvl_p());
2730
2731 if (RB_UNLIKELY(FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
2732 str_modifiable(str);
2733 return !str_dependent_p(str);
2734 }
2735 return TRUE;
2736}
2737
2738static void
2739str_make_independent_expand(VALUE str, long len, long expand, const int termlen)
2740{
2741 RUBY_ASSERT(ruby_thread_has_gvl_p());
2742
2743 char *ptr;
2744 char *oldptr;
2745 long capa = len + expand;
2746
2747 if (len > capa) len = capa;
2748
2749 if (!STR_EMBED_P(str) && str_embed_capa(str) >= capa + termlen) {
2750 ptr = RSTRING(str)->as.heap.ptr;
2751 STR_SET_EMBED(str);
2752 memcpy(RSTRING(str)->as.embed.ary, ptr, len);
2753 TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
2754 STR_SET_LEN(str, len);
2755 return;
2756 }
2757
2758 ptr = ALLOC_N(char, (size_t)capa + termlen);
2759 oldptr = RSTRING_PTR(str);
2760 if (oldptr) {
2761 memcpy(ptr, oldptr, len);
2762 }
2763 if (FL_TEST_RAW(str, STR_NOEMBED|STR_NOFREE|STR_SHARED) == STR_NOEMBED) {
2764 SIZED_FREE_N(oldptr, STR_HEAP_SIZE(str));
2765 }
2766 STR_SET_NOEMBED(str);
2767 FL_UNSET(str, STR_SHARED|STR_NOFREE);
2768 TERM_FILL(ptr + len, termlen);
2769 RSTRING(str)->as.heap.ptr = ptr;
2770 STR_SET_LEN(str, len);
2771 RSTRING(str)->as.heap.aux.capa = capa;
2772}
2773
2774void
2775rb_str_modify(VALUE str)
2776{
2777 if (!str_independent(str))
2778 str_make_independent(str);
2780}
2781
2782void
2784{
2785 RUBY_ASSERT(ruby_thread_has_gvl_p());
2786
2787 int termlen = TERM_LEN(str);
2788 long len = RSTRING_LEN(str);
2789
2790 if (expand < 0) {
2791 rb_raise(rb_eArgError, "negative expanding string size");
2792 }
2793 if (expand >= LONG_MAX - len) {
2794 rb_raise(rb_eArgError, "string size too big");
2795 }
2796
2797 if (!str_independent(str)) {
2798 str_make_independent_expand(str, len, expand, termlen);
2799 }
2800 else if (expand > 0) {
2801 RESIZE_CAPA_TERM(str, len + expand, termlen);
2802 }
2804}
2805
2806/* As rb_str_modify(), but don't clear coderange */
2807static void
2808str_modify_keep_cr(VALUE str)
2809{
2810 if (!str_independent(str))
2811 str_make_independent(str);
2813 /* Force re-scan later */
2815}
2816
2817static inline void
2818str_discard(VALUE str)
2819{
2820 str_modifiable(str);
2821 if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2822 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
2823 RSTRING(str)->as.heap.ptr = 0;
2824 STR_SET_LEN(str, 0);
2825 }
2826}
2827
2828void
2830{
2831 int encindex = rb_enc_get_index(str);
2832
2833 if (RB_UNLIKELY(encindex == -1)) {
2834 rb_raise(rb_eTypeError, "not encoding capable object");
2835 }
2836
2837 if (RB_LIKELY(rb_str_encindex_fastpath(encindex))) {
2838 return;
2839 }
2840
2841 rb_encoding *enc = rb_enc_from_index(encindex);
2842 if (!rb_enc_asciicompat(enc)) {
2843 rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc));
2844 }
2845}
2846
2847VALUE
2849{
2850 RUBY_ASSERT(ruby_thread_has_gvl_p());
2851
2852 VALUE s = *ptr;
2853 if (!RB_TYPE_P(s, T_STRING)) {
2854 s = rb_str_to_str(s);
2855 *ptr = s;
2856 }
2857 return s;
2858}
2859
2860char *
2862{
2863 VALUE str = rb_string_value(ptr);
2864 return RSTRING_PTR(str);
2865}
2866
2867static const char *
2868str_null_char(const char *s, long len, const int minlen, rb_encoding *enc)
2869{
2870 const char *e = s + len;
2871
2872 for (; s + minlen <= e; s += rb_enc_mbclen(s, e, enc)) {
2873 if (zero_filled(s, minlen)) return s;
2874 }
2875 return 0;
2876}
2877
2878static char *
2879str_fill_term(VALUE str, char *s, long len, int termlen)
2880{
2881 /* This function assumes that (capa + termlen) bytes of memory
2882 * is allocated, like many other functions in this file.
2883 */
2884 if (str_dependent_p(str)) {
2885 if (!zero_filled(s + len, termlen))
2886 str_make_independent_expand(str, len, 0L, termlen);
2887 }
2888 else {
2889 TERM_FILL(s + len, termlen);
2890 return s;
2891 }
2892 return RSTRING_PTR(str);
2893}
2894
2895void
2896rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen)
2897{
2898 long capa = str_capacity(str, oldtermlen) + oldtermlen;
2899 long len = RSTRING_LEN(str);
2900
2901 RUBY_ASSERT(capa >= len);
2902 if (capa - len < termlen) {
2903 rb_check_lockedtmp(str);
2904 str_make_independent_expand(str, len, 0L, termlen);
2905 }
2906 else if (str_dependent_p(str)) {
2907 if (termlen > oldtermlen)
2908 str_make_independent_expand(str, len, 0L, termlen);
2909 }
2910 else {
2911 if (!STR_EMBED_P(str)) {
2912 /* modify capa instead of realloc */
2913 RUBY_ASSERT(!FL_TEST((str), STR_SHARED));
2914 RSTRING(str)->as.heap.aux.capa = capa - termlen;
2915 }
2916 if (termlen > oldtermlen) {
2917 TERM_FILL(RSTRING_PTR(str) + len, termlen);
2918 }
2919 }
2920
2921 return;
2922}
2923
2924static char *
2925str_null_check(VALUE str, int *w)
2926{
2927 char *s = RSTRING_PTR(str);
2928 long len = RSTRING_LEN(str);
2929 int minlen = 1;
2930
2931 if (RB_UNLIKELY(!rb_str_enc_fastpath(str))) {
2932 rb_encoding *enc = rb_str_enc_get(str);
2933 minlen = rb_enc_mbminlen(enc);
2934
2935 if (minlen > 1) {
2936 *w = 1;
2937 if (str_null_char(s, len, minlen, enc)) {
2938 return NULL;
2939 }
2940 return str_fill_term(str, s, len, minlen);
2941 }
2942 }
2943
2944 *w = 0;
2945 if (!s || memchr(s, 0, len)) {
2946 return NULL;
2947 }
2948 if (s[len]) {
2949 s = str_fill_term(str, s, len, minlen);
2950 }
2951 return s;
2952}
2953
2954static char *str_to_cstr(VALUE str);
2955
2956const char *
2957rb_str_null_check(VALUE str)
2958{
2960
2961 const char *s;
2962 long len;
2963 RSTRING_GETMEM(str, s, len);
2964
2965 if (RB_LIKELY(rb_str_enc_fastpath(str))) {
2966 if (!s || memchr(s, 0, len)) {
2967 rb_raise(rb_eArgError, "string contains null byte");
2968 }
2969 }
2970 else {
2971 str_to_cstr(str);
2972 }
2973
2974 return s;
2975}
2976
2977char *
2978rb_str_to_cstr(VALUE str)
2979{
2980 int w;
2981 return str_null_check(str, &w);
2982}
2983
2984char *
2986{
2987 VALUE str = rb_string_value(ptr);
2988 return str_to_cstr(str);
2989}
2990
2991static char *
2992str_to_cstr(VALUE str)
2993{
2994 int w;
2995 char *s = str_null_check(str, &w);
2996 if (!s) {
2997 if (w) {
2998 rb_raise(rb_eArgError, "string contains null char");
2999 }
3000 rb_raise(rb_eArgError, "string contains null byte");
3001 }
3002 return s;
3003}
3004
3005char *
3006rb_str_fill_terminator(VALUE str, const int newminlen)
3007{
3008 char *s = RSTRING_PTR(str);
3009 long len = RSTRING_LEN(str);
3010 return str_fill_term(str, s, len, newminlen);
3011}
3012
3013VALUE
3015{
3016 str = rb_check_convert_type_with_id(str, T_STRING, "String", idTo_str);
3017 return str;
3018}
3019
3020/*
3021 * call-seq:
3022 * String.try_convert(object) -> object, new_string, or nil
3023 *
3024 * Attempts to convert the given +object+ to a string.
3025 *
3026 * If +object+ is already a string, returns +object+, unmodified.
3027 *
3028 * Otherwise if +object+ responds to <tt>:to_str</tt>,
3029 * calls <tt>object.to_str</tt> and returns the result.
3030 *
3031 * Returns +nil+ if +object+ does not respond to <tt>:to_str</tt>.
3032 *
3033 * Raises an exception unless <tt>object.to_str</tt> returns a string.
3034 */
3035static VALUE
3036rb_str_s_try_convert(VALUE dummy, VALUE str)
3037{
3038 return rb_check_string_type(str);
3039}
3040
3041static char*
3042str_nth_len(const char *p, const char *e, long *nthp, rb_encoding *enc)
3043{
3044 long nth = *nthp;
3045 if (rb_enc_mbmaxlen(enc) == 1) {
3046 p += nth;
3047 }
3048 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
3049 p += nth * rb_enc_mbmaxlen(enc);
3050 }
3051 else if (rb_enc_asciicompat(enc)) {
3052 const char *p2, *e2;
3053 int n;
3054
3055 while (p < e && 0 < nth) {
3056 e2 = p + nth;
3057 if (e < e2) {
3058 *nthp = nth;
3059 return (char *)e;
3060 }
3061 p2 = search_nonascii(p, e2);
3062 if (!p2) {
3063 nth -= e2 - p;
3064 *nthp = nth;
3065 return (char *)e2;
3066 }
3067 nth -= p2 - p;
3068 p = p2;
3069 n = rb_enc_mbclen(p, e, enc);
3070 p += n;
3071 nth--;
3072 }
3073 *nthp = nth;
3074 if (nth != 0) {
3075 return (char *)e;
3076 }
3077 return (char *)p;
3078 }
3079 else {
3080 while (p < e && nth--) {
3081 p += rb_enc_mbclen(p, e, enc);
3082 }
3083 }
3084 if (p > e) p = e;
3085 *nthp = nth;
3086 return (char*)p;
3087}
3088
3089char*
3090rb_enc_nth(const char *p, const char *e, long nth, rb_encoding *enc)
3091{
3092 return str_nth_len(p, e, &nth, enc);
3093}
3094
3095static char*
3096str_nth(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte)
3097{
3098 if (singlebyte)
3099 p += nth;
3100 else {
3101 p = str_nth_len(p, e, &nth, enc);
3102 }
3103 if (!p) return 0;
3104 if (p > e) p = e;
3105 return (char *)p;
3106}
3107
3108/* char offset to byte offset */
3109static long
3110str_offset(const char *p, const char *e, long nth, rb_encoding *enc, int singlebyte)
3111{
3112 const char *pp = str_nth(p, e, nth, enc, singlebyte);
3113 if (!pp) return e - p;
3114 return pp - p;
3115}
3116
3117long
3118rb_str_offset(VALUE str, long pos)
3119{
3120 return str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
3121 STR_ENC_GET(str), single_byte_optimizable(str));
3122}
3123
3124#ifdef NONASCII_MASK
3125static char *
3126str_utf8_nth(const char *p, const char *e, long *nthp)
3127{
3128 long nth = *nthp;
3129 if ((int)SIZEOF_VOIDP * 2 < e - p && (int)SIZEOF_VOIDP * 2 < nth) {
3130 const uintptr_t *s, *t;
3131 const uintptr_t lowbits = SIZEOF_VOIDP - 1;
3132 s = (const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
3133 t = (const uintptr_t*)(~lowbits & (uintptr_t)e);
3134 while (p < (const char *)s) {
3135 if (is_utf8_lead_byte(*p)) nth--;
3136 p++;
3137 }
3138 do {
3139 nth -= count_utf8_lead_bytes_with_word(s);
3140 s++;
3141 } while (s < t && (int)SIZEOF_VOIDP <= nth);
3142 p = (char *)s;
3143 }
3144 while (p < e) {
3145 if (is_utf8_lead_byte(*p)) {
3146 if (nth == 0) break;
3147 nth--;
3148 }
3149 p++;
3150 }
3151 *nthp = nth;
3152 return (char *)p;
3153}
3154
3155static long
3156str_utf8_offset(const char *p, const char *e, long nth)
3157{
3158 const char *pp = str_utf8_nth(p, e, &nth);
3159 return pp - p;
3160}
3161#endif
3162
3163/* byte offset to char offset */
3164long
3165rb_str_sublen(VALUE str, long pos)
3166{
3167 if (single_byte_optimizable(str) || pos < 0)
3168 return pos;
3169 else {
3170 const char *p = RSTRING_PTR(str);
3171 return enc_strlen(p, p + pos, STR_ENC_GET(str), ENC_CODERANGE(str));
3172 }
3173}
3174
3175static VALUE
3176str_subseq(VALUE str, long beg, long len)
3177{
3178 VALUE str2;
3179
3180 RUBY_ASSERT(beg >= 0);
3181 RUBY_ASSERT(len >= 0);
3182 RUBY_ASSERT(beg+len <= RSTRING_LEN(str));
3183
3184 const int termlen = TERM_LEN(str);
3185 if (!SHARABLE_SUBSTRING_P(str, beg, len)) {
3186 str2 = rb_enc_str_new(RSTRING_PTR(str) + beg, len, rb_str_enc_get(str));
3187 if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) {
3189 }
3190 RB_GC_GUARD(str);
3191 return str2;
3192 }
3193
3194 /* Sharing allocates a shared root as well unless str can be one itself, so
3195 * a copy is worth a larger slot only when it saves that second object. */
3196 const bool root_available = STR_SHARED_P(str) ||
3197 RB_FL_TEST_RAW(str, FL_FREEZE | STR_CHILLED) == FL_FREEZE;
3198 const size_t max_embed_size = root_available ?
3199 rb_gc_size_slot_size(sizeof(struct RString)) : STR_COPY_MAX_EMBED_SIZE;
3200 const size_t embed_size = rb_str_embed_size(len, termlen);
3201
3202 if (embed_size <= max_embed_size && rb_gc_size_allocatable_p(embed_size)) {
3203 str2 = str_alloc_embed(rb_cString, len + termlen);
3204 char *ptr2 = RSTRING(str2)->as.embed.ary;
3205 memcpy(ptr2, RSTRING_PTR(str) + beg, len);
3206 TERM_FILL(ptr2 + len, termlen);
3207
3208 STR_SET_LEN(str2, len);
3209 if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) {
3211 }
3212
3213 RB_GC_GUARD(str);
3214 }
3215 else {
3216 str2 = str_alloc_heap(rb_cString);
3217 str_replace_shared(str2, str);
3218 RUBY_ASSERT(!STR_EMBED_P(str2));
3219 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
3220 ENC_CODERANGE_CLEAR(str2);
3221 }
3222
3223 RSTRING(str2)->as.heap.ptr += beg;
3224 if (RSTRING_LEN(str2) > len) {
3225 STR_SET_LEN(str2, len);
3226 }
3227 }
3228
3229 return str2;
3230}
3231
3232VALUE
3233rb_str_subseq(VALUE str, long beg, long len)
3234{
3235 VALUE str2 = str_subseq(str, beg, len);
3236 rb_enc_cr_str_copy_for_substr(str2, str);
3237 return str2;
3238}
3239
3240char *
3241rb_str_subpos(VALUE str, long beg, long *lenp)
3242{
3243 long len = *lenp;
3244 long slen = -1L;
3245 const long blen = RSTRING_LEN(str);
3246 rb_encoding *enc = STR_ENC_GET(str);
3247 const char *p, *s = RSTRING_PTR(str), *e = s + blen;
3248
3249 if (len < 0) return 0;
3250 if (beg < 0 && -beg < 0) return 0;
3251 if (!blen) {
3252 len = 0;
3253 }
3254 if (single_byte_optimizable(str)) {
3255 if (beg > blen) return 0;
3256 if (beg < 0) {
3257 beg += blen;
3258 if (beg < 0) return 0;
3259 }
3260 if (len > blen - beg)
3261 len = blen - beg;
3262 if (len < 0) return 0;
3263 p = s + beg;
3264 goto end;
3265 }
3266 if (beg < 0) {
3267 if (len > -beg) len = -beg;
3268 if ((ENC_CODERANGE(str) == ENC_CODERANGE_VALID) &&
3269 (-beg * rb_enc_mbmaxlen(enc) < blen / 8)) {
3270 beg = -beg;
3271 while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
3272 p = e;
3273 if (!p) return 0;
3274 while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
3275 if (!p) return 0;
3276 len = e - p;
3277 goto end;
3278 }
3279 else {
3280 slen = str_strlen(str, enc);
3281 beg += slen;
3282 if (beg < 0) return 0;
3283 p = s + beg;
3284 if (len == 0) goto end;
3285 }
3286 }
3287 else if (beg > 0 && beg > blen) {
3288 return 0;
3289 }
3290 if (len == 0) {
3291 if (beg > str_strlen(str, enc)) return 0; /* str's enc */
3292 p = s + beg;
3293 }
3294#ifdef NONASCII_MASK
3295 else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
3296 enc == rb_utf8_encoding()) {
3297 p = str_utf8_nth(s, e, &beg);
3298 if (beg > 0) return 0;
3299 len = str_utf8_offset(p, e, len);
3300 }
3301#endif
3302 else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
3303 int char_sz = rb_enc_mbmaxlen(enc);
3304
3305 p = s + beg * char_sz;
3306 if (p > e) {
3307 return 0;
3308 }
3309 else if (len * char_sz > e - p)
3310 len = e - p;
3311 else
3312 len *= char_sz;
3313 }
3314 else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
3315 if (beg > 0) return 0;
3316 len = 0;
3317 }
3318 else {
3319 len = str_offset(p, e, len, enc, 0);
3320 }
3321 end:
3322 *lenp = len;
3323 RB_GC_GUARD(str);
3324 return (char *)p;
3325}
3326
3327static VALUE str_substr(VALUE str, long beg, long len, int empty);
3328
3329VALUE
3330rb_str_substr(VALUE str, long beg, long len)
3331{
3332 return str_substr(str, beg, len, TRUE);
3333}
3334
3335VALUE
3336rb_str_substr_two_fixnums(VALUE str, VALUE beg, VALUE len, int empty)
3337{
3338 return str_substr(str, NUM2LONG(beg), NUM2LONG(len), empty);
3339}
3340
3341static VALUE
3342str_substr(VALUE str, long beg, long len, int empty)
3343{
3344 const char *p = rb_str_subpos(str, beg, &len);
3345
3346 if (!p) return Qnil;
3347 if (!len && !empty) return Qnil;
3348
3349 beg = p - RSTRING_PTR(str);
3350
3351 VALUE str2 = str_subseq(str, beg, len);
3352 rb_enc_cr_str_copy_for_substr(str2, str);
3353 return str2;
3354}
3355
3356/* :nodoc: */
3357VALUE
3359{
3360 if (CHILLED_STRING_P(str)) {
3361 FL_UNSET_RAW(str, STR_CHILLED);
3362 }
3363
3364 if (OBJ_FROZEN(str)) return str;
3365 rb_str_resize(str, RSTRING_LEN(str));
3366 return rb_obj_freeze(str);
3367}
3368
3369/*
3370 * call-seq:
3371 * +string -> new_string or self
3372 *
3373 * Returns +self+ if +self+ is not frozen and can be mutated
3374 * without warning issuance.
3375 *
3376 * Otherwise returns <tt>self.dup</tt>, which is not frozen.
3377 *
3378 * Related: see {Freezing/Unfreezing}[rdoc-ref:String@FreezingUnfreezing].
3379 */
3380static VALUE
3381str_uplus(VALUE str)
3382{
3383 if (OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
3384 return rb_str_dup(str);
3385 }
3386 else {
3387 return str;
3388 }
3389}
3390
3391/*
3392 * call-seq:
3393 * -self -> frozen_string
3394 *
3395 * Returns a frozen string equal to +self+.
3396 *
3397 * The returned string is +self+ if and only if all of the following are true:
3398 *
3399 * - +self+ is already frozen.
3400 * - +self+ is an instance of \String (rather than of a subclass of \String)
3401 * - +self+ has no instance variables set on it.
3402 *
3403 * Otherwise, the returned string is a frozen copy of +self+.
3404 *
3405 * Returning +self+, when possible, saves duplicating +self+;
3406 * see {Data deduplication}[https://en.wikipedia.org/wiki/Data_deduplication].
3407 *
3408 * It may also save duplicating other, already-existing, strings:
3409 *
3410 * s0 = 'foo'
3411 * s1 = 'foo'
3412 * s0.object_id == s1.object_id # => false
3413 * (-s0).object_id == (-s1).object_id # => true
3414 *
3415 * Note that method #-@ is convenient for defining a constant:
3416 *
3417 * FileName = -'config/database.yml'
3418 *
3419 * While its alias #dedup is better suited for chaining:
3420 *
3421 * 'foo'.dedup.gsub!('o')
3422 *
3423 * Related: see {Freezing/Unfreezing}[rdoc-ref:String@FreezingUnfreezing].
3424 */
3425static VALUE
3426str_uminus(VALUE str)
3427{
3428 if (!BARE_STRING_P(str) && !rb_obj_frozen_p(str)) {
3429 str = rb_str_dup(str);
3430 }
3431 return rb_fstring(str);
3432}
3433
3434RUBY_ALIAS_FUNCTION(rb_str_dup_frozen(VALUE str), rb_str_new_frozen, (str))
3435#define rb_str_dup_frozen rb_str_new_frozen
3436
3437VALUE
3439{
3440 rb_check_frozen(str);
3441 if (FL_TEST(str, STR_TMPLOCK)) {
3442 rb_raise(rb_eRuntimeError, "temporal locking already locked string");
3443 }
3444 FL_SET(str, STR_TMPLOCK);
3445 return str;
3446}
3447
3448VALUE
3450{
3451 rb_check_frozen(str);
3452 if (!FL_TEST(str, STR_TMPLOCK)) {
3453 rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
3454 }
3455 FL_UNSET(str, STR_TMPLOCK);
3456 return str;
3457}
3458
3459VALUE
3460rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg)
3461{
3462 rb_str_locktmp(str);
3463 return rb_ensure(func, arg, rb_str_unlocktmp, str);
3464}
3465
3466void
3468{
3469 RUBY_ASSERT(ruby_thread_has_gvl_p());
3470
3471 long capa;
3472 const int termlen = TERM_LEN(str);
3473
3474 str_modifiable(str);
3475 if (STR_SHARED_P(str)) {
3476 rb_raise(rb_eRuntimeError, "can't set length of shared string");
3477 }
3478 if (len > (capa = (long)str_capacity(str, termlen)) || len < 0) {
3479 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
3480 }
3481
3482 int cr = ENC_CODERANGE(str);
3483 if (len == 0) {
3484 /* Empty string does not contain non-ASCII */
3486 }
3487 else if (cr == ENC_CODERANGE_UNKNOWN) {
3488 /* Leave unknown. */
3489 }
3490 else if (len > RSTRING_LEN(str)) {
3491 if (ENC_CODERANGE_CLEAN_P(cr)) {
3492 /* Update the coderange regarding the extended part. */
3493 const char *const prev_end = RSTRING_END(str);
3494 const char *const new_end = RSTRING_PTR(str) + len;
3495 rb_encoding *enc = rb_enc_get(str);
3496 rb_str_coderange_scan_restartable(prev_end, new_end, enc, &cr);
3497 ENC_CODERANGE_SET(str, cr);
3498 }
3499 else if (cr == ENC_CODERANGE_BROKEN) {
3500 /* May be valid now, by appended part. */
3502 }
3503 }
3504 else if (len < RSTRING_LEN(str)) {
3505 if (cr != ENC_CODERANGE_7BIT) {
3506 /* ASCII-only string is keeping after truncated. Valid
3507 * and broken may be invalid or valid, leave unknown. */
3509 }
3510 }
3511
3512 STR_SET_LEN(str, len);
3513 TERM_FILL(&RSTRING_PTR(str)[len], termlen);
3514}
3515
3516VALUE
3517rb_str_resize(VALUE str, long len)
3518{
3519 if (len < 0) {
3520 rb_raise(rb_eArgError, "negative string size (or size too big)");
3521 }
3522
3523 int independent = str_independent(str);
3524 long slen = RSTRING_LEN(str);
3525 const int termlen = TERM_LEN(str);
3526
3527 if (slen > len || (termlen != 1 && slen < len)) {
3529 }
3530
3531 {
3532 long capa;
3533 if (STR_EMBED_P(str)) {
3534 if (len == slen) return str;
3535 if (str_embed_capa(str) >= len + termlen) {
3536 STR_SET_LEN(str, len);
3537 TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
3538 return str;
3539 }
3540 str_make_independent_expand(str, slen, len - slen, termlen);
3541 }
3542 else if (str_embed_capa(str) >= len + termlen) {
3543 capa = RSTRING(str)->as.heap.aux.capa;
3544 char *ptr = STR_HEAP_PTR(str);
3545 STR_SET_EMBED(str);
3546 if (slen > len) slen = len;
3547 if (slen > 0) MEMCPY(RSTRING(str)->as.embed.ary, ptr, char, slen);
3548 TERM_FILL(RSTRING(str)->as.embed.ary + len, termlen);
3549 STR_SET_LEN(str, len);
3550 if (independent) {
3551 SIZED_FREE_N(ptr, capa + termlen);
3552 }
3553 return str;
3554 }
3555 else if (!independent) {
3556 if (len == slen) return str;
3557 str_make_independent_expand(str, slen, len - slen, termlen);
3558 }
3559 else if ((capa = RSTRING(str)->as.heap.aux.capa) < len ||
3560 (capa - len) > (len < 1024 ? len : 1024)) {
3561 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char,
3562 (size_t)len + termlen, STR_HEAP_SIZE(str));
3563 RSTRING(str)->as.heap.aux.capa = len;
3564 }
3565 else if (len == slen) return str;
3566 STR_SET_LEN(str, len);
3567 TERM_FILL(RSTRING(str)->as.heap.ptr + len, termlen); /* sentinel */
3568 }
3569 return str;
3570}
3571
3572static void
3573str_ensure_available_capa(VALUE str, long len)
3574{
3575 str_modify_keep_cr(str);
3576
3577 const int termlen = TERM_LEN(str);
3578 long olen = RSTRING_LEN(str);
3579
3580 if (RB_UNLIKELY(olen > LONG_MAX - len)) {
3581 rb_raise(rb_eArgError, "string sizes too big");
3582 }
3583
3584 long total = olen + len;
3585 long capa = str_capacity(str, termlen);
3586
3587 if (capa < total) {
3588 if (total >= LONG_MAX / 2) {
3589 capa = total;
3590 }
3591 while (total > capa) {
3592 capa = 2 * capa + termlen; /* == 2*(capa+termlen)-termlen */
3593 }
3594 RESIZE_CAPA_TERM(str, capa, termlen);
3595 }
3596}
3597
3598static VALUE
3599str_buf_cat4(VALUE str, const char *ptr, long len, bool keep_cr)
3600{
3601 if (keep_cr) {
3602 str_modify_keep_cr(str);
3603 }
3604 else {
3605 rb_str_modify(str);
3606 }
3607 if (len == 0) return 0;
3608
3609 long total, olen, off = -1;
3610 char *sptr;
3611 const int termlen = TERM_LEN(str);
3612
3613 RSTRING_GETMEM(str, sptr, olen);
3614 if (ptr >= sptr && ptr <= sptr + olen) {
3615 off = ptr - sptr;
3616 }
3617
3618 long capa = str_capacity(str, termlen);
3619
3620 if (olen > LONG_MAX - len) {
3621 rb_raise(rb_eArgError, "string sizes too big");
3622 }
3623 total = olen + len;
3624 if (capa < total) {
3625 if (total >= LONG_MAX / 2) {
3626 capa = total;
3627 }
3628 while (total > capa) {
3629 capa = 2 * capa + termlen; /* == 2*(capa+termlen)-termlen */
3630 }
3631 RESIZE_CAPA_TERM(str, capa, termlen);
3632 sptr = RSTRING_PTR(str);
3633 }
3634 if (off != -1) {
3635 ptr = sptr + off;
3636 }
3637 memcpy(sptr + olen, ptr, len);
3638 STR_SET_LEN(str, total);
3639 TERM_FILL(sptr + total, termlen); /* sentinel */
3640
3641 return str;
3642}
3643
3644#define str_buf_cat(str, ptr, len) str_buf_cat4((str), (ptr), len, false)
3645#define str_buf_cat2(str, ptr) str_buf_cat4((str), (ptr), rb_strlen_lit(ptr), false)
3646
3647VALUE
3648rb_str_cat(VALUE str, const char *ptr, long len)
3649{
3650 if (len == 0) return str;
3651 if (len < 0) {
3652 rb_raise(rb_eArgError, "negative string size (or size too big)");
3653 }
3654 return str_buf_cat(str, ptr, len);
3655}
3656
3657VALUE
3658rb_str_cat_cstr(VALUE str, const char *ptr)
3659{
3660 must_not_null(ptr);
3661 return rb_str_buf_cat(str, ptr, strlen(ptr));
3662}
3663
3664static void
3665rb_str_buf_cat_byte(VALUE str, unsigned char byte)
3666{
3667 RUBY_ASSERT(RB_ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT || RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII);
3668
3669 // We can't write directly to shared strings without impacting others, so we must make the string independent.
3670 if (UNLIKELY(!str_independent(str))) {
3671 str_make_independent(str);
3672 }
3673
3674 long string_length = -1;
3675 const int null_terminator_length = 1;
3676 char *sptr;
3677 RSTRING_GETMEM(str, sptr, string_length);
3678
3679 // Ensure the resulting string wouldn't be too long.
3680 if (UNLIKELY(string_length > LONG_MAX - 1)) {
3681 rb_raise(rb_eArgError, "string sizes too big");
3682 }
3683
3684 long string_capacity = str_capacity(str, null_terminator_length);
3685
3686 // Get the code range before any modifications since those might clear the code range.
3687 int cr = ENC_CODERANGE(str);
3688
3689 // Check if the string has spare string_capacity to write the new byte.
3690 if (LIKELY(string_capacity >= string_length + 1)) {
3691 // In fast path we can write the new byte and note the string's new length.
3692 sptr[string_length] = byte;
3693 STR_SET_LEN(str, string_length + 1);
3694 TERM_FILL(sptr + string_length + 1, null_terminator_length);
3695 }
3696 else {
3697 // If there's not enough string_capacity, make a call into the general string concatenation function.
3698 str_buf_cat(str, (char *)&byte, 1);
3699 }
3700
3701 // If the code range is already known, we can derive the resulting code range cheaply by looking at the byte we
3702 // just appended. If the code range is unknown, but the string was empty, then we can also derive the code range
3703 // by looking at the byte we just appended. Otherwise, we'd have to scan the bytes to determine the code range so
3704 // we leave it as unknown. It cannot be broken for binary strings so we don't need to handle that option.
3705 if (cr == ENC_CODERANGE_7BIT || string_length == 0) {
3706 if (ISASCII(byte)) {
3708 }
3709 else {
3711
3712 // Promote a US-ASCII string to ASCII-8BIT when a non-ASCII byte is appended.
3713 if (UNLIKELY(RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)) {
3714 rb_enc_associate_index(str, ENCINDEX_ASCII_8BIT);
3715 }
3716 }
3717 }
3718}
3719
3720RUBY_ALIAS_FUNCTION(rb_str_buf_cat(VALUE str, const char *ptr, long len), rb_str_cat, (str, ptr, len))
3721RUBY_ALIAS_FUNCTION(rb_str_buf_cat2(VALUE str, const char *ptr), rb_str_cat_cstr, (str, ptr))
3722RUBY_ALIAS_FUNCTION(rb_str_cat2(VALUE str, const char *ptr), rb_str_cat_cstr, (str, ptr))
3723
3724static VALUE
3725rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
3726 int ptr_encindex, int ptr_cr, int *ptr_cr_ret)
3727{
3728 int str_encindex = ENCODING_GET(str);
3729 int res_encindex;
3730 int str_cr, res_cr;
3731 rb_encoding *str_enc, *ptr_enc;
3732
3733 str_cr = RSTRING_LEN(str) ? ENC_CODERANGE(str) : ENC_CODERANGE_7BIT;
3734
3735 if (str_encindex == ptr_encindex) {
3736 if (str_cr != ENC_CODERANGE_UNKNOWN && ptr_cr == ENC_CODERANGE_UNKNOWN) {
3737 ptr_cr = coderange_scan(ptr, len, rb_enc_from_index(ptr_encindex));
3738 }
3739 }
3740 else {
3741 str_enc = rb_enc_from_index(str_encindex);
3742 ptr_enc = rb_enc_from_index(ptr_encindex);
3743 if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
3744 if (len == 0)
3745 return str;
3746 if (RSTRING_LEN(str) == 0) {
3747 rb_str_buf_cat(str, ptr, len);
3748 ENCODING_CODERANGE_SET(str, ptr_encindex, ptr_cr);
3749 rb_str_change_terminator_length(str, rb_enc_mbminlen(str_enc), rb_enc_mbminlen(ptr_enc));
3750 return str;
3751 }
3752 goto incompatible;
3753 }
3754 if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
3755 ptr_cr = coderange_scan(ptr, len, ptr_enc);
3756 }
3757 if (str_cr == ENC_CODERANGE_UNKNOWN) {
3758 if (ENCODING_IS_ASCII8BIT(str) || ptr_cr != ENC_CODERANGE_7BIT) {
3759 str_cr = rb_enc_str_coderange(str);
3760 }
3761 }
3762 }
3763 if (ptr_cr_ret)
3764 *ptr_cr_ret = ptr_cr;
3765
3766 if (str_encindex != ptr_encindex &&
3767 str_cr != ENC_CODERANGE_7BIT &&
3768 ptr_cr != ENC_CODERANGE_7BIT) {
3769 str_enc = rb_enc_from_index(str_encindex);
3770 ptr_enc = rb_enc_from_index(ptr_encindex);
3771 goto incompatible;
3772 }
3773
3774 if (str_cr == ENC_CODERANGE_UNKNOWN) {
3775 res_encindex = str_encindex;
3776 res_cr = ENC_CODERANGE_UNKNOWN;
3777 }
3778 else if (str_cr == ENC_CODERANGE_7BIT) {
3779 if (ptr_cr == ENC_CODERANGE_7BIT) {
3780 res_encindex = str_encindex;
3781 res_cr = ENC_CODERANGE_7BIT;
3782 }
3783 else {
3784 res_encindex = ptr_encindex;
3785 res_cr = ptr_cr;
3786 }
3787 }
3788 else if (str_cr == ENC_CODERANGE_VALID) {
3789 res_encindex = str_encindex;
3790 if (ENC_CODERANGE_CLEAN_P(ptr_cr))
3791 res_cr = str_cr;
3792 else
3793 res_cr = ptr_cr;
3794 }
3795 else { /* str_cr == ENC_CODERANGE_BROKEN */
3796 res_encindex = str_encindex;
3797 res_cr = str_cr;
3798 if (0 < len) res_cr = ENC_CODERANGE_UNKNOWN;
3799 }
3800
3801 if (len < 0) {
3802 rb_raise(rb_eArgError, "negative string size (or size too big)");
3803 }
3804 str_buf_cat(str, ptr, len);
3805 ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
3806 return str;
3807
3808 incompatible:
3809 rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
3810 rb_enc_inspect_name(str_enc), rb_enc_inspect_name(ptr_enc));
3812}
3813
3814VALUE
3815rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *ptr_enc)
3816{
3817 return rb_enc_cr_str_buf_cat(str, ptr, len,
3818 rb_enc_to_index(ptr_enc), ENC_CODERANGE_UNKNOWN, NULL);
3819}
3820
3821VALUE
3823{
3824 /* ptr must reference NUL terminated ASCII string. */
3825 int encindex = ENCODING_GET(str);
3826 rb_encoding *enc = rb_enc_from_index(encindex);
3827 if (rb_enc_asciicompat(enc)) {
3828 return rb_enc_cr_str_buf_cat(str, ptr, strlen(ptr),
3829 encindex, ENC_CODERANGE_7BIT, 0);
3830 }
3831 else {
3832 char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc));
3833 while (*ptr) {
3834 unsigned int c = (unsigned char)*ptr;
3835 int len = rb_enc_codelen(c, enc);
3836 rb_enc_mbcput(c, buf, enc);
3837 rb_enc_cr_str_buf_cat(str, buf, len,
3838 encindex, ENC_CODERANGE_VALID, 0);
3839 ptr++;
3840 }
3841 return str;
3842 }
3843}
3844
3845VALUE
3847{
3848 int str2_cr = rb_enc_str_coderange(str2);
3849
3850 if (rb_str_enc_fastpath(str)) {
3851 switch (str2_cr) {
3852 case ENC_CODERANGE_7BIT:
3853 // If RHS is 7bit we can do simple concatenation
3854 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2), true);
3855 RB_GC_GUARD(str2);
3856 return str;
3858 // If RHS is valid, we can do simple concatenation if encodings are the same
3859 if (ENCODING_GET_INLINED(str) == ENCODING_GET_INLINED(str2)) {
3860 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2), true);
3861 int str_cr = ENC_CODERANGE(str);
3862 if (UNLIKELY(str_cr != ENC_CODERANGE_VALID)) {
3863 ENC_CODERANGE_SET(str, RB_ENC_CODERANGE_AND(str_cr, str2_cr));
3864 }
3865 RB_GC_GUARD(str2);
3866 return str;
3867 }
3868 }
3869 }
3870
3871 rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
3872 ENCODING_GET(str2), str2_cr, &str2_cr);
3873
3874 ENC_CODERANGE_SET(str2, str2_cr);
3875
3876 return str;
3877}
3878
3879VALUE
3881{
3882 StringValue(str2);
3883 return rb_str_buf_append(str, str2);
3884}
3885
3886VALUE
3887rb_str_concat_literals(size_t num, const VALUE *strary)
3888{
3889 VALUE str;
3890 size_t i, s = 0;
3891 unsigned long len = 1;
3892
3893 if (UNLIKELY(!num)) return rb_str_new(0, 0);
3894 if (UNLIKELY(num == 1)) return rb_str_resurrect(strary[0]);
3895
3896 for (i = 0; i < num; ++i) { len += RSTRING_LEN(strary[i]); }
3897 str = rb_str_buf_new(len);
3898 str_enc_copy_direct(str, strary[0]);
3899
3900 for (i = s; i < num; ++i) {
3901 const VALUE v = strary[i];
3902 int encidx = ENCODING_GET(v);
3903
3904 rb_str_buf_append(str, v);
3905 if (encidx != ENCINDEX_US_ASCII) {
3906 if (ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)
3907 rb_enc_set_index(str, encidx);
3908 }
3909 }
3910 return str;
3911}
3912
3913/*
3914 * call-seq:
3915 * concat(*objects) -> string
3916 *
3917 * :include: doc/string/concat.rdoc
3918 */
3919static VALUE
3920rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
3921{
3922 str_modifiable(str);
3923
3924 if (argc == 1) {
3925 return rb_str_concat(str, argv[0]);
3926 }
3927 else if (argc > 1) {
3928 int i;
3929 VALUE arg_str = rb_str_tmp_new(0);
3930 rb_enc_copy(arg_str, str);
3931 for (i = 0; i < argc; i++) {
3932 rb_str_concat(arg_str, argv[i]);
3933 }
3934 rb_str_buf_append(str, arg_str);
3935 }
3936
3937 return str;
3938}
3939
3940/*
3941 * call-seq:
3942 * append_as_bytes(*objects) -> self
3943 *
3944 * Concatenates each object in +objects+ into +self+; returns +self+;
3945 * performs no encoding validation or conversion:
3946 *
3947 * s = 'foo'
3948 * s.append_as_bytes(" \xE2\x82") # => "foo \xE2\x82"
3949 * s.valid_encoding? # => false
3950 * s.append_as_bytes("\xAC 12")
3951 * s.valid_encoding? # => true
3952 *
3953 * When a given object is an integer,
3954 * the value is considered an 8-bit byte;
3955 * if the integer occupies more than one byte (i.e,. is greater than 255),
3956 * appends only the low-order byte (similar to String#setbyte):
3957 *
3958 * s = ""
3959 * s.append_as_bytes(0, 257) # => "\u0000\u0001"
3960 * s.bytesize # => 2
3961 *
3962 * Related: see {Modifying}[rdoc-ref:String@Modifying].
3963 */
3964
3965VALUE
3966rb_str_append_as_bytes(int argc, VALUE *argv, VALUE str)
3967{
3968 long needed_capacity = 0;
3969 volatile VALUE t0;
3970 enum ruby_value_type *types = ALLOCV_N(enum ruby_value_type, t0, argc);
3971
3972 for (int index = 0; index < argc; index++) {
3973 VALUE obj = argv[index];
3974 enum ruby_value_type type = types[index] = rb_type(obj);
3975 switch (type) {
3976 case T_FIXNUM:
3977 case T_BIGNUM:
3978 needed_capacity++;
3979 break;
3980 case T_STRING:
3981 needed_capacity += RSTRING_LEN(obj);
3982 break;
3983 default:
3984 rb_raise(
3986 "wrong argument type %"PRIsVALUE" (expected String or Integer)",
3987 rb_obj_class(obj)
3988 );
3989 break;
3990 }
3991 }
3992
3993 str_ensure_available_capa(str, needed_capacity);
3994 char *sptr = RSTRING_END(str);
3995
3996 for (int index = 0; index < argc; index++) {
3997 VALUE obj = argv[index];
3998 enum ruby_value_type type = types[index];
3999 switch (type) {
4000 case T_FIXNUM:
4001 case T_BIGNUM: {
4002 argv[index] = obj = rb_int_and(obj, INT2FIX(0xff));
4003 char byte = (char)(NUM2INT(obj) & 0xFF);
4004 *sptr = byte;
4005 sptr++;
4006 break;
4007 }
4008 case T_STRING: {
4009 const char *ptr;
4010 long len;
4011 RSTRING_GETMEM(obj, ptr, len);
4012 memcpy(sptr, ptr, len);
4013 sptr += len;
4014 break;
4015 }
4016 default:
4017 rb_bug("append_as_bytes arguments should have been validated");
4018 }
4019 }
4020
4021 STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
4022 TERM_FILL(sptr, TERM_LEN(str)); /* sentinel */
4023
4024 int cr = ENC_CODERANGE(str);
4025 switch (cr) {
4026 case ENC_CODERANGE_7BIT: {
4027 for (int index = 0; index < argc; index++) {
4028 VALUE obj = argv[index];
4029 enum ruby_value_type type = types[index];
4030 switch (type) {
4031 case T_FIXNUM:
4032 case T_BIGNUM: {
4033 if (!ISASCII(NUM2INT(obj))) {
4034 goto clear_cr;
4035 }
4036 break;
4037 }
4038 case T_STRING: {
4039 if (ENC_CODERANGE(obj) != ENC_CODERANGE_7BIT) {
4040 goto clear_cr;
4041 }
4042 break;
4043 }
4044 default:
4045 rb_bug("append_as_bytes arguments should have been validated");
4046 }
4047 }
4048 break;
4049 }
4051 if (ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT) {
4052 goto keep_cr;
4053 }
4054 else {
4055 goto clear_cr;
4056 }
4057 break;
4058 default:
4059 goto clear_cr;
4060 break;
4061 }
4062
4063 RB_GC_GUARD(t0);
4064
4065 clear_cr:
4066 // If no fast path was hit, we clear the coderange.
4067 // append_as_bytes is predominantly meant to be used in
4068 // buffering situation, hence it's likely the coderange
4069 // will never be scanned, so it's not worth spending time
4070 // precomputing the coderange except for simple and common
4071 // situations.
4073 keep_cr:
4074 return str;
4075}
4076
4077/*
4078 * call-seq:
4079 * self << object -> self
4080 *
4081 * Appends a string representation of +object+ to +self+;
4082 * returns +self+.
4083 *
4084 * If +object+ is a string, appends it to +self+:
4085 *
4086 * s = 'foo'
4087 * s << 'bar' # => "foobar"
4088 * s # => "foobar"
4089 *
4090 * If +object+ is an integer,
4091 * its value is considered a codepoint;
4092 * converts the value to a character before concatenating:
4093 *
4094 * s = 'foo'
4095 * s << 33 # => "foo!"
4096 *
4097 * Additionally, if the codepoint is in range <tt>0..0xff</tt>
4098 * and the encoding of +self+ is Encoding::US_ASCII,
4099 * changes the encoding to Encoding::ASCII_8BIT:
4100 *
4101 * s = 'foo'.encode(Encoding::US_ASCII)
4102 * s.encoding # => #<Encoding:US-ASCII>
4103 * s << 0xff # => "foo\xFF"
4104 * s.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
4105 *
4106 * Raises RangeError if that codepoint is not representable in the encoding of +self+:
4107 *
4108 * s = 'foo'
4109 * s.encoding # => <Encoding:UTF-8>
4110 * s << 0x00110000 # 1114112 out of char range (RangeError)
4111 * s = 'foo'.encode(Encoding::EUC_JP)
4112 * s << 0x00800080 # invalid codepoint 0x800080 in EUC-JP (RangeError)
4113 *
4114 * Related: see {Modifying}[rdoc-ref:String@Modifying].
4115 */
4116VALUE
4118{
4119 unsigned int code;
4120 rb_encoding *enc = STR_ENC_GET(str1);
4121 int encidx;
4122
4123 if (RB_INTEGER_TYPE_P(str2)) {
4124 if (rb_num_to_uint(str2, &code) == 0) {
4125 }
4126 else if (FIXNUM_P(str2)) {
4127 rb_raise(rb_eRangeError, "%ld out of char range", FIX2LONG(str2));
4128 }
4129 else {
4130 rb_raise(rb_eRangeError, "bignum out of char range");
4131 }
4132 }
4133 else {
4134 return rb_str_append(str1, str2);
4135 }
4136
4137 encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
4138
4139 if (encidx >= 0) {
4140 rb_str_buf_cat_byte(str1, (unsigned char)code);
4141 }
4142 else {
4143 long pos = RSTRING_LEN(str1);
4144 int cr = ENC_CODERANGE(str1);
4145 int len;
4146 char *buf;
4147
4148 switch (len = rb_enc_codelen(code, enc)) {
4149 case ONIGERR_INVALID_CODE_POINT_VALUE:
4150 rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4151 break;
4152 case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
4153 case 0:
4154 rb_raise(rb_eRangeError, "%u out of char range", code);
4155 break;
4156 }
4157 buf = ALLOCA_N(char, len + 1);
4158 rb_enc_mbcput(code, buf, enc);
4159 if (rb_enc_precise_mbclen(buf, buf + len + 1, enc) != len) {
4160 rb_raise(rb_eRangeError, "invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4161 }
4162 rb_str_resize(str1, pos+len);
4163 memcpy(RSTRING_PTR(str1) + pos, buf, len);
4164 if (cr == ENC_CODERANGE_7BIT && code > 127) {
4166 }
4167 else if (cr == ENC_CODERANGE_BROKEN) {
4169 }
4170 ENC_CODERANGE_SET(str1, cr);
4171 }
4172 return str1;
4173}
4174
4175int
4176rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code)
4177{
4178 int encidx = rb_enc_to_index(enc);
4179
4180 if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII) {
4181 /* US-ASCII automatically extended to ASCII-8BIT */
4182 if (code > 0xFF) {
4183 rb_raise(rb_eRangeError, "%u out of char range", code);
4184 }
4185 if (encidx == ENCINDEX_US_ASCII && code > 127) {
4186 return ENCINDEX_ASCII_8BIT;
4187 }
4188 return encidx;
4189 }
4190 else {
4191 return -1;
4192 }
4193}
4194
4195/*
4196 * call-seq:
4197 * prepend(*other_strings) -> new_string
4198 *
4199 * Prefixes to +self+ the concatenation of the given +other_strings+; returns +self+:
4200 *
4201 * 'baz'.prepend('foo', 'bar') # => "foobarbaz"
4202 *
4203 * Related: see {Modifying}[rdoc-ref:String@Modifying].
4204 *
4205 */
4206
4207static VALUE
4208rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
4209{
4210 str_modifiable(str);
4211
4212 if (argc == 1) {
4213 rb_str_update(str, 0L, 0L, argv[0]);
4214 }
4215 else if (argc > 1) {
4216 int i;
4217 VALUE arg_str = rb_str_tmp_new(0);
4218 rb_enc_copy(arg_str, str);
4219 for (i = 0; i < argc; i++) {
4220 rb_str_append(arg_str, argv[i]);
4221 }
4222 rb_str_update(str, 0L, 0L, arg_str);
4223 }
4224
4225 return str;
4226}
4227
4228st_index_t
4230{
4231 if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) {
4232 st_index_t precomputed_hash;
4233 memcpy(&precomputed_hash, RSTRING_END(str) + TERM_LEN(str), sizeof(precomputed_hash));
4234
4235 RUBY_ASSERT(precomputed_hash == str_do_hash(str));
4236 return precomputed_hash;
4237 }
4238
4239 return str_do_hash(str);
4240}
4241
4242int
4244{
4245 long len1, len2;
4246 const char *ptr1, *ptr2;
4247 RSTRING_GETMEM(str1, ptr1, len1);
4248 RSTRING_GETMEM(str2, ptr2, len2);
4249 return (len1 != len2 ||
4250 !rb_str_comparable(str1, str2) ||
4251 memcmp(ptr1, ptr2, len1) != 0);
4252}
4253
4254/*
4255 * call-seq:
4256 * hash -> integer
4257 *
4258 * :include: doc/string/hash.rdoc
4259 *
4260 */
4261
4262static VALUE
4263rb_str_hash_m(VALUE str)
4264{
4265 st_index_t hval = rb_str_hash(str);
4266 return ST2FIX(hval);
4267}
4268
4269#define lesser(a,b) (((a)>(b))?(b):(a))
4270
4271int
4273{
4274 int idx1, idx2;
4275 int rc1, rc2;
4276
4277 if (RSTRING_LEN(str1) == 0) return TRUE;
4278 if (RSTRING_LEN(str2) == 0) return TRUE;
4279 idx1 = ENCODING_GET(str1);
4280 idx2 = ENCODING_GET(str2);
4281 if (idx1 == idx2) return TRUE;
4282 rc1 = rb_enc_str_coderange(str1);
4283 rc2 = rb_enc_str_coderange(str2);
4284 if (rc1 == ENC_CODERANGE_7BIT) {
4285 if (rc2 == ENC_CODERANGE_7BIT) return TRUE;
4286 if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
4287 return TRUE;
4288 }
4289 if (rc2 == ENC_CODERANGE_7BIT) {
4290 if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
4291 return TRUE;
4292 }
4293 return FALSE;
4294}
4295
4296int
4298{
4299 long len1, len2;
4300 const char *ptr1, *ptr2;
4301 int retval;
4302
4303 if (str1 == str2) return 0;
4304 RSTRING_GETMEM(str1, ptr1, len1);
4305 RSTRING_GETMEM(str2, ptr2, len2);
4306 if (ptr1 == ptr2 || (retval = memcmp(ptr1, ptr2, lesser(len1, len2))) == 0) {
4307 if (len1 == len2) {
4308 if (!rb_str_comparable(str1, str2)) {
4309 if (ENCODING_GET(str1) > ENCODING_GET(str2))
4310 return 1;
4311 return -1;
4312 }
4313 return 0;
4314 }
4315 if (len1 > len2) return 1;
4316 return -1;
4317 }
4318 if (retval > 0) return 1;
4319 return -1;
4320}
4321
4322/*
4323 * call-seq:
4324 * self == other -> true or false
4325 *
4326 * Returns whether +other+ is equal to +self+.
4327 *
4328 * When +other+ is a string, returns whether +other+ has the same length and content as +self+:
4329 *
4330 * s = 'foo'
4331 * s == 'foo' # => true
4332 * s == 'food' # => false
4333 * s == 'FOO' # => false
4334 *
4335 * Returns +false+ if the two strings' encodings are not compatible:
4336 *
4337 * "\u{e4 f6 fc}".encode(Encoding::ISO_8859_1) == ("\u{c4 d6 dc}") # => false
4338 *
4339 * When +other+ is not a string:
4340 *
4341 * - If +other+ responds to method <tt>to_str</tt>,
4342 * <tt>other == self</tt> is called and its return value is returned.
4343 * - If +other+ does not respond to <tt>to_str</tt>,
4344 * +false+ is returned.
4345 *
4346 * Related: {Comparing}[rdoc-ref:String@Comparing].
4347 */
4348
4349VALUE
4351{
4352 if (str1 == str2) return Qtrue;
4353 if (!RB_TYPE_P(str2, T_STRING)) {
4354 if (!rb_respond_to(str2, idTo_str)) {
4355 return Qfalse;
4356 }
4357 return rb_equal(str2, str1);
4358 }
4359 return rb_str_eql_internal(str1, str2);
4360}
4361
4362/*
4363 * call-seq:
4364 * eql?(object) -> true or false
4365 *
4366 * :include: doc/string/eql_p.rdoc
4367 *
4368 */
4369
4370VALUE
4371rb_str_eql(VALUE str1, VALUE str2)
4372{
4373 if (str1 == str2) return Qtrue;
4374 if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
4375 return rb_str_eql_internal(str1, str2);
4376}
4377
4378/*
4379 * call-seq:
4380 * self <=> other -> -1, 0, 1, or nil
4381 *
4382 * Compares +self+ and +other+,
4383 * evaluating their _contents_, not their _lengths_.
4384 *
4385 * Returns:
4386 *
4387 * - +-1+, if +self+ is smaller.
4388 * - +0+, if the two are equal.
4389 * - +1+, if +self+ is larger.
4390 * - +nil+, if the two are incomparable.
4391 *
4392 * Examples:
4393 *
4394 * 'a' <=> 'b' # => -1
4395 * 'a' <=> 'ab' # => -1
4396 * 'a' <=> 'a' # => 0
4397 * 'b' <=> 'a' # => 1
4398 * 'ab' <=> 'a' # => 1
4399 * 'a' <=> :a # => nil
4400 *
4401 * \Class \String includes module Comparable,
4402 * each of whose methods uses String#<=> for comparison.
4403 *
4404 * Related: see {Comparing}[rdoc-ref:String@Comparing].
4405 */
4406
4407static VALUE
4408rb_str_cmp_m(VALUE str1, VALUE str2)
4409{
4410 int result;
4411 VALUE s = rb_check_string_type(str2);
4412 if (NIL_P(s)) {
4413 return rb_invcmp(str1, str2);
4414 }
4415 result = rb_str_cmp(str1, s);
4416 return INT2FIX(result);
4417}
4418
4419static VALUE str_casecmp(VALUE str1, VALUE str2);
4420static VALUE str_casecmp_p(VALUE str1, VALUE str2);
4421
4422/*
4423 * call-seq:
4424 * casecmp(other_string) -> -1, 0, 1, or nil
4425 *
4426 * Ignoring case, compares +self+ and +other_string+; returns:
4427 *
4428 * - -1 if <tt>self.downcase</tt> is smaller than <tt>other_string.downcase</tt>.
4429 * - 0 if the two are equal.
4430 * - 1 if <tt>self.downcase</tt> is larger than <tt>other_string.downcase</tt>.
4431 * - +nil+ if the two are incomparable.
4432 *
4433 * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
4434 *
4435 * Examples:
4436 *
4437 * 'foo'.casecmp('goo') # => -1
4438 * 'goo'.casecmp('foo') # => 1
4439 * 'foo'.casecmp('food') # => -1
4440 * 'food'.casecmp('foo') # => 1
4441 * 'FOO'.casecmp('foo') # => 0
4442 * 'foo'.casecmp('FOO') # => 0
4443 * 'foo'.casecmp(1) # => nil
4444 *
4445 * Related: see {Comparing}[rdoc-ref:String@Comparing].
4446 */
4447
4448VALUE
4449rb_str_casecmp(VALUE str1, VALUE str2)
4450{
4451 VALUE s = rb_check_string_type(str2);
4452 if (NIL_P(s)) {
4453 return Qnil;
4454 }
4455 return str_casecmp(str1, s);
4456}
4457
4458static VALUE
4459str_casecmp(VALUE str1, VALUE str2)
4460{
4461 long len;
4462 rb_encoding *enc;
4463 const char *p1, *p1end, *p2, *p2end;
4464
4465 enc = rb_enc_compatible(str1, str2);
4466 if (!enc) {
4467 return Qnil;
4468 }
4469
4470 p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
4471 p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
4472 if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
4473 while (p1 < p1end && p2 < p2end) {
4474 if (*p1 != *p2) {
4475 unsigned int c1 = TOLOWER(*p1 & 0xff);
4476 unsigned int c2 = TOLOWER(*p2 & 0xff);
4477 if (c1 != c2)
4478 return INT2FIX(c1 < c2 ? -1 : 1);
4479 }
4480 p1++;
4481 p2++;
4482 }
4483 }
4484 else {
4485 while (p1 < p1end && p2 < p2end) {
4486 int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
4487 int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
4488
4489 if (0 <= c1 && 0 <= c2) {
4490 c1 = TOLOWER(c1);
4491 c2 = TOLOWER(c2);
4492 if (c1 != c2)
4493 return INT2FIX(c1 < c2 ? -1 : 1);
4494 }
4495 else {
4496 int r;
4497 l1 = rb_enc_mbclen(p1, p1end, enc);
4498 l2 = rb_enc_mbclen(p2, p2end, enc);
4499 len = l1 < l2 ? l1 : l2;
4500 r = memcmp(p1, p2, len);
4501 if (r != 0)
4502 return INT2FIX(r < 0 ? -1 : 1);
4503 if (l1 != l2)
4504 return INT2FIX(l1 < l2 ? -1 : 1);
4505 }
4506 p1 += l1;
4507 p2 += l2;
4508 }
4509 }
4510 if (p1 == p1end && p2 == p2end) return INT2FIX(0);
4511 if (p1 == p1end) return INT2FIX(-1);
4512 return INT2FIX(1);
4513}
4514
4515/*
4516 * call-seq:
4517 * casecmp?(other_string) -> true, false, or nil
4518 *
4519 * Returns +true+ if +self+ and +other_string+ are equal after
4520 * Unicode case folding, +false+ if unequal, +nil+ if incomparable.
4521 *
4522 * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
4523 *
4524 * Examples:
4525 *
4526 * 'foo'.casecmp?('goo') # => false
4527 * 'goo'.casecmp?('foo') # => false
4528 * 'foo'.casecmp?('food') # => false
4529 * 'food'.casecmp?('foo') # => false
4530 * 'FOO'.casecmp?('foo') # => true
4531 * 'foo'.casecmp?('FOO') # => true
4532 * 'foo'.casecmp?(1) # => nil
4533 *
4534 * Related: see {Comparing}[rdoc-ref:String@Comparing].
4535 */
4536
4537static VALUE
4538rb_str_casecmp_p(VALUE str1, VALUE str2)
4539{
4540 VALUE s = rb_check_string_type(str2);
4541 if (NIL_P(s)) {
4542 return Qnil;
4543 }
4544 return str_casecmp_p(str1, s);
4545}
4546
4547static VALUE
4548str_casecmp_p(VALUE str1, VALUE str2)
4549{
4550 rb_encoding *enc;
4551 VALUE folded_str1, folded_str2;
4552 VALUE fold_opt = sym_fold;
4553
4554 enc = rb_enc_compatible(str1, str2);
4555 if (!enc) {
4556 return Qnil;
4557 }
4558
4559 if (is_ascii_string(str1) && is_ascii_string(str2)) {
4560 if (RSTRING_LEN(str1) != RSTRING_LEN(str2)) return Qfalse;
4561 const char *p1 = RSTRING_PTR(str1), *p1end = RSTRING_END(str1);
4562 const char *p2 = RSTRING_PTR(str2);
4563 while (p1 < p1end) {
4564 if (*p1 != *p2 && TOLOWER((unsigned char)*p1) != TOLOWER((unsigned char)*p2)) {
4565 return Qfalse;
4566 }
4567 p1++;
4568 p2++;
4569 }
4570 return Qtrue;
4571 }
4572
4573 folded_str1 = rb_str_downcase(1, &fold_opt, str1);
4574 folded_str2 = rb_str_downcase(1, &fold_opt, str2);
4575
4576 return rb_str_eql(folded_str1, folded_str2);
4577}
4578
4579static long
4580strseq_core(const char *str_ptr, const char *str_ptr_end, long str_len,
4581 const char *sub_ptr, long sub_len, long offset, rb_encoding *enc)
4582{
4583 const char *search_start = str_ptr;
4584 long pos, search_len = str_len - offset;
4585
4586 for (;;) {
4587 const char *t;
4588 pos = rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
4589 if (pos < 0) return pos;
4590 t = rb_enc_right_char_head(search_start, search_start+pos, str_ptr_end, enc);
4591 if (t == search_start + pos) break;
4592 search_len -= t - search_start;
4593 if (search_len <= 0) return -1;
4594 offset += t - search_start;
4595 search_start = t;
4596 }
4597 return pos + offset;
4598}
4599
4600/* found index in byte */
4601#define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0)
4602#define rb_str_byteindex(str, sub, offset) rb_strseq_index(str, sub, offset, 1)
4603
4604static long
4605rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
4606{
4607 const char *str_ptr, *str_ptr_end, *sub_ptr;
4608 long str_len, sub_len;
4609 rb_encoding *enc;
4610
4611 enc = rb_enc_check(str, sub);
4612 if (is_broken_string(sub)) return -1;
4613
4614 str_ptr = RSTRING_PTR(str);
4615 str_ptr_end = RSTRING_END(str);
4616 str_len = RSTRING_LEN(str);
4617 sub_ptr = RSTRING_PTR(sub);
4618 sub_len = RSTRING_LEN(sub);
4619
4620 if (str_len < sub_len) return -1;
4621
4622 if (offset != 0) {
4623 long str_len_char, sub_len_char;
4624 int single_byte = single_byte_optimizable(str);
4625 str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc);
4626 sub_len_char = in_byte ? sub_len : str_strlen(sub, enc);
4627 if (offset < 0) {
4628 offset += str_len_char;
4629 if (offset < 0) return -1;
4630 }
4631 if (str_len_char - offset < sub_len_char) return -1;
4632 if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
4633 str_ptr += offset;
4634 }
4635 if (sub_len == 0) return offset;
4636
4637 /* need proceed one character at a time */
4638 return strseq_core(str_ptr, str_ptr_end, str_len, sub_ptr, sub_len, offset, enc);
4639}
4640
4641
4642/*
4643 * call-seq:
4644 * index(pattern, offset = 0) -> integer or nil
4645 *
4646 * :include: doc/string/index.rdoc
4647 *
4648 */
4649
4650static VALUE
4651rb_str_index_m(int argc, VALUE *argv, VALUE str)
4652{
4653 VALUE sub;
4654 VALUE initpos;
4655 rb_encoding *enc = STR_ENC_GET(str);
4656 long pos;
4657
4658 if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
4659 long slen = str_strlen(str, enc); /* str's enc */
4660 pos = NUM2LONG(initpos);
4661 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4662 if (RB_TYPE_P(sub, T_REGEXP)) {
4664 }
4665 return Qnil;
4666 }
4667 }
4668 else {
4669 pos = 0;
4670 }
4671
4672 if (RB_TYPE_P(sub, T_REGEXP)) {
4673 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
4674 enc, single_byte_optimizable(str));
4675
4676 if (rb_reg_search(sub, str, pos, 0) >= 0) {
4677 VALUE match = rb_backref_get();
4678 pos = rb_str_sublen(str, RMATCH_BEG(match, 0));
4679 return LONG2NUM(pos);
4680 }
4681 }
4682 else {
4683 StringValue(sub);
4684 pos = rb_str_index(str, sub, pos);
4685 if (pos >= 0) {
4686 pos = rb_str_sublen(str, pos);
4687 return LONG2NUM(pos);
4688 }
4689 }
4690 return Qnil;
4691}
4692
4693/* Ensure that the given pos is a valid character boundary.
4694 * Note that in this function, "character" means a code point
4695 * (Unicode scalar value), not a grapheme cluster.
4696 */
4697static void
4698str_ensure_byte_pos(VALUE str, long pos)
4699{
4700 if (!single_byte_optimizable(str)) {
4701 const char *s = RSTRING_PTR(str);
4702 const char *e = RSTRING_END(str);
4703 const char *p = s + pos;
4704 if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
4705 rb_raise(rb_eIndexError,
4706 "offset %ld does not land on character boundary", pos);
4707 }
4708 }
4709}
4710
4711/*
4712 * call-seq:
4713 * byteindex(object, offset = 0) -> integer or nil
4714 *
4715 * Returns the 0-based integer index of a substring of +self+
4716 * specified by +object+ (a string or Regexp) and +offset+,
4717 * or +nil+ if there is no such substring;
4718 * the returned index is the count of _bytes_ (not characters).
4719 *
4720 * When +object+ is a string,
4721 * returns the index of the first found substring equal to +object+:
4722 *
4723 * s = 'foo' # => "foo"
4724 * s.size # => 3 # Three 1-byte characters.
4725 * s.bytesize # => 3 # Three bytes.
4726 * s.byteindex('f') # => 0
4727 * s.byteindex('o') # => 1
4728 * s.byteindex('oo') # => 1
4729 * s.byteindex('ooo') # => nil
4730 *
4731 * When +object+ is a Regexp,
4732 * returns the index of the first found substring matching +object+;
4733 * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
4734 *
4735 * s = 'foo'
4736 * s.byteindex(/f/) # => 0
4737 * $~ # => #<MatchData "f">
4738 * s.byteindex(/o/) # => 1
4739 * s.byteindex(/oo/) # => 1
4740 * s.byteindex(/ooo/) # => nil
4741 * $~ # => nil
4742 *
4743 * \Integer argument +offset+, if given, specifies the 0-based index
4744 * of the byte where searching is to begin.
4745 *
4746 * When +offset+ is non-negative,
4747 * searching begins at byte position +offset+:
4748 *
4749 * s = 'foo'
4750 * s.byteindex('o', 1) # => 1
4751 * s.byteindex('o', 2) # => 2
4752 * s.byteindex('o', 3) # => nil
4753 *
4754 * When +offset+ is negative, counts backward from the end of +self+:
4755 *
4756 * s = 'foo'
4757 * s.byteindex('o', -1) # => 2
4758 * s.byteindex('o', -2) # => 1
4759 * s.byteindex('o', -3) # => 1
4760 * s.byteindex('o', -4) # => nil
4761 *
4762 * Raises IndexError if the byte at +offset+ is not the first byte of a character:
4763 *
4764 * s = "\uFFFF\uFFFF" # => "\uFFFF\uFFFF"
4765 * s.size # => 2 # Two 3-byte characters.
4766 * s.bytesize # => 6 # Six bytes.
4767 * s.byteindex("\uFFFF") # => 0
4768 * s.byteindex("\uFFFF", 1) # Raises IndexError
4769 * s.byteindex("\uFFFF", 2) # Raises IndexError
4770 * s.byteindex("\uFFFF", 3) # => 3
4771 * s.byteindex("\uFFFF", 4) # Raises IndexError
4772 * s.byteindex("\uFFFF", 5) # Raises IndexError
4773 * s.byteindex("\uFFFF", 6) # => nil
4774 *
4775 * Related: see {Querying}[rdoc-ref:String@Querying].
4776 */
4777
4778static VALUE
4779rb_str_byteindex_m(int argc, VALUE *argv, VALUE str)
4780{
4781 VALUE sub;
4782 VALUE initpos;
4783 long pos;
4784
4785 if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
4786 long slen = RSTRING_LEN(str);
4787 pos = NUM2LONG(initpos);
4788 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4789 if (RB_TYPE_P(sub, T_REGEXP)) {
4791 }
4792 return Qnil;
4793 }
4794 }
4795 else {
4796 pos = 0;
4797 }
4798
4799 str_ensure_byte_pos(str, pos);
4800
4801 if (RB_TYPE_P(sub, T_REGEXP)) {
4802 if (rb_reg_search(sub, str, pos, 0) >= 0) {
4803 VALUE match = rb_backref_get();
4804 pos = RMATCH_BEG(match, 0);
4805 return LONG2NUM(pos);
4806 }
4807 }
4808 else {
4809 StringValue(sub);
4810 pos = rb_str_byteindex(str, sub, pos);
4811 if (pos >= 0) return LONG2NUM(pos);
4812 }
4813 return Qnil;
4814}
4815
4816static long
4817str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
4818{
4819 const char *hit, *adjusted, *sbeg, *e, *t;
4820 int c;
4821 long slen, searchlen;
4822
4823 sbeg = RSTRING_PTR(str);
4824 slen = RSTRING_LEN(sub);
4825 if (slen == 0) return s - sbeg;
4826 e = RSTRING_END(str);
4827 t = RSTRING_PTR(sub);
4828 c = *t & 0xff;
4829 searchlen = s - sbeg + 1;
4830
4831 if (memcmp(s, t, slen) == 0) {
4832 return s - sbeg;
4833 }
4834
4835 do {
4836 hit = memrchr(sbeg, c, searchlen);
4837 if (!hit) break;
4838 adjusted = rb_enc_left_char_head(sbeg, hit, e, enc);
4839 if (hit != adjusted) {
4840 searchlen = adjusted - sbeg;
4841 continue;
4842 }
4843 if (memcmp(hit, t, slen) == 0)
4844 return hit - sbeg;
4845 searchlen = adjusted - sbeg;
4846 } while (searchlen > 0);
4847
4848 return -1;
4849}
4850
4851/* found index in byte */
4852static long
4853rb_str_rindex(VALUE str, VALUE sub, long pos)
4854{
4855 long len, slen;
4856 const char *sbeg, *s;
4857 rb_encoding *enc;
4858 int singlebyte;
4859
4860 enc = rb_enc_check(str, sub);
4861 if (is_broken_string(sub)) return -1;
4862 singlebyte = single_byte_optimizable(str);
4863 len = singlebyte ? RSTRING_LEN(str) : str_strlen(str, enc); /* rb_enc_check */
4864 slen = str_strlen(sub, enc); /* rb_enc_check */
4865
4866 /* substring longer than string */
4867 if (len < slen) return -1;
4868 if (len - pos < slen) pos = len - slen;
4869 if (len == 0) return pos;
4870
4871 sbeg = RSTRING_PTR(str);
4872
4873 if (pos == 0) {
4874 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4875 return 0;
4876 else
4877 return -1;
4878 }
4879
4880 s = str_nth(sbeg, RSTRING_END(str), pos, enc, singlebyte);
4881 return str_rindex(str, sub, s, enc);
4882}
4883
4884/*
4885 * call-seq:
4886 * rindex(pattern, offset = self.length) -> integer or nil
4887 *
4888 * :include:doc/string/rindex.rdoc
4889 *
4890 */
4891
4892static VALUE
4893rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
4894{
4895 VALUE sub;
4896 VALUE initpos;
4897 rb_encoding *enc = STR_ENC_GET(str);
4898 long pos, len = str_strlen(str, enc); /* str's enc */
4899
4900 if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
4901 pos = NUM2LONG(initpos);
4902 if (pos < 0 && (pos += len) < 0) {
4903 if (RB_TYPE_P(sub, T_REGEXP)) {
4905 }
4906 return Qnil;
4907 }
4908 if (pos > len) pos = len;
4909 }
4910 else {
4911 pos = len;
4912 }
4913
4914 if (RB_TYPE_P(sub, T_REGEXP)) {
4915 /* enc = rb_enc_check(str, sub); */
4916 pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
4917 enc, single_byte_optimizable(str));
4918
4919 if (rb_reg_search(sub, str, pos, 1) >= 0) {
4920 VALUE match = rb_backref_get();
4921 pos = rb_str_sublen(str, RMATCH_BEG(match, 0));
4922 return LONG2NUM(pos);
4923 }
4924 }
4925 else {
4926 StringValue(sub);
4927 pos = rb_str_rindex(str, sub, pos);
4928 if (pos >= 0) {
4929 pos = rb_str_sublen(str, pos);
4930 return LONG2NUM(pos);
4931 }
4932 }
4933 return Qnil;
4934}
4935
4936static long
4937rb_str_byterindex(VALUE str, VALUE sub, long pos)
4938{
4939 long len, slen;
4940 const char *sbeg, *s;
4941 rb_encoding *enc;
4942
4943 enc = rb_enc_check(str, sub);
4944 if (is_broken_string(sub)) return -1;
4945 len = RSTRING_LEN(str);
4946 slen = RSTRING_LEN(sub);
4947
4948 /* substring longer than string */
4949 if (len < slen) return -1;
4950 if (len - pos < slen) pos = len - slen;
4951 if (len == 0) return pos;
4952
4953 sbeg = RSTRING_PTR(str);
4954
4955 if (pos == 0) {
4956 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4957 return 0;
4958 else
4959 return -1;
4960 }
4961
4962 s = sbeg + pos;
4963 return str_rindex(str, sub, s, enc);
4964}
4965
4966/*
4967 * call-seq:
4968 * byterindex(object, offset = self.bytesize) -> integer or nil
4969 *
4970 * Returns the 0-based integer index of a substring of +self+
4971 * that is the _last_ match for the given +object+ (a string or Regexp) and +offset+,
4972 * or +nil+ if there is no such substring;
4973 * the returned index is the count of _bytes_ (not characters).
4974 *
4975 * When +object+ is a string,
4976 * returns the index of the _last_ found substring equal to +object+:
4977 *
4978 * s = 'foo' # => "foo"
4979 * s.size # => 3 # Three 1-byte characters.
4980 * s.bytesize # => 3 # Three bytes.
4981 * s.byterindex('f') # => 0
4982 * s.byterindex('o') # => 2
4983 * s.byterindex('oo') # => 1
4984 * s.byterindex('ooo') # => nil
4985 *
4986 * When +object+ is a Regexp,
4987 * returns the index of the last found substring matching +object+;
4988 * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
4989 *
4990 * s = 'foo'
4991 * s.byterindex(/f/) # => 0
4992 * $~ # => #<MatchData "f">
4993 * s.byterindex(/o/) # => 2
4994 * s.byterindex(/oo/) # => 1
4995 * s.byterindex(/ooo/) # => nil
4996 * $~ # => nil
4997 *
4998 * The last match means starting at the possible last position,
4999 * not the last of the longest matches:
5000 *
5001 * s = 'foo'
5002 * s.byterindex(/o+/) # => 2
5003 * $~ #=> #<MatchData "o">
5004 *
5005 * To get the last longest match, use a negative lookbehind:
5006 *
5007 * s = 'foo'
5008 * s.byterindex(/(?<!o)o+/) # => 1
5009 * $~ # => #<MatchData "oo">
5010 *
5011 * Or use method #byteindex with negative lookahead:
5012 *
5013 * s = 'foo'
5014 * s.byteindex(/o+(?!.*o)/) # => 1
5015 * $~ #=> #<MatchData "oo">
5016 *
5017 * \Integer argument +offset+, if given, specifies the 0-based index
5018 * of the byte where searching is to end.
5019 *
5020 * When +offset+ is non-negative,
5021 * searching ends at byte position +offset+:
5022 *
5023 * s = 'foo'
5024 * s.byterindex('o', 0) # => nil
5025 * s.byterindex('o', 1) # => 1
5026 * s.byterindex('o', 2) # => 2
5027 * s.byterindex('o', 3) # => 2
5028 *
5029 * When +offset+ is negative, counts backward from the end of +self+:
5030 *
5031 * s = 'foo'
5032 * s.byterindex('o', -1) # => 2
5033 * s.byterindex('o', -2) # => 1
5034 * s.byterindex('o', -3) # => nil
5035 *
5036 * Raises IndexError if the byte at +offset+ is not the first byte of a character:
5037 *
5038 * s = "\uFFFF\uFFFF" # => "\uFFFF\uFFFF"
5039 * s.size # => 2 # Two 3-byte characters.
5040 * s.bytesize # => 6 # Six bytes.
5041 * s.byterindex("\uFFFF") # => 3
5042 * s.byterindex("\uFFFF", 1) # Raises IndexError
5043 * s.byterindex("\uFFFF", 2) # Raises IndexError
5044 * s.byterindex("\uFFFF", 3) # => 3
5045 * s.byterindex("\uFFFF", 4) # Raises IndexError
5046 * s.byterindex("\uFFFF", 5) # Raises IndexError
5047 * s.byterindex("\uFFFF", 6) # => nil
5048 *
5049 * Related: see {Querying}[rdoc-ref:String@Querying].
5050 */
5051
5052static VALUE
5053rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
5054{
5055 VALUE sub;
5056 VALUE initpos;
5057 long pos, len = RSTRING_LEN(str);
5058
5059 if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
5060 pos = NUM2LONG(initpos);
5061 if (pos < 0 && (pos += len) < 0) {
5062 if (RB_TYPE_P(sub, T_REGEXP)) {
5064 }
5065 return Qnil;
5066 }
5067 if (pos > len) pos = len;
5068 }
5069 else {
5070 pos = len;
5071 }
5072
5073 str_ensure_byte_pos(str, pos);
5074
5075 if (RB_TYPE_P(sub, T_REGEXP)) {
5076 if (rb_reg_search(sub, str, pos, 1) >= 0) {
5077 VALUE match = rb_backref_get();
5078 pos = RMATCH_BEG(match, 0);
5079 return LONG2NUM(pos);
5080 }
5081 }
5082 else {
5083 StringValue(sub);
5084 pos = rb_str_byterindex(str, sub, pos);
5085 if (pos >= 0) return LONG2NUM(pos);
5086 }
5087 return Qnil;
5088}
5089
5090/*
5091 * call-seq:
5092 * self =~ other -> integer or nil
5093 *
5094 * When +other+ is a Regexp:
5095 *
5096 * - Returns the integer index (in characters) of the first match
5097 * for +self+ and +other+, or +nil+ if none;
5098 * - Updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables].
5099 *
5100 * Examples:
5101 *
5102 * 'foo' =~ /f/ # => 0
5103 * $~ # => #<MatchData "f">
5104 * 'foo' =~ /o/ # => 1
5105 * $~ # => #<MatchData "o">
5106 * 'foo' =~ /x/ # => nil
5107 * $~ # => nil
5108 *
5109 * Note that <tt>string =~ regexp</tt> is different from <tt>regexp =~ string</tt>
5110 * (see Regexp#=~):
5111 *
5112 * number = nil
5113 * 'no. 9' =~ /(?<number>\d+)/ # => 4
5114 * number # => nil # Not assigned.
5115 * /(?<number>\d+)/ =~ 'no. 9' # => 4
5116 * number # => "9" # Assigned.
5117 *
5118 * When +other+ is not a Regexp, returns the value
5119 * returned by <tt>other =~ self</tt>.
5120 *
5121 * Related: see {Querying}[rdoc-ref:String@Querying].
5122 */
5123
5124static VALUE
5125rb_str_match(VALUE x, VALUE y)
5126{
5127 switch (OBJ_BUILTIN_TYPE(y)) {
5128 case T_STRING:
5129 rb_raise(rb_eTypeError, "type mismatch: String given");
5130
5131 case T_REGEXP:
5132 return rb_reg_match(y, x);
5133
5134 default:
5135 return rb_funcall(y, idEqTilde, 1, x);
5136 }
5137}
5138
5139
5140static VALUE get_pat(VALUE);
5141
5142
5143/*
5144 * call-seq:
5145 * match(pattern, offset = 0) -> matchdata or nil
5146 * match(pattern, offset = 0) {|matchdata| ... } -> object
5147 *
5148 * Creates a MatchData object based on +self+ and the given arguments;
5149 * updates {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
5150 *
5151 * - Computes +regexp+ by converting +pattern+ (if not already a Regexp).
5152 *
5153 * regexp = Regexp.new(pattern)
5154 *
5155 * - Calls <tt>regexp.match</tt> with +self+ to compute +matchdata+.
5156 * If +offset+ is given, it is also passed (see Regexp#match).
5157 *
5158 * With no block given, returns the computed +matchdata+ or +nil+:
5159 *
5160 * 'foo'.match('f') # => #<MatchData "f">
5161 * 'foo'.match('o') # => #<MatchData "o">
5162 * 'foo'.match('x') # => nil
5163 * 'foo'.match('f', 1) # => nil
5164 * 'foo'.match('o', 1) # => #<MatchData "o">
5165 *
5166 * With a block given and computed +matchdata+ non-nil, calls the block with +matchdata+;
5167 * returns the block's return value:
5168 *
5169 * 'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">
5170 *
5171 * With a block given and +nil+ +matchdata+, does not call the block:
5172 *
5173 * 'foo'.match(/x/) {|matchdata| fail 'Cannot happen' } # => nil
5174 *
5175 * Related: see {Querying}[rdoc-ref:String@Querying].
5176 */
5177
5178static VALUE
5179rb_str_match_m(int argc, VALUE *argv, VALUE str)
5180{
5181 VALUE re, result;
5182 if (argc < 1)
5183 rb_check_arity(argc, 1, 2);
5184 re = argv[0];
5185 argv[0] = str;
5186 result = rb_funcallv(get_pat(re), rb_intern("match"), argc, argv);
5187 if (!NIL_P(result) && rb_block_given_p()) {
5188 return rb_yield(result);
5189 }
5190 return result;
5191}
5192
5193/*
5194 * call-seq:
5195 * match?(pattern, offset = 0) -> true or false
5196 *
5197 * Returns whether a match is found for +self+ and the given arguments;
5198 * does not update {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
5199 *
5200 * Computes +regexp+ by converting +pattern+ (if not already a Regexp):
5201 *
5202 * regexp = Regexp.new(pattern)
5203 *
5204 * The search for +regexp+ in +self+ begins at the given character +offset+.
5205 * Returns +true+ if a match is found, +false+ otherwise:
5206 *
5207 * 'foo'.match?(/o/) # => true
5208 * 'foo'.match?('o') # => true
5209 * 'foo'.match?(/x/) # => false
5210 * 'foo'.match?('f', 1) # => false
5211 * 'foo'.match?('o', 1) # => true
5212 *
5213 * Related: see {Querying}[rdoc-ref:String@Querying].
5214 */
5215
5216static VALUE
5217rb_str_match_m_p(int argc, VALUE *argv, VALUE str)
5218{
5219 VALUE re;
5220 rb_check_arity(argc, 1, 2);
5221 re = get_pat(argv[0]);
5222 return rb_reg_match_p(re, str, argc > 1 ? NUM2LONG(argv[1]) : 0);
5223}
5224
5225enum neighbor_char {
5226 NEIGHBOR_NOT_CHAR,
5227 NEIGHBOR_FOUND,
5228 NEIGHBOR_WRAPPED
5229};
5230
5231static enum neighbor_char
5232enc_succ_char(char *p, long len, rb_encoding *enc)
5233{
5234 long i;
5235 int l;
5236
5237 if (rb_enc_mbminlen(enc) > 1) {
5238 /* wchar, trivial case */
5239 int r = rb_enc_precise_mbclen(p, p + len, enc), c;
5240 if (!MBCLEN_CHARFOUND_P(r)) {
5241 return NEIGHBOR_NOT_CHAR;
5242 }
5243 c = rb_enc_mbc_to_codepoint(p, p + len, enc) + 1;
5244 l = rb_enc_code_to_mbclen(c, enc);
5245 if (!l) return NEIGHBOR_NOT_CHAR;
5246 if (l != len) return NEIGHBOR_WRAPPED;
5247 rb_enc_mbcput(c, p, enc);
5248 r = rb_enc_precise_mbclen(p, p + len, enc);
5249 if (!MBCLEN_CHARFOUND_P(r)) {
5250 return NEIGHBOR_NOT_CHAR;
5251 }
5252 return NEIGHBOR_FOUND;
5253 }
5254 while (1) {
5255 for (i = len-1; 0 <= i && (unsigned char)p[i] == 0xff; i--)
5256 p[i] = '\0';
5257 if (i < 0)
5258 return NEIGHBOR_WRAPPED;
5259 ++((unsigned char*)p)[i];
5260 l = rb_enc_precise_mbclen(p, p+len, enc);
5261 if (MBCLEN_CHARFOUND_P(l)) {
5262 l = MBCLEN_CHARFOUND_LEN(l);
5263 if (l == len) {
5264 return NEIGHBOR_FOUND;
5265 }
5266 else {
5267 memset(p+l, 0xff, len-l);
5268 }
5269 }
5270 if (MBCLEN_INVALID_P(l) && i < len-1) {
5271 long len2;
5272 int l2;
5273 for (len2 = len-1; 0 < len2; len2--) {
5274 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5275 if (!MBCLEN_INVALID_P(l2))
5276 break;
5277 }
5278 memset(p+len2+1, 0xff, len-(len2+1));
5279 }
5280 }
5281}
5282
5283static enum neighbor_char
5284enc_pred_char(char *p, long len, rb_encoding *enc)
5285{
5286 long i;
5287 int l;
5288 if (rb_enc_mbminlen(enc) > 1) {
5289 /* wchar, trivial case */
5290 int r = rb_enc_precise_mbclen(p, p + len, enc), c;
5291 if (!MBCLEN_CHARFOUND_P(r)) {
5292 return NEIGHBOR_NOT_CHAR;
5293 }
5294 c = rb_enc_mbc_to_codepoint(p, p + len, enc);
5295 if (!c) return NEIGHBOR_NOT_CHAR;
5296 --c;
5297 l = rb_enc_code_to_mbclen(c, enc);
5298 if (!l) return NEIGHBOR_NOT_CHAR;
5299 if (l != len) return NEIGHBOR_WRAPPED;
5300 rb_enc_mbcput(c, p, enc);
5301 r = rb_enc_precise_mbclen(p, p + len, enc);
5302 if (!MBCLEN_CHARFOUND_P(r)) {
5303 return NEIGHBOR_NOT_CHAR;
5304 }
5305 return NEIGHBOR_FOUND;
5306 }
5307 while (1) {
5308 for (i = len-1; 0 <= i && (unsigned char)p[i] == 0; i--)
5309 p[i] = '\xff';
5310 if (i < 0)
5311 return NEIGHBOR_WRAPPED;
5312 --((unsigned char*)p)[i];
5313 l = rb_enc_precise_mbclen(p, p+len, enc);
5314 if (MBCLEN_CHARFOUND_P(l)) {
5315 l = MBCLEN_CHARFOUND_LEN(l);
5316 if (l == len) {
5317 return NEIGHBOR_FOUND;
5318 }
5319 else {
5320 memset(p+l, 0, len-l);
5321 }
5322 }
5323 if (MBCLEN_INVALID_P(l) && i < len-1) {
5324 long len2;
5325 int l2;
5326 for (len2 = len-1; 0 < len2; len2--) {
5327 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5328 if (!MBCLEN_INVALID_P(l2))
5329 break;
5330 }
5331 memset(p+len2+1, 0, len-(len2+1));
5332 }
5333 }
5334}
5335
5336/*
5337 overwrite +p+ by succeeding letter in +enc+ and returns
5338 NEIGHBOR_FOUND or NEIGHBOR_WRAPPED.
5339 When NEIGHBOR_WRAPPED, carried-out letter is stored into carry.
5340 assuming each ranges are successive, and mbclen
5341 never change in each ranges.
5342 NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one
5343 character.
5344 */
5345static enum neighbor_char
5346enc_succ_alnum_char(char *p, long len, rb_encoding *enc, char *carry)
5347{
5348 enum neighbor_char ret;
5349 unsigned int c;
5350 int ctype;
5351 int range;
5352 char save[ONIGENC_CODE_TO_MBC_MAXLEN];
5353
5354 /* skip 03A2, invalid char between GREEK CAPITAL LETTERS */
5355 int try;
5356 const int max_gaps = 1;
5357
5358 c = rb_enc_mbc_to_codepoint(p, p+len, enc);
5359 if (rb_enc_isctype(c, ONIGENC_CTYPE_DIGIT, enc))
5360 ctype = ONIGENC_CTYPE_DIGIT;
5361 else if (rb_enc_isctype(c, ONIGENC_CTYPE_ALPHA, enc))
5362 ctype = ONIGENC_CTYPE_ALPHA;
5363 else
5364 return NEIGHBOR_NOT_CHAR;
5365
5366 MEMCPY(save, p, char, len);
5367 for (try = 0; try <= max_gaps; ++try) {
5368 ret = enc_succ_char(p, len, enc);
5369 if (ret == NEIGHBOR_FOUND) {
5370 c = rb_enc_mbc_to_codepoint(p, p+len, enc);
5371 if (rb_enc_isctype(c, ctype, enc))
5372 return NEIGHBOR_FOUND;
5373 }
5374 }
5375 MEMCPY(p, save, char, len);
5376 range = 1;
5377 while (1) {
5378 MEMCPY(save, p, char, len);
5379 ret = enc_pred_char(p, len, enc);
5380 if (ret == NEIGHBOR_FOUND) {
5381 c = rb_enc_mbc_to_codepoint(p, p+len, enc);
5382 if (!rb_enc_isctype(c, ctype, enc)) {
5383 MEMCPY(p, save, char, len);
5384 break;
5385 }
5386 }
5387 else {
5388 MEMCPY(p, save, char, len);
5389 break;
5390 }
5391 range++;
5392 }
5393 if (range == 1) {
5394 return NEIGHBOR_NOT_CHAR;
5395 }
5396
5397 if (ctype != ONIGENC_CTYPE_DIGIT) {
5398 MEMCPY(carry, p, char, len);
5399 return NEIGHBOR_WRAPPED;
5400 }
5401
5402 MEMCPY(carry, p, char, len);
5403 enc_succ_char(carry, len, enc);
5404 return NEIGHBOR_WRAPPED;
5405}
5406
5407
5408static VALUE str_succ(VALUE str);
5409
5410/*
5411 * call-seq:
5412 * succ -> new_str
5413 *
5414 * :include: doc/string/succ.rdoc
5415 *
5416 */
5417
5418VALUE
5420{
5421 VALUE str;
5422 str = rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
5423 rb_enc_cr_str_copy_for_substr(str, orig);
5424 return str_succ(str);
5425}
5426
5427static VALUE
5428str_succ(VALUE str)
5429{
5430 rb_encoding *enc;
5431 char *sbeg, *s, *e, *last_alnum = 0;
5432 int found_alnum = 0;
5433 long l, slen;
5434 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
5435 long carry_pos = 0, carry_len = 1;
5436 enum neighbor_char neighbor = NEIGHBOR_FOUND;
5437
5438 slen = RSTRING_LEN(str);
5439 if (slen == 0) return str;
5440
5441 enc = STR_ENC_GET(str);
5442 sbeg = RSTRING_PTR(str);
5443 s = e = sbeg + slen;
5444
5445 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5446 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
5447 if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
5448 ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
5449 break;
5450 }
5451 }
5452 l = rb_enc_precise_mbclen(s, e, enc);
5453 if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
5454 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5455 neighbor = enc_succ_alnum_char(s, l, enc, carry);
5456 switch (neighbor) {
5457 case NEIGHBOR_NOT_CHAR:
5458 continue;
5459 case NEIGHBOR_FOUND:
5460 return str;
5461 case NEIGHBOR_WRAPPED:
5462 last_alnum = s;
5463 break;
5464 }
5465 found_alnum = 1;
5466 carry_pos = s - sbeg;
5467 carry_len = l;
5468 }
5469 if (!found_alnum) { /* str contains no alnum */
5470 s = e;
5471 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5472 enum neighbor_char neighbor;
5473 char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
5474 l = rb_enc_precise_mbclen(s, e, enc);
5475 if (!ONIGENC_MBCLEN_CHARFOUND_P(l)) continue;
5476 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5477 MEMCPY(tmp, s, char, l);
5478 neighbor = enc_succ_char(tmp, l, enc);
5479 switch (neighbor) {
5480 case NEIGHBOR_FOUND:
5481 MEMCPY(s, tmp, char, l);
5482 return str;
5483 break;
5484 case NEIGHBOR_WRAPPED:
5485 MEMCPY(s, tmp, char, l);
5486 break;
5487 case NEIGHBOR_NOT_CHAR:
5488 break;
5489 }
5490 if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
5491 /* wrapped to \0...\0. search next valid char. */
5492 enc_succ_char(s, l, enc);
5493 }
5494 if (!rb_enc_asciicompat(enc)) {
5495 MEMCPY(carry, s, char, l);
5496 carry_len = l;
5497 }
5498 carry_pos = s - sbeg;
5499 }
5501 }
5502 RESIZE_CAPA(str, slen + carry_len);
5503 sbeg = RSTRING_PTR(str);
5504 s = sbeg + carry_pos;
5505 memmove(s + carry_len, s, slen - carry_pos);
5506 memmove(s, carry, carry_len);
5507 slen += carry_len;
5508 STR_SET_LEN(str, slen);
5509 TERM_FILL(&sbeg[slen], rb_enc_mbminlen(enc));
5510 rb_enc_str_coderange(str);
5511 return str;
5512}
5513
5514
5515/*
5516 * call-seq:
5517 * succ! -> self
5518 *
5519 * Like String#succ, but modifies +self+ in place; returns +self+.
5520 *
5521 * Related: see {Modifying}[rdoc-ref:String@Modifying].
5522 */
5523
5524static VALUE
5525rb_str_succ_bang(VALUE str)
5526{
5527 rb_str_modify(str);
5528 str_succ(str);
5529 return str;
5530}
5531
5532static int
5533all_digits_p(const char *s, long len)
5534{
5535 while (len-- > 0) {
5536 if (!ISDIGIT(*s)) return 0;
5537 s++;
5538 }
5539 return 1;
5540}
5541
5542static int
5543str_upto_i(VALUE str, VALUE arg)
5544{
5545 rb_yield(str);
5546 return 0;
5547}
5548
5549/*
5550 * call-seq:
5551 * upto(other_string, exclusive = false) {|string| ... } -> self
5552 * upto(other_string, exclusive = false) -> new_enumerator
5553 *
5554 * :include: doc/string/upto.rdoc
5555 *
5556 */
5557
5558static VALUE
5559rb_str_upto(int argc, VALUE *argv, VALUE beg)
5560{
5561 VALUE end, exclusive;
5562
5563 rb_scan_args(argc, argv, "11", &end, &exclusive);
5564 RETURN_ENUMERATOR(beg, argc, argv);
5565 return rb_str_upto_each(beg, end, RTEST(exclusive), str_upto_i, Qnil);
5566}
5567
5568VALUE
5569rb_str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALUE arg)
5570{
5571 VALUE current, after_end;
5572 ID succ;
5573 int n, ascii;
5574 rb_encoding *enc;
5575
5576 CONST_ID(succ, "succ");
5577 StringValue(end);
5578 enc = rb_enc_check(beg, end);
5579 ascii = (is_ascii_string(beg) && is_ascii_string(end));
5580 /* single character */
5581 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
5582 char c = RSTRING_PTR(beg)[0];
5583 char e = RSTRING_PTR(end)[0];
5584
5585 if (c > e || (excl && c == e)) return beg;
5586 for (;;) {
5587 VALUE str = rb_enc_str_new(&c, 1, enc);
5589 if ((*each)(str, arg)) break;
5590 if (!excl && c == e) break;
5591 c++;
5592 if (excl && c == e) break;
5593 }
5594 return beg;
5595 }
5596 /* both edges are all digits */
5597 if (ascii && ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0]) &&
5598 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
5599 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
5600 VALUE b, e;
5601 int width;
5602
5603 width = RSTRING_LENINT(beg);
5604 b = rb_str_to_inum(beg, 10, FALSE);
5605 e = rb_str_to_inum(end, 10, FALSE);
5606 if (FIXNUM_P(b) && FIXNUM_P(e)) {
5607 long bi = FIX2LONG(b);
5608 long ei = FIX2LONG(e);
5609 rb_encoding *usascii = rb_usascii_encoding();
5610
5611 while (bi <= ei) {
5612 if (excl && bi == ei) break;
5613 if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
5614 bi++;
5615 }
5616 }
5617 else {
5618 ID op = excl ? '<' : idLE;
5619 VALUE args[2], fmt = rb_fstring_lit("%.*d");
5620
5621 args[0] = INT2FIX(width);
5622 while (rb_funcall(b, op, 1, e)) {
5623 args[1] = b;
5624 if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
5625 b = rb_funcallv(b, succ, 0, 0);
5626 }
5627 }
5628 return beg;
5629 }
5630 /* normal case */
5631 n = rb_str_cmp(beg, end);
5632 if (n > 0 || (excl && n == 0)) return beg;
5633
5634 after_end = rb_funcallv(end, succ, 0, 0);
5635 current = str_duplicate(rb_cString, beg);
5636 while (!rb_str_equal(current, after_end)) {
5637 VALUE next = Qnil;
5638 if (excl || !rb_str_equal(current, end))
5639 next = rb_funcallv(current, succ, 0, 0);
5640 if ((*each)(current, arg)) break;
5641 if (NIL_P(next)) break;
5642 current = next;
5643 StringValue(current);
5644 if (excl && rb_str_equal(current, end)) break;
5645 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
5646 break;
5647 }
5648
5649 return beg;
5650}
5651
5652VALUE
5653rb_str_upto_endless_each(VALUE beg, int (*each)(VALUE, VALUE), VALUE arg)
5654{
5655 VALUE current;
5656 ID succ;
5657
5658 CONST_ID(succ, "succ");
5659 /* both edges are all digits */
5660 if (is_ascii_string(beg) && ISDIGIT(RSTRING_PTR(beg)[0]) &&
5661 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
5662 VALUE b, args[2], fmt = rb_fstring_lit("%.*d");
5663 int width = RSTRING_LENINT(beg);
5664 b = rb_str_to_inum(beg, 10, FALSE);
5665 if (FIXNUM_P(b)) {
5666 long bi = FIX2LONG(b);
5667 rb_encoding *usascii = rb_usascii_encoding();
5668
5669 while (FIXABLE(bi)) {
5670 if ((*each)(rb_enc_sprintf(usascii, "%.*ld", width, bi), arg)) break;
5671 bi++;
5672 }
5673 b = LONG2NUM(bi);
5674 }
5675 args[0] = INT2FIX(width);
5676 while (1) {
5677 args[1] = b;
5678 if ((*each)(rb_str_format(numberof(args), args, fmt), arg)) break;
5679 b = rb_funcallv(b, succ, 0, 0);
5680 }
5681 }
5682 /* normal case */
5683 current = str_duplicate(rb_cString, beg);
5684 while (1) {
5685 VALUE next = rb_funcallv(current, succ, 0, 0);
5686 if ((*each)(current, arg)) break;
5687 current = next;
5688 StringValue(current);
5689 if (RSTRING_LEN(current) == 0)
5690 break;
5691 }
5692
5693 return beg;
5694}
5695
5696static int
5697include_range_i(VALUE str, VALUE arg)
5698{
5699 VALUE *argp = (VALUE *)arg;
5700 if (!rb_equal(str, *argp)) return 0;
5701 *argp = Qnil;
5702 return 1;
5703}
5704
5705VALUE
5706rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive)
5707{
5708 beg = rb_str_new_frozen(beg);
5709 StringValue(end);
5710 end = rb_str_new_frozen(end);
5711 if (NIL_P(val)) return Qfalse;
5712 val = rb_check_string_type(val);
5713 if (NIL_P(val)) return Qfalse;
5714 if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
5715 rb_enc_asciicompat(STR_ENC_GET(end)) &&
5716 rb_enc_asciicompat(STR_ENC_GET(val))) {
5717 const char *bp = RSTRING_PTR(beg);
5718 const char *ep = RSTRING_PTR(end);
5719 const char *vp = RSTRING_PTR(val);
5720 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
5721 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
5722 return Qfalse;
5723 else {
5724 char b = *bp;
5725 char e = *ep;
5726 char v = *vp;
5727
5728 if (ISASCII(b) && ISASCII(e) && ISASCII(v)) {
5729 if (b <= v && v < e) return Qtrue;
5730 return RBOOL(!RTEST(exclusive) && v == e);
5731 }
5732 }
5733 }
5734#if 0
5735 /* both edges are all digits */
5736 if (ISDIGIT(*bp) && ISDIGIT(*ep) &&
5737 all_digits_p(bp, RSTRING_LEN(beg)) &&
5738 all_digits_p(ep, RSTRING_LEN(end))) {
5739 /* TODO */
5740 }
5741#endif
5742 }
5743 rb_str_upto_each(beg, end, RTEST(exclusive), include_range_i, (VALUE)&val);
5744
5745 return RBOOL(NIL_P(val));
5746}
5747
5748static VALUE
5749rb_str_subpat(VALUE str, VALUE re, VALUE backref)
5750{
5751 if (rb_reg_search(re, str, 0, 0) >= 0) {
5752 VALUE match = rb_backref_get();
5753 int nth = rb_reg_backref_number(match, backref);
5754 return rb_reg_nth_match(nth, match);
5755 }
5756 return Qnil;
5757}
5758
5759static VALUE
5760rb_str_aref(VALUE str, VALUE indx)
5761{
5762 long idx;
5763
5764 if (FIXNUM_P(indx)) {
5765 idx = FIX2LONG(indx);
5766 }
5767 else if (RB_TYPE_P(indx, T_REGEXP)) {
5768 return rb_str_subpat(str, indx, INT2FIX(0));
5769 }
5770 else if (RB_TYPE_P(indx, T_STRING)) {
5771 if (rb_str_index(str, indx, 0) != -1)
5772 return str_duplicate(rb_cString, indx);
5773 return Qnil;
5774 }
5775 else {
5776 /* check if indx is Range */
5777 long beg, len = str_strlen(str, NULL);
5778 switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
5779 case Qfalse:
5780 break;
5781 case Qnil:
5782 return Qnil;
5783 default:
5784 return rb_str_substr(str, beg, len);
5785 }
5786 idx = NUM2LONG(indx);
5787 }
5788
5789 return str_substr(str, idx, 1, FALSE);
5790}
5791
5792
5793/*
5794 * call-seq:
5795 * self[offset] -> new_string or nil
5796 * self[offset, size] -> new_string or nil
5797 * self[range] -> new_string or nil
5798 * self[regexp, capture = 0] -> new_string or nil
5799 * self[substring] -> new_string or nil
5800 *
5801 * :include: doc/string/aref.rdoc
5802 *
5803 */
5804
5805static VALUE
5806rb_str_aref_m(int argc, VALUE *argv, VALUE str)
5807{
5808 if (argc == 2) {
5809 if (RB_TYPE_P(argv[0], T_REGEXP)) {
5810 return rb_str_subpat(str, argv[0], argv[1]);
5811 }
5812 else {
5813 return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
5814 }
5815 }
5816 rb_check_arity(argc, 1, 2);
5817 return rb_str_aref(str, argv[0]);
5818}
5819
5820VALUE
5822{
5823 char *ptr = RSTRING_PTR(str);
5824 long olen = RSTRING_LEN(str), nlen;
5825
5826 str_modifiable(str);
5827 if (len > olen) len = olen;
5828 nlen = olen - len;
5829 if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
5830 char *oldptr = ptr;
5831 size_t old_capa = RSTRING(str)->as.heap.aux.capa + TERM_LEN(str);
5832 int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
5833 STR_SET_EMBED(str);
5834 ptr = RSTRING(str)->as.embed.ary;
5835 memmove(ptr, oldptr + len, nlen);
5836 if (fl == STR_NOEMBED) {
5837 SIZED_FREE_N(oldptr, old_capa);
5838 }
5839 }
5840 else {
5841 if (!STR_SHARED_P(str)) {
5842 VALUE shared = heap_str_make_shared(rb_obj_class(str), str);
5843 rb_enc_cr_str_exact_copy(shared, str);
5845 }
5846 ptr = RSTRING(str)->as.heap.ptr += len;
5847 }
5848 STR_SET_LEN(str, nlen);
5849
5850 if (!SHARABLE_MIDDLE_SUBSTRING) {
5851 TERM_FILL(ptr + nlen, TERM_LEN(str));
5852 }
5854 return str;
5855}
5856
5857static void
5858rb_str_update_1(VALUE str, long beg, long len, VALUE val, long vbeg, long vlen)
5859{
5860 char *sptr;
5861 long slen;
5862 int cr;
5863
5864 if (beg == 0 && vlen == 0) {
5865 rb_str_drop_bytes(str, len);
5866 return;
5867 }
5868
5869 str_modify_keep_cr(str);
5870 RSTRING_GETMEM(str, sptr, slen);
5871 if (len < vlen) {
5872 /* expand string */
5873 RESIZE_CAPA(str, slen + vlen - len);
5874 sptr = RSTRING_PTR(str);
5875 }
5876
5878 cr = rb_enc_str_coderange(val);
5879 else
5881
5882 if (vlen != len) {
5883 memmove(sptr + beg + vlen,
5884 sptr + beg + len,
5885 slen - (beg + len));
5886 }
5887 if (vlen < beg && len < 0) {
5888 MEMZERO(sptr + slen, char, -len);
5889 }
5890 if (vlen > 0) {
5891 memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
5892 }
5893 slen += vlen - len;
5894 STR_SET_LEN(str, slen);
5895 TERM_FILL(&sptr[slen], TERM_LEN(str));
5896 ENC_CODERANGE_SET(str, cr);
5897}
5898
5899static inline void
5900rb_str_update_0(VALUE str, long beg, long len, VALUE val)
5901{
5902 rb_str_update_1(str, beg, len, val, 0, RSTRING_LEN(val));
5903}
5904
5905void
5906rb_str_update(VALUE str, long beg, long len, VALUE val)
5907{
5908 long slen;
5909 char *p, *e;
5910 rb_encoding *enc;
5911 int singlebyte = single_byte_optimizable(str);
5912 int cr;
5913
5914 if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
5915
5916 StringValue(val);
5917 enc = rb_enc_check(str, val);
5918 slen = str_strlen(str, enc); /* rb_enc_check */
5919
5920 if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
5921 rb_raise(rb_eIndexError, "index %ld out of string", beg);
5922 }
5923 if (beg < 0) {
5924 beg += slen;
5925 }
5926 RUBY_ASSERT(beg >= 0);
5927 RUBY_ASSERT(beg <= slen);
5928
5929 if (len > slen - beg) {
5930 len = slen - beg;
5931 }
5932 p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte);
5933 if (!p) p = RSTRING_END(str);
5934 e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
5935 if (!e) e = RSTRING_END(str);
5936 /* error check */
5937 beg = p - RSTRING_PTR(str); /* physical position */
5938 len = e - p; /* physical length */
5939 rb_str_update_0(str, beg, len, val);
5940 rb_enc_associate(str, enc);
5942 if (cr != ENC_CODERANGE_BROKEN)
5943 ENC_CODERANGE_SET(str, cr);
5944}
5945
5946static void
5947rb_str_subpat_set(VALUE str, VALUE re, VALUE backref, VALUE val)
5948{
5949 int nth;
5950 VALUE match;
5951 long start, end, len;
5952 rb_encoding *enc;
5953
5954 if (rb_reg_search(re, str, 0, 0) < 0) {
5955 rb_raise(rb_eIndexError, "regexp not matched");
5956 }
5957 match = rb_backref_get();
5958 nth = rb_reg_backref_number(match, backref);
5959 int num_regs = RMATCH_NREGS(match);
5960 if ((nth >= num_regs) || ((nth < 0) && (-nth >= num_regs))) {
5961 rb_raise(rb_eIndexError, "index %d out of regexp", nth);
5962 }
5963 if (nth < 0) {
5964 nth += num_regs;
5965 }
5966
5967 start = RMATCH_BEG(match, nth);
5968 if (start == -1) {
5969 rb_raise(rb_eIndexError, "regexp group %d not matched", nth);
5970 }
5971 end = RMATCH_END(match, nth);
5972 len = end - start;
5973 StringValue(val);
5974 enc = rb_enc_check_str(str, val);
5975 rb_str_update_0(str, start, len, val);
5976 rb_enc_associate(str, enc);
5977}
5978
5979static VALUE
5980rb_str_aset(VALUE str, VALUE indx, VALUE val)
5981{
5982 long idx, beg;
5983
5984 switch (TYPE(indx)) {
5985 case T_REGEXP:
5986 rb_str_subpat_set(str, indx, INT2FIX(0), val);
5987 return val;
5988
5989 case T_STRING:
5990 beg = rb_str_index(str, indx, 0);
5991 if (beg < 0) {
5992 rb_raise(rb_eIndexError, "string not matched");
5993 }
5994 beg = rb_str_sublen(str, beg);
5995 rb_str_update(str, beg, str_strlen(indx, NULL), val);
5996 return val;
5997
5998 default:
5999 /* check if indx is Range */
6000 {
6001 long beg, len;
6002 if (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 2)) {
6003 rb_str_update(str, beg, len, val);
6004 return val;
6005 }
6006 }
6007 /* FALLTHROUGH */
6008
6009 case T_FIXNUM:
6010 idx = NUM2LONG(indx);
6011 rb_str_update(str, idx, 1, val);
6012 return val;
6013 }
6014}
6015
6016/*
6017 * call-seq:
6018 * self[index] = other_string -> new_string
6019 * self[start, length] = other_string -> new_string
6020 * self[range] = other_string -> new_string
6021 * self[regexp, capture = 0] = other_string -> new_string
6022 * self[substring] = other_string -> new_string
6023 *
6024 * :include: doc/string/aset.rdoc
6025 *
6026 */
6027
6028static VALUE
6029rb_str_aset_m(int argc, VALUE *argv, VALUE str)
6030{
6031 if (argc == 3) {
6032 if (RB_TYPE_P(argv[0], T_REGEXP)) {
6033 rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
6034 }
6035 else {
6036 rb_str_update(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
6037 }
6038 return argv[2];
6039 }
6040 rb_check_arity(argc, 2, 3);
6041 return rb_str_aset(str, argv[0], argv[1]);
6042}
6043
6044/*
6045 * call-seq:
6046 * insert(offset, other_string) -> self
6047 *
6048 * :include: doc/string/insert.rdoc
6049 *
6050 */
6051
6052static VALUE
6053rb_str_insert(VALUE str, VALUE idx, VALUE str2)
6054{
6055 long pos = NUM2LONG(idx);
6056
6057 if (pos == -1) {
6058 return rb_str_append(str, str2);
6059 }
6060 else if (pos < 0) {
6061 pos++;
6062 }
6063 rb_str_update(str, pos, 0, str2);
6064 return str;
6065}
6066
6067
6068/*
6069 * call-seq:
6070 * slice!(index) -> new_string or nil
6071 * slice!(start, length) -> new_string or nil
6072 * slice!(range) -> new_string or nil
6073 * slice!(regexp, capture = 0) -> new_string or nil
6074 * slice!(substring) -> new_string or nil
6075 *
6076 * Like String#[] (and its alias String#slice), except that:
6077 *
6078 * - Performs substitutions in +self+ (not in a copy of +self+).
6079 * - Returns the removed substring if any modifications were made, +nil+ otherwise.
6080 *
6081 * A few examples:
6082 *
6083 * s = 'hello'
6084 * s.slice!('e') # => "e"
6085 * s # => "hllo"
6086 * s.slice!('e') # => nil
6087 * s # => "hllo"
6088 *
6089 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6090 */
6091
6092static VALUE
6093rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
6094{
6095 VALUE result = Qnil;
6096 VALUE indx;
6097 long beg, len = 1;
6098 char *p;
6099
6100 rb_check_arity(argc, 1, 2);
6101 str_modify_keep_cr(str);
6102 indx = argv[0];
6103 if (RB_TYPE_P(indx, T_REGEXP)) {
6104 if (rb_reg_search(indx, str, 0, 0) < 0) return Qnil;
6105 VALUE match = rb_backref_get();
6106 int num_regs = RMATCH_NREGS(match);
6107 int nth = 0;
6108 if (argc > 1 && (nth = rb_reg_backref_number(match, argv[1])) < 0) {
6109 if ((nth += num_regs) <= 0) return Qnil;
6110 }
6111 else if (nth >= num_regs) return Qnil;
6112 beg = RMATCH_BEG(match, nth);
6113 len = RMATCH_END(match, nth) - beg;
6114 goto subseq;
6115 }
6116 else if (argc == 2) {
6117 beg = NUM2LONG(indx);
6118 len = NUM2LONG(argv[1]);
6119 goto num_index;
6120 }
6121 else if (FIXNUM_P(indx)) {
6122 beg = FIX2LONG(indx);
6123 if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
6124 if (!len) return Qnil;
6125 beg = p - RSTRING_PTR(str);
6126 goto subseq;
6127 }
6128 else if (RB_TYPE_P(indx, T_STRING)) {
6129 beg = rb_str_index(str, indx, 0);
6130 if (beg == -1) return Qnil;
6131 len = RSTRING_LEN(indx);
6132 result = str_duplicate(rb_cString, indx);
6133 goto squash;
6134 }
6135 else {
6136 switch (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 0)) {
6137 case Qnil:
6138 return Qnil;
6139 case Qfalse:
6140 beg = NUM2LONG(indx);
6141 if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
6142 if (!len) return Qnil;
6143 beg = p - RSTRING_PTR(str);
6144 goto subseq;
6145 default:
6146 goto num_index;
6147 }
6148 }
6149
6150 num_index:
6151 if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
6152 beg = p - RSTRING_PTR(str);
6153
6154 subseq:
6155 result = rb_str_new(RSTRING_PTR(str)+beg, len);
6156 rb_enc_cr_str_copy_for_substr(result, str);
6157
6158 squash:
6159 if (len > 0) {
6160 if (beg == 0) {
6161 rb_str_drop_bytes(str, len);
6162 }
6163 else {
6164 char *sptr = RSTRING_PTR(str);
6165 long slen = RSTRING_LEN(str);
6166 if (beg + len > slen) /* pathological check */
6167 len = slen - beg;
6168 memmove(sptr + beg,
6169 sptr + beg + len,
6170 slen - (beg + len));
6171 slen -= len;
6172 STR_SET_LEN(str, slen);
6173 TERM_FILL(&sptr[slen], TERM_LEN(str));
6174 }
6175 }
6176 return result;
6177}
6178
6179static VALUE
6180get_pat(VALUE pat)
6181{
6182 VALUE val;
6183
6184 switch (OBJ_BUILTIN_TYPE(pat)) {
6185 case T_REGEXP:
6186 return pat;
6187
6188 case T_STRING:
6189 break;
6190
6191 default:
6192 val = rb_check_string_type(pat);
6193 if (NIL_P(val)) {
6194 Check_Type(pat, T_REGEXP);
6195 }
6196 pat = val;
6197 }
6198
6199 return rb_reg_regcomp(pat);
6200}
6201
6202static VALUE
6203get_pat_quoted(VALUE pat, int check)
6204{
6205 VALUE val;
6206
6207 switch (OBJ_BUILTIN_TYPE(pat)) {
6208 case T_REGEXP:
6209 return pat;
6210
6211 case T_STRING:
6212 break;
6213
6214 default:
6215 val = rb_check_string_type(pat);
6216 if (NIL_P(val)) {
6217 Check_Type(pat, T_REGEXP);
6218 }
6219 pat = val;
6220 }
6221 if (check && is_broken_string(pat)) {
6222 rb_exc_raise(rb_reg_check_preprocess(pat));
6223 }
6224 return pat;
6225}
6226
6227static long
6228rb_pat_search0(VALUE pat, VALUE str, long pos, int set_backref_str, VALUE *match)
6229{
6230 if (BUILTIN_TYPE(pat) == T_STRING) {
6231 pos = rb_str_byteindex(str, pat, pos);
6232 if (set_backref_str) {
6233 if (pos >= 0) {
6234 str = rb_str_new_frozen_String(str);
6235 VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
6236 if (match) {
6237 *match = match_data;
6238 }
6239 }
6240 else {
6242 }
6243 }
6244 return pos;
6245 }
6246 else {
6247 return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
6248 }
6249}
6250
6251static long
6252rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
6253{
6254 return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
6255}
6256
6257
6258/*
6259 * call-seq:
6260 * sub!(pattern, replacement) -> self or nil
6261 * sub!(pattern) {|match| ... } -> self or nil
6262 *
6263 * Like String#sub, except that:
6264 *
6265 * - Changes are made to +self+, not to copy of +self+.
6266 * - Returns +self+ if any changes are made, +nil+ otherwise.
6267 *
6268 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6269 */
6270
6271static VALUE
6272rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
6273{
6274 VALUE pat, repl, hash = Qnil;
6275 int iter = 0;
6276 long plen;
6277 int min_arity = rb_block_given_p() ? 1 : 2;
6278 long beg;
6279
6280 rb_check_arity(argc, min_arity, 2);
6281 if (argc == 1) {
6282 iter = 1;
6283 }
6284 else {
6285 repl = argv[1];
6286 if (!RB_TYPE_P(repl, T_STRING)) {
6287 hash = rb_check_hash_type(repl);
6288 if (NIL_P(hash)) {
6289 StringValue(repl);
6290 }
6291 }
6292 }
6293
6294 pat = get_pat_quoted(argv[0], 1);
6295
6296 str_modifiable(str);
6297 beg = rb_pat_search(pat, str, 0, 1);
6298 if (beg >= 0) {
6299 rb_encoding *enc;
6300 int cr = ENC_CODERANGE(str);
6301 long beg0, end0;
6302 VALUE match, match0 = Qnil;
6303 char *p, *rp;
6304 long len, rlen;
6305
6306 match = rb_backref_get();
6307 if (RB_TYPE_P(pat, T_STRING)) {
6308 beg0 = beg;
6309 end0 = beg0 + RSTRING_LEN(pat);
6310 match0 = pat;
6311 }
6312 else {
6313 beg0 = RMATCH_BEG(match, 0);
6314 end0 = RMATCH_END(match, 0);
6315 if (iter) match0 = rb_reg_nth_match(0, match);
6316 }
6317
6318 if (iter || !NIL_P(hash)) {
6319 p = RSTRING_PTR(str); len = RSTRING_LEN(str);
6320
6321 if (iter) {
6322 repl = rb_obj_as_string(rb_yield(match0));
6323 }
6324 else {
6325 repl = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
6326 repl = rb_obj_as_string(repl);
6327 }
6328 str_mod_check(str, p, len);
6329 rb_check_frozen(str);
6330 }
6331 else {
6332 repl = rb_reg_regsub_match(repl, str, match);
6333 }
6334
6335 enc = rb_enc_compatible(str, repl);
6336 if (!enc) {
6337 rb_encoding *str_enc = STR_ENC_GET(str);
6338 p = RSTRING_PTR(str); len = RSTRING_LEN(str);
6339 if (coderange_scan(p, beg0, str_enc) != ENC_CODERANGE_7BIT ||
6340 coderange_scan(p+end0, len-end0, str_enc) != ENC_CODERANGE_7BIT) {
6341 rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
6342 rb_enc_inspect_name(str_enc),
6343 rb_enc_inspect_name(STR_ENC_GET(repl)));
6344 }
6345 enc = STR_ENC_GET(repl);
6346 }
6347 rb_str_modify(str);
6348 rb_enc_associate(str, enc);
6350 int cr2 = ENC_CODERANGE(repl);
6351 if (cr2 == ENC_CODERANGE_BROKEN ||
6352 (cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
6354 else
6355 cr = cr2;
6356 }
6357 plen = end0 - beg0;
6358 rlen = RSTRING_LEN(repl);
6359 len = RSTRING_LEN(str);
6360 if (rlen > plen) {
6361 RESIZE_CAPA(str, len + rlen - plen);
6362 }
6363 p = RSTRING_PTR(str);
6364 if (rlen != plen) {
6365 memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen);
6366 }
6367 rp = RSTRING_PTR(repl);
6368 memmove(p + beg0, rp, rlen);
6369 len += rlen - plen;
6370 STR_SET_LEN(str, len);
6371 TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
6372 ENC_CODERANGE_SET(str, cr);
6373
6374 RB_GC_GUARD(match);
6375
6376 return str;
6377 }
6378 return Qnil;
6379}
6380
6381
6382/*
6383 * call-seq:
6384 * sub(pattern, replacement) -> new_string
6385 * sub(pattern) {|match| ... } -> new_string
6386 *
6387 * :include: doc/string/sub.rdoc
6388 */
6389
6390static VALUE
6391rb_str_sub(int argc, VALUE *argv, VALUE str)
6392{
6393 str = str_duplicate(rb_cString, str);
6394 rb_str_sub_bang(argc, argv, str);
6395 return str;
6396}
6397
6398static VALUE
6399str_gsub(int argc, VALUE *argv, VALUE str, int bang)
6400{
6401 VALUE pat, val = Qnil, repl, match0 = Qnil, dest, hash = Qnil, match = Qnil;
6402 long beg, beg0, end0;
6403 long offset, blen, slen, len, last;
6404 enum {STR, ITER, FAST_MAP, MAP} mode = STR;
6405 char *sp, *cp;
6406 int need_backref_str = -1;
6407 rb_encoding *str_enc;
6408
6409 switch (argc) {
6410 case 1:
6411 RETURN_ENUMERATOR(str, argc, argv);
6412 mode = ITER;
6413 break;
6414 case 2:
6415 repl = argv[1];
6416 if (!RB_TYPE_P(repl, T_STRING)) {
6417 hash = rb_check_hash_type(repl);
6418 if (NIL_P(hash)) {
6419 StringValue(repl);
6420 }
6421 else if (rb_hash_default_unredefined(hash) && !FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
6422 mode = FAST_MAP;
6423 }
6424 else {
6425 mode = MAP;
6426 }
6427 }
6428 break;
6429 default:
6430 rb_error_arity(argc, 1, 2);
6431 }
6432
6433 pat = get_pat_quoted(argv[0], 1);
6434 beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
6435
6436 if (beg < 0) {
6437 if (bang) return Qnil; /* no match, no substitution */
6438 return str_duplicate(rb_cString, str);
6439 }
6440 if (bang) str_modify_keep_cr(str);
6441
6442 offset = 0;
6443 blen = RSTRING_LEN(str) + 30; /* len + margin */
6444 dest = rb_str_buf_new(blen);
6445 sp = RSTRING_PTR(str);
6446 slen = RSTRING_LEN(str);
6447 cp = sp;
6448 str_enc = STR_ENC_GET(str);
6449 rb_enc_associate(dest, str_enc);
6450 ENC_CODERANGE_SET(dest, rb_enc_asciicompat(str_enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);
6451
6452 do {
6453 if (RB_TYPE_P(pat, T_STRING)) {
6454 beg0 = beg;
6455 end0 = beg0 + RSTRING_LEN(pat);
6456 match0 = pat;
6457 }
6458 else {
6459 beg0 = RMATCH_BEG(match, 0);
6460 end0 = RMATCH_END(match, 0);
6461 if (mode == ITER) match0 = rb_reg_nth_match(0, match);
6462 }
6463
6464 if (mode != STR) {
6465 if (mode == ITER) {
6466 val = rb_obj_as_string(rb_yield(match0));
6467 }
6468 else {
6469 struct RString fake_str = {RBASIC_INIT};
6470 VALUE key;
6471 if (mode == FAST_MAP) {
6472 // It is safe to use a fake_str here because we established that it won't escape,
6473 // as it's only used for `rb_hash_aref` and we checked the hash doesn't have a
6474 // default proc.
6475 key = setup_fake_str(&fake_str, sp + beg0, end0 - beg0, ENCODING_GET_INLINED(str));
6476 }
6477 else {
6478 key = rb_str_subseq(str, beg0, end0 - beg0);
6479 }
6480 val = rb_hash_aref(hash, key);
6481 val = rb_obj_as_string(val);
6482 }
6483 str_mod_check(str, sp, slen);
6484 if (val == dest) { /* paranoid check [ruby-dev:24827] */
6485 rb_raise(rb_eRuntimeError, "block should not cheat");
6486 }
6487 }
6488 else if (need_backref_str) {
6489 val = rb_reg_regsub_match(repl, str, match);
6490 if (need_backref_str < 0) {
6491 need_backref_str = val != repl;
6492 }
6493 }
6494 else {
6495 val = repl;
6496 }
6497
6498 len = beg0 - offset; /* copy pre-match substr */
6499 if (len) {
6500 rb_enc_str_buf_cat(dest, cp, len, str_enc);
6501 }
6502
6503 rb_str_buf_append(dest, val);
6504
6505 last = offset;
6506 offset = end0;
6507 if (beg0 == end0) {
6508 /*
6509 * Always consume at least one character of the input string
6510 * in order to prevent infinite loops.
6511 */
6512 if (RSTRING_LEN(str) <= end0) break;
6513 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0, RSTRING_END(str), str_enc);
6514 rb_enc_str_buf_cat(dest, RSTRING_PTR(str)+end0, len, str_enc);
6515 offset = end0 + len;
6516 }
6517 cp = RSTRING_PTR(str) + offset;
6518 if (offset > RSTRING_LEN(str)) break;
6519
6520 // In FAST_MAP and STR mode the backref can't escape so we can re-use the MatchData safely.
6521 if (mode != FAST_MAP && mode != STR) {
6522 match = Qnil;
6523 }
6524 beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
6525
6526 RB_GC_GUARD(match);
6527 } while (beg >= 0);
6528
6529 if (RSTRING_LEN(str) > offset) {
6530 rb_enc_str_buf_cat(dest, cp, RSTRING_LEN(str) - offset, str_enc);
6531 }
6532 rb_pat_search0(pat, str, last, 1, &match);
6533 if (bang) {
6534 str_shared_replace(str, dest);
6535 }
6536 else {
6537 str = dest;
6538 }
6539
6540 return str;
6541}
6542
6543
6544/*
6545 * call-seq:
6546 * gsub!(pattern, replacement) -> self or nil
6547 * gsub!(pattern) {|match| ... } -> self or nil
6548 * gsub!(pattern) -> an_enumerator
6549 *
6550 * Like String#gsub, except that:
6551 *
6552 * - Performs substitutions in +self+ (not in a copy of +self+).
6553 * - Returns +self+ if any substitutions were performed, +nil+ otherwise.
6554 *
6555 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6556 */
6557
6558static VALUE
6559rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
6560{
6561 str_modifiable(str);
6562 return str_gsub(argc, argv, str, 1);
6563}
6564
6565
6566/*
6567 * call-seq:
6568 * gsub(pattern, replacement) -> new_string
6569 * gsub(pattern) {|match| ... } -> new_string
6570 * gsub(pattern) -> enumerator
6571 *
6572 * Returns a copy of +self+ with zero or more substrings replaced.
6573 *
6574 * Argument +pattern+ may be a string or a Regexp;
6575 * argument +replacement+ may be a string or a Hash.
6576 * Varying types for the argument values makes this method very versatile.
6577 *
6578 * Below are some simple examples;
6579 * for many more examples, see {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
6580 *
6581 * With arguments +pattern+ and string +replacement+ given,
6582 * replaces each matching substring with the given +replacement+ string:
6583 *
6584 * s = 'abracadabra'
6585 * s.gsub('ab', 'AB') # => "ABracadABra"
6586 * s.gsub(/[a-c]/, 'X') # => "XXrXXXdXXrX"
6587 *
6588 * With arguments +pattern+ and hash +replacement+ given,
6589 * replaces each matching substring with a value from the given +replacement+ hash,
6590 * or removes it:
6591 *
6592 * h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
6593 * s.gsub(/[a-c]/, h) # => "ABrACAdABrA" # 'a', 'b', 'c' replaced.
6594 * s.gsub(/[a-d]/, h) # => "ABrACAABrA" # 'd' removed.
6595 *
6596 * With argument +pattern+ and a block given,
6597 * calls the block with each matching substring;
6598 * replaces that substring with the block's return value:
6599 *
6600 * s.gsub(/[a-d]/) {|substring| substring.upcase }
6601 * # => "ABrACADABrA"
6602 *
6603 * With argument +pattern+ and no block given,
6604 * returns a new Enumerator.
6605 *
6606 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
6607 */
6608
6609static VALUE
6610rb_str_gsub(int argc, VALUE *argv, VALUE str)
6611{
6612 return str_gsub(argc, argv, str, 0);
6613}
6614
6615
6616/*
6617 * call-seq:
6618 * replace(other_string) -> self
6619 *
6620 * Replaces the contents of +self+ with the contents of +other_string+;
6621 * returns +self+:
6622 *
6623 * s = 'foo' # => "foo"
6624 * s.replace('bar') # => "bar"
6625 *
6626 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6627 */
6628
6629VALUE
6631{
6632 str_modifiable(str);
6633 if (str == str2) return str;
6634
6635 StringValue(str2);
6636 str_discard(str);
6637 return str_replace(str, str2);
6638}
6639
6640/*
6641 * call-seq:
6642 * clear -> self
6643 *
6644 * Removes the contents of +self+:
6645 *
6646 * s = 'foo'
6647 * s.clear # => ""
6648 * s # => ""
6649 *
6650 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6651 */
6652
6653static VALUE
6654rb_str_clear(VALUE str)
6655{
6656 str_discard(str);
6657 STR_SET_EMBED(str);
6658 STR_SET_LEN(str, 0);
6659 RSTRING_PTR(str)[0] = 0;
6660 if (rb_enc_asciicompat(STR_ENC_GET(str)))
6662 else
6664 return str;
6665}
6666
6667/*
6668 * call-seq:
6669 * chr -> string
6670 *
6671 * :include: doc/string/chr.rdoc
6672 *
6673 */
6674
6675static VALUE
6676rb_str_chr(VALUE str)
6677{
6678 return rb_str_substr(str, 0, 1);
6679}
6680
6681/*
6682 * call-seq:
6683 * getbyte(index) -> integer or nil
6684 *
6685 * :include: doc/string/getbyte.rdoc
6686 *
6687 */
6688VALUE
6689rb_str_getbyte(VALUE str, VALUE index)
6690{
6691 long pos = NUM2LONG(index);
6692
6693 if (pos < 0)
6694 pos += RSTRING_LEN(str);
6695 if (pos < 0 || RSTRING_LEN(str) <= pos)
6696 return Qnil;
6697
6698 return INT2FIX((unsigned char)RSTRING_PTR(str)[pos]);
6699}
6700
6701/*
6702 * call-seq:
6703 * setbyte(index, integer) -> integer
6704 *
6705 * Sets the byte at zero-based offset +index+ to the value of the given +integer+;
6706 * returns +integer+:
6707 *
6708 * s = 'xyzzy'
6709 * s.setbyte(2, 129) # => 129
6710 * s # => "xy\x81zy"
6711 *
6712 * Related: see {Modifying}[rdoc-ref:String@Modifying].
6713 */
6714VALUE
6715rb_str_setbyte(VALUE str, VALUE index, VALUE value)
6716{
6717 long pos = NUM2LONG(index);
6718 long len = RSTRING_LEN(str);
6719 char *ptr, *head, *left = 0;
6720 rb_encoding *enc;
6721 int cr = ENC_CODERANGE_UNKNOWN, width, nlen;
6722
6723 if (pos < -len || len <= pos)
6724 rb_raise(rb_eIndexError, "index %ld out of string", pos);
6725 if (pos < 0)
6726 pos += len;
6727
6728 VALUE v = rb_to_int(value);
6729 VALUE w = rb_int_and(v, INT2FIX(0xff));
6730 char byte = (char)(NUM2INT(w) & 0xFF);
6731
6732 if (!str_independent(str))
6733 str_make_independent(str);
6734 enc = STR_ENC_GET(str);
6735 head = RSTRING_PTR(str);
6736 ptr = &head[pos];
6737 if (!STR_EMBED_P(str)) {
6738 cr = ENC_CODERANGE(str);
6739 switch (cr) {
6740 case ENC_CODERANGE_7BIT:
6741 left = ptr;
6742 *ptr = byte;
6743 if (ISASCII(byte)) goto end;
6744 nlen = rb_enc_precise_mbclen(left, head+len, enc);
6745 if (!MBCLEN_CHARFOUND_P(nlen))
6747 else
6749 goto end;
6751 left = rb_enc_left_char_head(head, ptr, head+len, enc);
6752 width = rb_enc_precise_mbclen(left, head+len, enc);
6753 *ptr = byte;
6754 nlen = rb_enc_precise_mbclen(left, head+len, enc);
6755 if (!MBCLEN_CHARFOUND_P(nlen))
6757 else if (MBCLEN_CHARFOUND_LEN(nlen) != width || ISASCII(byte))
6759 goto end;
6760 }
6761 }
6763 *ptr = byte;
6764
6765 end:
6766 return value;
6767}
6768
6769static inline bool
6770str_bit_offset_out_of_range(long byte_len, uint64_t bit_offset)
6771{
6772 /* Compare byte indexes to avoid overflowing byte_len * CHAR_BIT. */
6773 return bit_offset / CHAR_BIT >= (uint64_t)byte_len;
6774}
6775
6776/*
6777 * Keep both the full bit offset and its long representation. Most calls use a
6778 * Fixnum-sized offset and can stay on the original long fast path; only large
6779 * Bignum offsets need the uint64_t path below. This matters on platforms
6780 * where long is narrower than the address space, such as 32-bit and LLP64.
6781 */
6783 uint64_t value;
6784 long long_value;
6785 bool fits_long;
6786};
6787
6788static inline struct str_bit_offset
6789str_bit_offset_from_index(VALUE index)
6790{
6791 VALUE integer = rb_to_int(index);
6792 struct str_bit_offset offset;
6793
6794 /*
6795 * FIXNUM_P only decides whether the common long path is immediately usable.
6796 * This covers practically all offsets on LP64 platforms; Bignum offsets
6797 * are still accepted below when they fit in uint64_t, mainly for platforms
6798 * with 32-bit long where large strings can have Bignum bit offsets.
6799 */
6800 if (FIXNUM_P(integer)) {
6801 offset.long_value = FIX2LONG(integer);
6802 if (offset.long_value < 0) {
6803 rb_raise(rb_eIndexError, "bit index out of range");
6804 }
6805 offset.value = (uint64_t)offset.long_value;
6806 offset.fits_long = true;
6807 return offset;
6808 }
6809
6810 RUBY_ASSERT(RB_TYPE_P(integer, T_BIGNUM));
6811 if (rb_int_negative_p(integer)) {
6812 rb_raise(rb_eIndexError, "bit index out of range");
6813 }
6814 if (rb_cmpint(rb_int_cmp(integer, ULL2NUM(UINT64_MAX)), integer, ULL2NUM(UINT64_MAX)) > 0) {
6815 rb_raise(rb_eArgError, "bit index out of representable range");
6816 }
6817
6818 offset.value = (uint64_t)NUM2ULL(integer);
6819 if (offset.value <= (uint64_t)LONG_MAX) {
6820 offset.long_value = (long)offset.value;
6821 offset.fits_long = true;
6822 }
6823 else {
6824 offset.long_value = 0;
6825 offset.fits_long = false;
6826 }
6827 return offset;
6828}
6829
6830static bool
6831str_lsb_first(int argc, VALUE *argv, VALUE *index)
6832{
6833 static ID keywords[1];
6834 VALUE opts, vlsb_first;
6835
6836 if (!keywords[0]) {
6837 keywords[0] = rb_intern_const("lsb_first");
6838 }
6839
6840 rb_scan_args(argc, argv, "1:", index, &opts);
6841 rb_get_kwargs(opts, keywords, 0, 1, &vlsb_first);
6842 if (vlsb_first == Qundef || vlsb_first == Qtrue) {
6843 return true;
6844 }
6845 if (vlsb_first == Qfalse) {
6846 return false;
6847 }
6848 rb_raise(rb_eArgError, "lsb_first must be true or false");
6849 UNREACHABLE_RETURN(false);
6850}
6851
6852static inline uint64_t
6853str_logical_to_physical_bit64(uint64_t logical, bool lsb_first)
6854{
6855 return lsb_first ? logical : ((logical & ~(uint64_t)7) | (7 - (logical & 7)));
6856}
6857
6858static inline long
6859str_logical_to_physical_bit(long logical, bool lsb_first)
6860{
6861 return lsb_first ? logical : ((logical & ~7L) | (7 - (logical & 7L)));
6862}
6863
6865 long byte_index;
6866 unsigned int bit_offset;
6867};
6868
6869static inline struct str_bit_location
6870str_bit_location_from_offset(uint64_t logical, bool lsb_first)
6871{
6872 /*
6873 * When long is 32-bit, a bit offset for a large string can be a Bignum
6874 * while the byte index still fits in long, which is RSTRING_LEN's type.
6875 */
6876 uint64_t physical = str_logical_to_physical_bit64(logical, lsb_first);
6877 struct str_bit_location location;
6878 location.byte_index = (long)(physical / CHAR_BIT);
6879 location.bit_offset = (unsigned int)(physical % CHAR_BIT);
6880 return location;
6881}
6882
6883static inline int
6884str_get_bit(const char *ptr, long bit_index)
6885{
6886 return (((unsigned char)ptr[bit_index / CHAR_BIT]) >> (bit_index % CHAR_BIT)) & 1;
6887}
6888
6889static inline int
6890str_get_bit_location(const char *ptr, struct str_bit_location location)
6891{
6892 return (((unsigned char)ptr[location.byte_index]) >> location.bit_offset) & 1;
6893}
6894
6895static int
6896str_bit_get(int argc, VALUE *argv, VALUE str)
6897{
6898 VALUE index;
6899 bool lsb_first = str_lsb_first(argc, argv, &index);
6900 struct str_bit_offset offset = str_bit_offset_from_index(index);
6901
6902 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6903 return -1;
6904 }
6905
6906 if (offset.fits_long) {
6907 return str_get_bit(RSTRING_PTR(str), str_logical_to_physical_bit(offset.long_value, lsb_first));
6908 }
6909 else {
6910 return str_get_bit_location(RSTRING_PTR(str), str_bit_location_from_offset(offset.value, lsb_first));
6911 }
6912}
6913
6914/*
6915 * call-seq:
6916 * bit_get(offset, lsb_first: true) -> 0, 1, or nil
6917 *
6918 * :include: doc/string/bit_get.rdoc
6919 *
6920 */
6921static VALUE
6922rb_str_bit_get(int argc, VALUE *argv, VALUE str)
6923{
6924 int bit = str_bit_get(argc, argv, str);
6925 return bit < 0 ? Qnil : INT2FIX(bit);
6926}
6927
6928/*
6929 * call-seq:
6930 * bit_set?(offset, lsb_first: true) -> true, false, or nil
6931 *
6932 * :include: doc/string/bit_set_p.rdoc
6933 *
6934 */
6935static VALUE
6936rb_str_bit_set_p(int argc, VALUE *argv, VALUE str)
6937{
6938 int bit = str_bit_get(argc, argv, str);
6939 return bit < 0 ? Qnil : RBOOL(bit);
6940}
6941
6942enum str_bit_mutation {
6943 STR_BIT_SET,
6944 STR_BIT_CLEAR,
6945 STR_BIT_FLIP
6946};
6947
6948static VALUE
6949str_mutate_bit(int argc, VALUE *argv, VALUE str, enum str_bit_mutation mutation)
6950{
6951 VALUE index;
6952 bool lsb_first = str_lsb_first(argc, argv, &index);
6953 struct str_bit_offset offset = str_bit_offset_from_index(index);
6954 struct str_bit_location location;
6955 long bit_index;
6956 unsigned char *ptr;
6957 unsigned char mask;
6958
6959 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6960 rb_raise(rb_eIndexError, "bit index out of range");
6961 }
6962
6963 rb_str_modify(str);
6964 ptr = (unsigned char *)RSTRING_PTR(str);
6965 if (offset.fits_long) {
6966 bit_index = str_logical_to_physical_bit(offset.long_value, lsb_first);
6967 mask = (unsigned char)(1u << (bit_index % CHAR_BIT));
6968 location.byte_index = bit_index / CHAR_BIT;
6969 }
6970 else {
6971 location = str_bit_location_from_offset(offset.value, lsb_first);
6972 mask = (unsigned char)(1u << location.bit_offset);
6973 }
6974
6975 switch (mutation) {
6976 case STR_BIT_SET:
6977 ptr[location.byte_index] |= mask;
6978 break;
6979 case STR_BIT_CLEAR:
6980 ptr[location.byte_index] &= (unsigned char)~mask;
6981 break;
6982 case STR_BIT_FLIP:
6983 ptr[location.byte_index] ^= mask;
6984 break;
6985 }
6986
6987 return str;
6988}
6989
6990/*
6991 * call-seq:
6992 * bit_set(offset, lsb_first: true) -> self
6993 *
6994 * :include: doc/string/bit_set.rdoc
6995 *
6996 */
6997static VALUE
6998rb_str_bit_set(int argc, VALUE *argv, VALUE str)
6999{
7000 return str_mutate_bit(argc, argv, str, STR_BIT_SET);
7001}
7002
7003/*
7004 * call-seq:
7005 * bit_clear(offset, lsb_first: true) -> self
7006 *
7007 * :include: doc/string/bit_clear.rdoc
7008 *
7009 */
7010static VALUE
7011rb_str_bit_clear(int argc, VALUE *argv, VALUE str)
7012{
7013 return str_mutate_bit(argc, argv, str, STR_BIT_CLEAR);
7014}
7015
7016/*
7017 * call-seq:
7018 * bit_flip(offset, lsb_first: true) -> self
7019 *
7020 * :include: doc/string/bit_flip.rdoc
7021 *
7022 */
7023static VALUE
7024rb_str_bit_flip(int argc, VALUE *argv, VALUE str)
7025{
7026 return str_mutate_bit(argc, argv, str, STR_BIT_FLIP);
7027}
7028
7029static uint64_t
7030str_count_bits(const unsigned char *ptr, long len)
7031{
7032 uint64_t count = 0;
7033 long off = 0;
7034 long unrolled_end = len & ~31L;
7035 long aligned_end = len & ~7L;
7036
7037 // 32 bytes (256 bits) at a time
7038 for (; off < unrolled_end; off += 32) {
7039 uint64_t w0, w1, w2, w3;
7040 memcpy(&w0, ptr + off, 8);
7041 memcpy(&w1, ptr + off + 8, 8);
7042 memcpy(&w2, ptr + off + 16, 8);
7043 memcpy(&w3, ptr + off + 24, 8);
7044 count += rb_popcount64(w0);
7045 count += rb_popcount64(w1);
7046 count += rb_popcount64(w2);
7047 count += rb_popcount64(w3);
7048 }
7049
7050 // 8 bytes (64 bits) at a time
7051 for (; off < aligned_end; off += 8) {
7052 uint64_t word;
7053 memcpy(&word, ptr + off, 8);
7054 count += rb_popcount64(word);
7055 }
7056
7057 // remaining bytes
7058 if (off < len) {
7059 uint64_t word = 0;
7060 int shift = 0;
7061 for (; off < len; off++, shift += CHAR_BIT) {
7062 word |= (uint64_t)ptr[off] << shift;
7063 }
7064 count += rb_popcount64(word);
7065 }
7066
7067 return count;
7068}
7069
7070/*
7071 * call-seq:
7072 * bit_count -> integer
7073 *
7074 * :include: doc/string/bit_count.rdoc
7075 *
7076 */
7077static VALUE
7078rb_str_bit_count(VALUE str)
7079{
7080 return ULL2NUM(str_count_bits((const unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)));
7081}
7082
7083static void
7084str_check_bitwise_length(VALUE str, VALUE other)
7085{
7086 if (RSTRING_LEN(str) != RSTRING_LEN(other)) {
7087 rb_raise(rb_eArgError, "operands must have the same length (%ld vs %ld)",
7088 RSTRING_LEN(str), RSTRING_LEN(other));
7089 }
7090}
7091
7092static VALUE
7093str_bitwise_result(VALUE str)
7094{
7095 long len = RSTRING_LEN(str);
7096 VALUE result = rb_str_buf_new(len);
7097 rb_str_resize(result, len);
7098 rb_enc_associate(result, rb_ascii8bit_encoding());
7099 ENC_CODERANGE_CLEAR(result);
7100 return result;
7101}
7102
7103#define STR_DEFINE_UNARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7104 static void \
7105 name(unsigned char *dst, const unsigned char *src, long len) \
7106 { \
7107 long off = 0; \
7108 long unrolled_end = len & ~31L; \
7109 long aligned_end = len & ~7L; \
7110 for (; off < unrolled_end; off += 32) { \
7111 uint64_t s0, s1, s2, s3; \
7112 memcpy(&s0, src + off, 8); \
7113 memcpy(&s1, src + off + 8, 8); \
7114 memcpy(&s2, src + off + 16, 8); \
7115 memcpy(&s3, src + off + 24, 8); \
7116 s0 = (expr_word(s0)); \
7117 s1 = (expr_word(s1)); \
7118 s2 = (expr_word(s2)); \
7119 s3 = (expr_word(s3)); \
7120 memcpy(dst + off, &s0, 8); \
7121 memcpy(dst + off + 8, &s1, 8); \
7122 memcpy(dst + off + 16, &s2, 8); \
7123 memcpy(dst + off + 24, &s3, 8); \
7124 } \
7125 for (; off < aligned_end; off += 8) { \
7126 uint64_t word; \
7127 memcpy(&word, src + off, 8); \
7128 word = (expr_word(word)); \
7129 memcpy(dst + off, &word, 8); \
7130 } \
7131 for (; off < len; off++) dst[off] = (expr_byte(src[off])); \
7132 }
7133
7134#define STR_DEFINE_BINARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7135 static void \
7136 name(unsigned char *dst, const unsigned char *lhs, \
7137 const unsigned char *rhs, long len) \
7138 { \
7139 long off = 0; \
7140 long unrolled_end = len & ~31L; \
7141 long aligned_end = len & ~7L; \
7142 for (; off < unrolled_end; off += 32) { \
7143 uint64_t l0, l1, l2, l3, r0, r1, r2, r3; \
7144 memcpy(&l0, lhs + off, 8); memcpy(&r0, rhs + off, 8); \
7145 memcpy(&l1, lhs + off + 8, 8); memcpy(&r1, rhs + off + 8, 8); \
7146 memcpy(&l2, lhs + off + 16, 8); memcpy(&r2, rhs + off + 16, 8); \
7147 memcpy(&l3, lhs + off + 24, 8); memcpy(&r3, rhs + off + 24, 8); \
7148 l0 = expr_word(l0, r0); \
7149 l1 = expr_word(l1, r1); \
7150 l2 = expr_word(l2, r2); \
7151 l3 = expr_word(l3, r3); \
7152 memcpy(dst + off, &l0, 8); \
7153 memcpy(dst + off + 8, &l1, 8); \
7154 memcpy(dst + off + 16, &l2, 8); \
7155 memcpy(dst + off + 24, &l3, 8); \
7156 } \
7157 for (; off < aligned_end; off += 8) { \
7158 uint64_t lhs_word, rhs_word; \
7159 memcpy(&lhs_word, lhs + off, 8); \
7160 memcpy(&rhs_word, rhs + off, 8); \
7161 lhs_word = expr_word(lhs_word, rhs_word); \
7162 memcpy(dst + off, &lhs_word, 8); \
7163 } \
7164 for (; off < len; off++) dst[off] = expr_byte(lhs[off], rhs[off]); \
7165 }
7166
7167#define STR_BITWISE_NOT_WORD(x) (~(x))
7168#define STR_BITWISE_NOT_BYTE(x) ((unsigned char)~(x))
7169#define STR_BITWISE_AND_WORD(x, y) ((x) & (y))
7170#define STR_BITWISE_AND_BYTE(x, y) ((unsigned char)((x) & (y)))
7171#define STR_BITWISE_OR_WORD(x, y) ((x) | (y))
7172#define STR_BITWISE_OR_BYTE(x, y) ((unsigned char)((x) | (y)))
7173#define STR_BITWISE_XOR_WORD(x, y) ((x) ^ (y))
7174#define STR_BITWISE_XOR_BYTE(x, y) ((unsigned char)((x) ^ (y)))
7175
7176STR_DEFINE_UNARY_BITWISE_KERNEL(str_bitwise_not, STR_BITWISE_NOT_WORD, STR_BITWISE_NOT_BYTE)
7177STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_and, STR_BITWISE_AND_WORD, STR_BITWISE_AND_BYTE)
7178STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_or, STR_BITWISE_OR_WORD, STR_BITWISE_OR_BYTE)
7179STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_xor, STR_BITWISE_XOR_WORD, STR_BITWISE_XOR_BYTE)
7180
7181/*
7182 * call-seq:
7183 * bitwise_not -> string
7184 *
7185 * :include: doc/string/bitwise_not.rdoc
7186 *
7187 */
7188static VALUE
7189rb_str_bitwise_not(VALUE str)
7190{
7191 long len = RSTRING_LEN(str);
7192 VALUE result = str_bitwise_result(str);
7193 str_bitwise_not((unsigned char *)RSTRING_PTR(result),
7194 (const unsigned char *)RSTRING_PTR(str), len);
7195 return result;
7196}
7197
7198/*
7199 * call-seq:
7200 * bitwise_not! -> self
7201 *
7202 * :include: doc/string/bitwise_not_bang.rdoc
7203 *
7204 */
7205static VALUE
7206rb_str_bitwise_not_bang(VALUE str)
7207{
7208 long len;
7209 unsigned char *ptr;
7210
7211 rb_str_modify(str);
7212 len = RSTRING_LEN(str);
7213 ptr = (unsigned char *)RSTRING_PTR(str);
7214 str_bitwise_not(ptr, ptr, len);
7215 return str;
7216}
7217
7218#define STR_DEFINE_BINARY_BITWISE_METHOD(name) \
7219 static VALUE \
7220 rb_str_bitwise_##name(VALUE str, VALUE other) \
7221 { \
7222 long len; \
7223 VALUE result; \
7224 StringValue(other); \
7225 str_check_bitwise_length(str, other); \
7226 len = RSTRING_LEN(str); \
7227 result = str_bitwise_result(str); \
7228 str_bitwise_##name((unsigned char *)RSTRING_PTR(result), \
7229 (const unsigned char *)RSTRING_PTR(str), \
7230 (const unsigned char *)RSTRING_PTR(other), len); \
7231 return result; \
7232 } \
7233 static VALUE \
7234 rb_str_bitwise_##name##_bang(VALUE str, VALUE other) \
7235 { \
7236 long len; \
7237 unsigned char *ptr; \
7238 StringValue(other); \
7239 str_check_bitwise_length(str, other); \
7240 rb_str_modify(str); \
7241 len = RSTRING_LEN(str); \
7242 ptr = (unsigned char *)RSTRING_PTR(str); \
7243 str_bitwise_##name(ptr, ptr, \
7244 (const unsigned char *)RSTRING_PTR(other), len); \
7245 return str; \
7246 }
7247
7248STR_DEFINE_BINARY_BITWISE_METHOD(and)
7249STR_DEFINE_BINARY_BITWISE_METHOD(or)
7250STR_DEFINE_BINARY_BITWISE_METHOD(xor)
7251
7252static VALUE
7253str_byte_substr(VALUE str, long beg, long len, int empty)
7254{
7255 long n = RSTRING_LEN(str);
7256
7257 if (beg > n || len < 0) return Qnil;
7258 if (beg < 0) {
7259 beg += n;
7260 if (beg < 0) return Qnil;
7261 }
7262 if (len > n - beg)
7263 len = n - beg;
7264 if (len <= 0) {
7265 if (!empty) return Qnil;
7266 len = 0;
7267 }
7268
7269 VALUE str2 = str_subseq(str, beg, len);
7270
7271 str_enc_copy_direct(str2, str);
7272
7273 if (RSTRING_LEN(str2) == 0) {
7274 if (!rb_enc_asciicompat(STR_ENC_GET(str)))
7276 else
7278 }
7279 else {
7280 switch (ENC_CODERANGE(str)) {
7281 case ENC_CODERANGE_7BIT:
7283 break;
7284 default:
7286 break;
7287 }
7288 }
7289
7290 return str2;
7291}
7292
7293VALUE
7294rb_str_byte_substr(VALUE str, VALUE beg, VALUE len)
7295{
7296 return str_byte_substr(str, NUM2LONG(beg), NUM2LONG(len), TRUE);
7297}
7298
7299static VALUE
7300str_byte_aref(VALUE str, VALUE indx)
7301{
7302 long idx;
7303 if (FIXNUM_P(indx)) {
7304 idx = FIX2LONG(indx);
7305 }
7306 else {
7307 /* check if indx is Range */
7308 long beg, len = RSTRING_LEN(str);
7309
7310 switch (rb_range_beg_len(indx, &beg, &len, len, 0)) {
7311 case Qfalse:
7312 break;
7313 case Qnil:
7314 return Qnil;
7315 default:
7316 return str_byte_substr(str, beg, len, TRUE);
7317 }
7318
7319 idx = NUM2LONG(indx);
7320 }
7321 return str_byte_substr(str, idx, 1, FALSE);
7322}
7323
7324/*
7325 * call-seq:
7326 * byteslice(offset, length = 1) -> string or nil
7327 * byteslice(range) -> string or nil
7328 *
7329 * :include: doc/string/byteslice.rdoc
7330 */
7331
7332static VALUE
7333rb_str_byteslice(int argc, VALUE *argv, VALUE str)
7334{
7335 if (argc == 2) {
7336 long beg = NUM2LONG(argv[0]);
7337 long len = NUM2LONG(argv[1]);
7338 return str_byte_substr(str, beg, len, TRUE);
7339 }
7340 rb_check_arity(argc, 1, 2);
7341 return str_byte_aref(str, argv[0]);
7342}
7343
7344static void
7345str_check_beg_len(VALUE str, long *beg, long *len)
7346{
7347 long end, slen = RSTRING_LEN(str);
7348
7349 if (*len < 0) rb_raise(rb_eIndexError, "negative length %ld", *len);
7350 if ((slen < *beg) || ((*beg < 0) && (*beg + slen < 0))) {
7351 rb_raise(rb_eIndexError, "index %ld out of string", *beg);
7352 }
7353 if (*beg < 0) {
7354 *beg += slen;
7355 }
7356 RUBY_ASSERT(*beg >= 0);
7357 RUBY_ASSERT(*beg <= slen);
7358
7359 if (*len > slen - *beg) {
7360 *len = slen - *beg;
7361 }
7362 end = *beg + *len;
7363 str_ensure_byte_pos(str, *beg);
7364 str_ensure_byte_pos(str, end);
7365}
7366
7367/*
7368 * call-seq:
7369 * bytesplice(offset, length, str) -> self
7370 * bytesplice(offset, length, str, str_offset, str_length) -> self
7371 * bytesplice(range, str) -> self
7372 * bytesplice(range, str, str_range) -> self
7373 *
7374 * :include: doc/string/bytesplice.rdoc
7375 */
7376
7377static VALUE
7378rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
7379{
7380 long beg, len, vbeg, vlen;
7381 VALUE val;
7382 int cr;
7383
7384 rb_check_arity(argc, 2, 5);
7385 if (!(argc == 2 || argc == 3 || argc == 5)) {
7386 rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
7387 }
7388 if (argc == 2 || (argc == 3 && !RB_INTEGER_TYPE_P(argv[0]))) {
7389 if (!rb_range_beg_len(argv[0], &beg, &len, RSTRING_LEN(str), 2)) {
7390 rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
7391 rb_builtin_class_name(argv[0]));
7392 }
7393 val = argv[1];
7394 StringValue(val);
7395 if (argc == 2) {
7396 /* bytesplice(range, str) */
7397 vbeg = 0;
7398 vlen = RSTRING_LEN(val);
7399 }
7400 else {
7401 /* bytesplice(range, str, str_range) */
7402 if (!rb_range_beg_len(argv[2], &vbeg, &vlen, RSTRING_LEN(val), 2)) {
7403 rb_raise(rb_eTypeError, "wrong argument type %s (expected Range)",
7404 rb_builtin_class_name(argv[2]));
7405 }
7406 }
7407 }
7408 else {
7409 beg = NUM2LONG(argv[0]);
7410 len = NUM2LONG(argv[1]);
7411 val = argv[2];
7412 StringValue(val);
7413 if (argc == 3) {
7414 /* bytesplice(index, length, str) */
7415 vbeg = 0;
7416 vlen = RSTRING_LEN(val);
7417 }
7418 else {
7419 /* bytesplice(index, length, str, str_index, str_length) */
7420 vbeg = NUM2LONG(argv[3]);
7421 vlen = NUM2LONG(argv[4]);
7422 }
7423 }
7424 str_check_beg_len(str, &beg, &len);
7425 str_check_beg_len(val, &vbeg, &vlen);
7426 str_modify_keep_cr(str);
7427
7428 if (RB_UNLIKELY(ENCODING_GET_INLINED(str) != ENCODING_GET_INLINED(val))) {
7429 rb_enc_associate(str, rb_enc_check(str, val));
7430 }
7431
7432 rb_str_update_1(str, beg, len, val, vbeg, vlen);
7434 if (cr != ENC_CODERANGE_BROKEN)
7435 ENC_CODERANGE_SET(str, cr);
7436 return str;
7437}
7438
7439/*
7440 * call-seq:
7441 * reverse -> new_string
7442 *
7443 * Returns a new string with the characters from +self+ in reverse order.
7444 *
7445 * 'drawer'.reverse # => "reward"
7446 * 'reviled'.reverse # => "deliver"
7447 * 'stressed'.reverse # => "desserts"
7448 * 'semordnilaps'.reverse # => "spalindromes"
7449 *
7450 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
7451 */
7452
7453static VALUE
7454rb_str_reverse(VALUE str)
7455{
7456 rb_encoding *enc;
7457 VALUE rev;
7458 char *s, *e, *p;
7459 int cr;
7460
7461 if (RSTRING_LEN(str) <= 1) return str_duplicate(rb_cString, str);
7462 enc = STR_ENC_GET(str);
7463 rev = rb_str_new(0, RSTRING_LEN(str));
7464 s = RSTRING_PTR(str); e = RSTRING_END(str);
7465 p = RSTRING_END(rev);
7466 cr = ENC_CODERANGE(str);
7467
7468 if (RSTRING_LEN(str) > 1) {
7469 if (single_byte_optimizable(str)) {
7470 while (s < e) {
7471 *--p = *s++;
7472 }
7473 }
7474 else if (cr == ENC_CODERANGE_VALID) {
7475 while (s < e) {
7476 int clen = rb_enc_fast_mbclen(s, e, enc);
7477
7478 p -= clen;
7479 memcpy(p, s, clen);
7480 s += clen;
7481 }
7482 }
7483 else {
7484 cr = rb_enc_asciicompat(enc) ?
7486 while (s < e) {
7487 int clen = rb_enc_mbclen(s, e, enc);
7488
7489 if (clen > 1 || (*s & 0x80)) cr = ENC_CODERANGE_UNKNOWN;
7490 p -= clen;
7491 memcpy(p, s, clen);
7492 s += clen;
7493 }
7494 }
7495 }
7496 STR_SET_LEN(rev, RSTRING_LEN(str));
7497 str_enc_copy_direct(rev, str);
7498 ENC_CODERANGE_SET(rev, cr);
7499
7500 return rev;
7501}
7502
7503
7504/*
7505 * call-seq:
7506 * reverse! -> self
7507 *
7508 * Returns +self+ with its characters reversed:
7509 *
7510 * 'drawer'.reverse! # => "reward"
7511 * 'reviled'.reverse! # => "deliver"
7512 * 'stressed'.reverse! # => "desserts"
7513 * 'semordnilaps'.reverse! # => "spalindromes"
7514 *
7515 * Related: see {Modifying}[rdoc-ref:String@Modifying].
7516 */
7517
7518static VALUE
7519rb_str_reverse_bang(VALUE str)
7520{
7521 if (RSTRING_LEN(str) > 1) {
7522 if (single_byte_optimizable(str)) {
7523 char *s, *e, c;
7524
7525 str_modify_keep_cr(str);
7526 s = RSTRING_PTR(str);
7527 e = RSTRING_END(str) - 1;
7528 while (s < e) {
7529 c = *s;
7530 *s++ = *e;
7531 *e-- = c;
7532 }
7533 }
7534 else {
7535 str_shared_replace(str, rb_str_reverse(str));
7536 }
7537 }
7538 else {
7539 str_modify_keep_cr(str);
7540 }
7541 return str;
7542}
7543
7544
7545/*
7546 * call-seq:
7547 * include?(other_string) -> true or false
7548 *
7549 * Returns whether +self+ contains +other_string+:
7550 *
7551 * s = 'bar'
7552 * s.include?('ba') # => true
7553 * s.include?('ar') # => true
7554 * s.include?('bar') # => true
7555 * s.include?('a') # => true
7556 * s.include?('') # => true
7557 * s.include?('foo') # => false
7558 *
7559 * Related: see {Querying}[rdoc-ref:String@Querying].
7560 */
7561
7562VALUE
7563rb_str_include(VALUE str, VALUE arg)
7564{
7565 long i;
7566
7567 StringValue(arg);
7568 i = rb_str_index(str, arg, 0);
7569
7570 return RBOOL(i != -1);
7571}
7572
7573
7574/*
7575 * call-seq:
7576 * to_i(base = 10) -> integer
7577 *
7578 * Returns the result of interpreting leading characters in +self+
7579 * as an integer in the given +base+;
7580 * +base+ must be either +0+ or in range <tt>(2..36)</tt>:
7581 *
7582 * '123456'.to_i # => 123456
7583 * '123def'.to_i(16) # => 1195503
7584 *
7585 * With +base+ zero given, string +object+ may contain leading characters
7586 * to specify the actual base:
7587 *
7588 * '123def'.to_i(0) # => 123
7589 * '0123def'.to_i(0) # => 83
7590 * '0b123def'.to_i(0) # => 1
7591 * '0o123def'.to_i(0) # => 83
7592 * '0d123def'.to_i(0) # => 123
7593 * '0x123def'.to_i(0) # => 1195503
7594 *
7595 * Characters past a leading valid number (in the given +base+) are ignored:
7596 *
7597 * '12.345'.to_i # => 12
7598 * '12345'.to_i(2) # => 1
7599 *
7600 * Returns zero if there is no leading valid number:
7601 *
7602 * 'abcdef'.to_i # => 0
7603 * '2'.to_i(2) # => 0
7604 *
7605 * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non-String].
7606 */
7607
7608static VALUE
7609rb_str_to_i(int argc, VALUE *argv, VALUE str)
7610{
7611 int base = 10;
7612
7613 if (rb_check_arity(argc, 0, 1) && (base = NUM2INT(argv[0])) < 0) {
7614 rb_raise(rb_eArgError, "invalid radix %d", base);
7615 }
7616 return rb_str_to_inum(str, base, FALSE);
7617}
7618
7619
7620/*
7621 * call-seq:
7622 * to_f -> float
7623 *
7624 * Returns the result of interpreting leading characters in +self+ as a Float:
7625 *
7626 * '3.14159'.to_f # => 3.14159
7627 * '1.234e-2'.to_f # => 0.01234
7628 *
7629 * Characters past a leading valid number are ignored:
7630 *
7631 * '3.14 (pi to two places)'.to_f # => 3.14
7632 *
7633 * Returns zero if there is no leading valid number:
7634 *
7635 * 'abcdef'.to_f # => 0.0
7636 *
7637 * See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non-String].
7638 */
7639
7640static VALUE
7641rb_str_to_f(VALUE str)
7642{
7643 return DBL2NUM(rb_str_to_dbl(str, FALSE));
7644}
7645
7646
7647/*
7648 * call-seq:
7649 * to_s -> self or new_string
7650 *
7651 * Returns +self+ if +self+ is a +String+,
7652 * or +self+ converted to a +String+ if +self+ is a subclass of +String+.
7653 *
7654 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
7655 */
7656
7657static VALUE
7658rb_str_to_s(VALUE str)
7659{
7660 if (rb_obj_class(str) != rb_cString) {
7661 return str_duplicate(rb_cString, str);
7662 }
7663 return str;
7664}
7665
7666#if 0
7667static void
7668str_cat_char(VALUE str, unsigned int c, rb_encoding *enc)
7669{
7670 char s[RUBY_MAX_CHAR_LEN];
7671 int n = rb_enc_codelen(c, enc);
7672
7673 rb_enc_mbcput(c, s, enc);
7674 rb_enc_str_buf_cat(str, s, n, enc);
7675}
7676#endif
7677
7678#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
7679
7680int
7681rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p)
7682{
7683 char buf[CHAR_ESC_LEN + 1];
7684 int l;
7685
7686#if SIZEOF_INT > 4
7687 c &= 0xffffffff;
7688#endif
7689 if (unicode_p) {
7690 if (c < 0x7F && ISPRINT(c)) {
7691 snprintf(buf, CHAR_ESC_LEN, "%c", c);
7692 }
7693 else if (c < 0x10000) {
7694 snprintf(buf, CHAR_ESC_LEN, "\\u%04X", c);
7695 }
7696 else {
7697 snprintf(buf, CHAR_ESC_LEN, "\\u{%X}", c);
7698 }
7699 }
7700 else {
7701 if (c < 0x100) {
7702 snprintf(buf, CHAR_ESC_LEN, "\\x%02X", c);
7703 }
7704 else {
7705 snprintf(buf, CHAR_ESC_LEN, "\\x{%X}", c);
7706 }
7707 }
7708 l = (int)strlen(buf); /* CHAR_ESC_LEN cannot exceed INT_MAX */
7709 rb_str_buf_cat(result, buf, l);
7710 return l;
7711}
7712
7713const char *
7714ruby_escaped_char(int c)
7715{
7716 switch (c) {
7717 case '\0': return "\\0";
7718 case '\n': return "\\n";
7719 case '\r': return "\\r";
7720 case '\t': return "\\t";
7721 case '\f': return "\\f";
7722 case '\013': return "\\v";
7723 case '\010': return "\\b";
7724 case '\007': return "\\a";
7725 case '\033': return "\\e";
7726 case '\x7f': return "\\c?";
7727 }
7728 return NULL;
7729}
7730
7731VALUE
7732rb_str_escape(VALUE str)
7733{
7734 int encidx = ENCODING_GET(str);
7735 rb_encoding *enc = rb_enc_from_index(encidx);
7736 const char *p = RSTRING_PTR(str);
7737 const char *pend = RSTRING_END(str);
7738 const char *prev = p;
7739 char buf[CHAR_ESC_LEN + 1];
7740 VALUE result = rb_str_buf_new(0);
7741 int unicode_p = rb_enc_unicode_p(enc);
7742 int asciicompat = rb_enc_asciicompat(enc);
7743
7744 while (p < pend) {
7745 unsigned int c;
7746 const char *cc;
7747 int n = rb_enc_precise_mbclen(p, pend, enc);
7748 if (!MBCLEN_CHARFOUND_P(n)) {
7749 if (p > prev) str_buf_cat(result, prev, p - prev);
7750 n = rb_enc_mbminlen(enc);
7751 if (pend < p + n)
7752 n = (int)(pend - p);
7753 while (n--) {
7754 snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377);
7755 str_buf_cat(result, buf, strlen(buf));
7756 prev = ++p;
7757 }
7758 continue;
7759 }
7760 n = MBCLEN_CHARFOUND_LEN(n);
7761 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7762 p += n;
7763 cc = ruby_escaped_char(c);
7764 if (cc) {
7765 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7766 str_buf_cat(result, cc, strlen(cc));
7767 prev = p;
7768 }
7769 else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) {
7770 }
7771 else {
7772 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7773 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7774 prev = p;
7775 }
7776 }
7777 if (p > prev) str_buf_cat(result, prev, p - prev);
7778 ENCODING_CODERANGE_SET(result, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
7779
7780 return result;
7781}
7782
7783/* Lookup table for the inspect fast path. 1 marks bytes that need
7784 * no escaping. 0 marks bytes that need escape inspection: 0x00-0x1F
7785 * (control), 0x22 ("), 0x23 (#), 0x5C (\‍), 0x7F (DEL), 0x80-0xFF
7786 * (non-ASCII). */
7787static const bool inspect_no_escape[256] = {
7788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
7789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
7790 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x20-0x2F */
7791 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x30-0x3F */
7792 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F */
7793 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 0x50-0x5F */
7794 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F */
7795 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 0x70-0x7F */
7796};
7797
7798/*
7799 * call-seq:
7800 * inspect -> string
7801 *
7802 * :include: doc/string/inspect.rdoc
7803 *
7804 */
7805
7806VALUE
7808{
7809 int encidx = ENCODING_GET(str);
7810 rb_encoding *enc = rb_enc_from_index(encidx);
7811 const char *p, *pend, *prev;
7812 char buf[CHAR_ESC_LEN + 1];
7813 VALUE result = rb_str_buf_new(RSTRING_LEN(str) + 2); /* string content + surrounding quotes */
7814 rb_encoding *resenc = rb_default_internal_encoding();
7815 int unicode_p = rb_enc_unicode_p(enc);
7816 int asciicompat = rb_enc_asciicompat(enc);
7817 int cr = rb_enc_str_coderange(str);
7818
7819 if (resenc == NULL) resenc = rb_default_external_encoding();
7820 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
7821 rb_enc_associate(result, resenc);
7822 str_buf_cat2(result, "\"");
7823
7824 p = RSTRING_PTR(str); pend = RSTRING_END(str);
7825 prev = p;
7826 while (p < pend) {
7827 unsigned int c, cc;
7828 int n;
7829
7830 /* Fast path: bulk-skip runs of safe ASCII bytes via a lookup table.
7831 * Only well-formed strings (CR=7BIT for any encoding, or UTF-8 VALID)
7832 * are eligible. */
7833 if (cr == ENC_CODERANGE_7BIT ||
7834 (encidx == ENCINDEX_UTF_8 && cr == ENC_CODERANGE_VALID)) {
7835 while (p < pend && inspect_no_escape[(unsigned char)*p]) p++;
7836 if (p >= pend) break;
7837 }
7838
7839 n = rb_enc_precise_mbclen(p, pend, enc);
7840 if (!MBCLEN_CHARFOUND_P(n)) {
7841 if (p > prev) str_buf_cat(result, prev, p - prev);
7842 n = rb_enc_mbminlen(enc);
7843 if (pend < p + n)
7844 n = (int)(pend - p);
7845 while (n--) {
7846 snprintf(buf, CHAR_ESC_LEN, "\\x%02X", *p & 0377);
7847 str_buf_cat(result, buf, strlen(buf));
7848 prev = ++p;
7849 }
7850 continue;
7851 }
7852 n = MBCLEN_CHARFOUND_LEN(n);
7853 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7854 p += n;
7855 if ((asciicompat || unicode_p) &&
7856 (c == '"'|| c == '\\' ||
7857 (c == '#' &&
7858 p < pend &&
7859 MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
7860 (cc = rb_enc_codepoint(p,pend,enc),
7861 (cc == '$' || cc == '@' || cc == '{'))))) {
7862 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7863 str_buf_cat2(result, "\\");
7864 if (asciicompat || enc == resenc) {
7865 prev = p - n;
7866 continue;
7867 }
7868 }
7869 switch (c) {
7870 case '\n': cc = 'n'; break;
7871 case '\r': cc = 'r'; break;
7872 case '\t': cc = 't'; break;
7873 case '\f': cc = 'f'; break;
7874 case '\013': cc = 'v'; break;
7875 case '\010': cc = 'b'; break;
7876 case '\007': cc = 'a'; break;
7877 case 033: cc = 'e'; break;
7878 default: cc = 0; break;
7879 }
7880 if (cc) {
7881 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7882 buf[0] = '\\';
7883 buf[1] = (char)cc;
7884 str_buf_cat(result, buf, 2);
7885 prev = p;
7886 continue;
7887 }
7888 /* The special casing of 0x85 (NEXT_LINE) here is because
7889 * Oniguruma historically treats it as printable, but it
7890 * doesn't match the print POSIX bracket class or character
7891 * property in regexps.
7892 *
7893 * See Ruby Bug #16842 for details:
7894 * https://bugs.ruby-lang.org/issues/16842
7895 */
7896 if ((enc == resenc && rb_enc_isprint(c, enc) && c != 0x85) ||
7897 (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c))) {
7898 continue;
7899 }
7900 else {
7901 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7902 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7903 prev = p;
7904 continue;
7905 }
7906 }
7907 if (p > prev) str_buf_cat(result, prev, p - prev);
7908 str_buf_cat2(result, "\"");
7909
7910 return result;
7911}
7912
7913#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
7914
7915/*
7916 * call-seq:
7917 * dump -> new_string
7918 *
7919 * :include: doc/string/dump.rdoc
7920 *
7921 */
7922
7923VALUE
7925{
7926 int encidx = rb_enc_get_index(str);
7927 rb_encoding *enc = rb_enc_from_index(encidx);
7928 long len;
7929 const char *p, *pend;
7930 char *q, *qend;
7931 VALUE result;
7932 int u8 = (encidx == rb_utf8_encindex());
7933 static const char nonascii_suffix[] = ".dup.force_encoding(\"%s\")";
7934
7935 len = 2; /* "" */
7936 if (!rb_enc_asciicompat(enc)) {
7937 len += strlen(nonascii_suffix) - rb_strlen_lit("%s");
7938 len += strlen(enc->name);
7939 }
7940
7941 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7942 while (p < pend) {
7943 int clen;
7944 unsigned char c = *p++;
7945
7946 switch (c) {
7947 case '"': case '\\':
7948 case '\n': case '\r':
7949 case '\t': case '\f':
7950 case '\013': case '\010': case '\007': case '\033':
7951 clen = 2;
7952 break;
7953
7954 case '#':
7955 clen = IS_EVSTR(p, pend) ? 2 : 1;
7956 break;
7957
7958 default:
7959 if (ISPRINT(c)) {
7960 clen = 1;
7961 }
7962 else {
7963 if (u8 && c > 0x7F) { /* \u notation */
7964 int n = rb_enc_precise_mbclen(p-1, pend, enc);
7965 if (MBCLEN_CHARFOUND_P(n)) {
7966 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
7967 if (cc <= 0xFFFF)
7968 clen = 6; /* \uXXXX */
7969 else if (cc <= 0xFFFFF)
7970 clen = 9; /* \u{XXXXX} */
7971 else
7972 clen = 10; /* \u{XXXXXX} */
7973 p += MBCLEN_CHARFOUND_LEN(n)-1;
7974 break;
7975 }
7976 }
7977 clen = 4; /* \xNN */
7978 }
7979 break;
7980 }
7981
7982 if (clen > LONG_MAX - len) {
7983 rb_raise(rb_eRuntimeError, "string size too big");
7984 }
7985 len += clen;
7986 }
7987
7988 result = rb_str_new(0, len);
7989 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7990 q = RSTRING_PTR(result); qend = q + len + 1;
7991
7992 *q++ = '"';
7993 while (p < pend) {
7994 unsigned char c = *p++;
7995
7996 if (c == '"' || c == '\\') {
7997 *q++ = '\\';
7998 *q++ = c;
7999 }
8000 else if (c == '#') {
8001 if (IS_EVSTR(p, pend)) *q++ = '\\';
8002 *q++ = '#';
8003 }
8004 else if (c == '\n') {
8005 *q++ = '\\';
8006 *q++ = 'n';
8007 }
8008 else if (c == '\r') {
8009 *q++ = '\\';
8010 *q++ = 'r';
8011 }
8012 else if (c == '\t') {
8013 *q++ = '\\';
8014 *q++ = 't';
8015 }
8016 else if (c == '\f') {
8017 *q++ = '\\';
8018 *q++ = 'f';
8019 }
8020 else if (c == '\013') {
8021 *q++ = '\\';
8022 *q++ = 'v';
8023 }
8024 else if (c == '\010') {
8025 *q++ = '\\';
8026 *q++ = 'b';
8027 }
8028 else if (c == '\007') {
8029 *q++ = '\\';
8030 *q++ = 'a';
8031 }
8032 else if (c == '\033') {
8033 *q++ = '\\';
8034 *q++ = 'e';
8035 }
8036 else if (ISPRINT(c)) {
8037 *q++ = c;
8038 }
8039 else {
8040 *q++ = '\\';
8041 if (u8) {
8042 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
8043 if (MBCLEN_CHARFOUND_P(n)) {
8044 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
8045 p += n;
8046 if (cc <= 0xFFFF)
8047 snprintf(q, qend-q, "u%04X", cc); /* \uXXXX */
8048 else
8049 snprintf(q, qend-q, "u{%X}", cc); /* \u{XXXXX} or \u{XXXXXX} */
8050 q += strlen(q);
8051 continue;
8052 }
8053 }
8054 snprintf(q, qend-q, "x%02X", c);
8055 q += 3;
8056 }
8057 }
8058 *q++ = '"';
8059 *q = '\0';
8060 if (!rb_enc_asciicompat(enc)) {
8061 snprintf(q, qend-q, nonascii_suffix, enc->name);
8062 encidx = rb_ascii8bit_encindex();
8063 }
8064 /* result from dump is ASCII */
8065 rb_enc_associate_index(result, encidx);
8067 return result;
8068}
8069
8070static int
8071unescape_ascii(unsigned int c)
8072{
8073 switch (c) {
8074 case 'n':
8075 return '\n';
8076 case 'r':
8077 return '\r';
8078 case 't':
8079 return '\t';
8080 case 'f':
8081 return '\f';
8082 case 'v':
8083 return '\13';
8084 case 'b':
8085 return '\010';
8086 case 'a':
8087 return '\007';
8088 case 'e':
8089 return 033;
8090 }
8092}
8093
8094static void
8095undump_after_backslash(VALUE undumped, const char **ss, const char *s_end, rb_encoding **penc, bool *utf8, bool *binary)
8096{
8097 const char *s = *ss;
8098 unsigned int c;
8099 int codelen;
8100 size_t hexlen;
8101 unsigned char buf[6];
8102 static rb_encoding *enc_utf8 = NULL;
8103
8104 switch (*s) {
8105 case '\\':
8106 case '"':
8107 case '#':
8108 rb_str_cat(undumped, s, 1); /* cat itself */
8109 s++;
8110 break;
8111 case 'n':
8112 case 'r':
8113 case 't':
8114 case 'f':
8115 case 'v':
8116 case 'b':
8117 case 'a':
8118 case 'e':
8119 *buf = unescape_ascii(*s);
8120 rb_str_cat(undumped, (char *)buf, 1);
8121 s++;
8122 break;
8123 case 'u':
8124 if (*binary) {
8125 rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
8126 }
8127 *utf8 = true;
8128 if (++s >= s_end) {
8129 rb_raise(rb_eRuntimeError, "invalid Unicode escape");
8130 }
8131 if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
8132 if (*penc != enc_utf8) {
8133 *penc = enc_utf8;
8134 rb_enc_associate(undumped, enc_utf8);
8135 }
8136 if (*s == '{') { /* handle \u{...} form */
8137 s++;
8138 for (;;) {
8139 if (s >= s_end) {
8140 rb_raise(rb_eRuntimeError, "unterminated Unicode escape");
8141 }
8142 if (*s == '}') {
8143 s++;
8144 break;
8145 }
8146 if (ISSPACE(*s)) {
8147 s++;
8148 continue;
8149 }
8150 c = scan_hex(s, s_end-s, &hexlen);
8151 if (hexlen == 0 || hexlen > 6) {
8152 rb_raise(rb_eRuntimeError, "invalid Unicode escape");
8153 }
8154 if (c > 0x10ffff) {
8155 rb_raise(rb_eRuntimeError, "invalid Unicode codepoint (too large)");
8156 }
8157 if (0xd800 <= c && c <= 0xdfff) {
8158 rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
8159 }
8160 codelen = rb_enc_mbcput(c, (char *)buf, *penc);
8161 rb_str_cat(undumped, (char *)buf, codelen);
8162 s += hexlen;
8163 }
8164 }
8165 else { /* handle \uXXXX form */
8166 c = scan_hex(s, 4, &hexlen);
8167 if (hexlen != 4) {
8168 rb_raise(rb_eRuntimeError, "invalid Unicode escape");
8169 }
8170 if (0xd800 <= c && c <= 0xdfff) {
8171 rb_raise(rb_eRuntimeError, "invalid Unicode codepoint");
8172 }
8173 codelen = rb_enc_mbcput(c, (char *)buf, *penc);
8174 rb_str_cat(undumped, (char *)buf, codelen);
8175 s += hexlen;
8176 }
8177 break;
8178 case 'x':
8179 if (++s >= s_end) {
8180 rb_raise(rb_eRuntimeError, "invalid hex escape");
8181 }
8182 *buf = scan_hex(s, 2, &hexlen);
8183 if (hexlen != 2) {
8184 rb_raise(rb_eRuntimeError, "invalid hex escape");
8185 }
8186 if (!ISASCII(*buf)) {
8187 if (*utf8) {
8188 rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
8189 }
8190 *binary = true;
8191 }
8192 rb_str_cat(undumped, (char *)buf, 1);
8193 s += hexlen;
8194 break;
8195 default:
8196 rb_str_cat(undumped, s-1, 2);
8197 s++;
8198 }
8199
8200 *ss = s;
8201}
8202
8203static VALUE rb_str_is_ascii_only_p(VALUE str);
8204
8205/*
8206 * call-seq:
8207 * undump -> new_string
8208 *
8209 * Inverse of String#dump; returns a copy of +self+ with changes of the kinds made by String#dump "undone."
8210 *
8211 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
8212 */
8213
8214static VALUE
8215str_undump(VALUE str)
8216{
8217 const char *s = RSTRING_PTR(str);
8218 const char *s_end = RSTRING_END(str);
8219 rb_encoding *enc = rb_enc_get(str);
8220 VALUE undumped = rb_enc_str_new(s, 0L, enc);
8221 bool utf8 = false;
8222 bool binary = false;
8223 int w;
8224
8226 if (rb_str_is_ascii_only_p(str) == Qfalse) {
8227 rb_raise(rb_eRuntimeError, "non-ASCII character detected");
8228 }
8229 if (!str_null_check(str, &w)) {
8230 rb_raise(rb_eRuntimeError, "string contains null byte");
8231 }
8232 if (RSTRING_LEN(str) < 2) goto invalid_format;
8233 if (*s != '"') goto invalid_format;
8234
8235 /* strip '"' at the start */
8236 s++;
8237
8238 for (;;) {
8239 if (s >= s_end) {
8240 rb_raise(rb_eRuntimeError, "unterminated dumped string");
8241 }
8242
8243 if (*s == '"') {
8244 /* epilogue */
8245 s++;
8246 if (s == s_end) {
8247 /* ascii compatible dumped string */
8248 break;
8249 }
8250 else {
8251 static const char force_encoding_suffix[] = ".force_encoding(\""; /* "\")" */
8252 static const char dup_suffix[] = ".dup";
8253 const char *encname;
8254 int encidx;
8255 ptrdiff_t size;
8256
8257 /* check separately for strings dumped by older versions */
8258 size = sizeof(dup_suffix) - 1;
8259 if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
8260
8261 size = sizeof(force_encoding_suffix) - 1;
8262 if (s_end - s <= size) goto invalid_format;
8263 if (memcmp(s, force_encoding_suffix, size) != 0) goto invalid_format;
8264 s += size;
8265
8266 if (utf8) {
8267 rb_raise(rb_eRuntimeError, "dumped string contained Unicode escape but used force_encoding");
8268 }
8269
8270 encname = s;
8271 s = memchr(s, '"', s_end-s);
8272 size = s - encname;
8273 if (!s) goto invalid_format;
8274 if (s_end - s != 2) goto invalid_format;
8275 if (s[0] != '"' || s[1] != ')') goto invalid_format;
8276
8277 encidx = rb_enc_find_index2(encname, (long)size);
8278 if (encidx < 0) {
8279 rb_raise(rb_eRuntimeError, "dumped string has unknown encoding name");
8280 }
8281 rb_enc_associate_index(undumped, encidx);
8282 }
8283 break;
8284 }
8285
8286 if (*s == '\\') {
8287 s++;
8288 if (s >= s_end) {
8289 rb_raise(rb_eRuntimeError, "invalid escape");
8290 }
8291 undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
8292 }
8293 else {
8294 rb_str_cat(undumped, s++, 1);
8295 }
8296 }
8297
8298 RB_GC_GUARD(str);
8299
8300 return undumped;
8301invalid_format:
8302 rb_raise(rb_eRuntimeError, "invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
8303}
8304
8305static void
8306rb_str_check_dummy_enc(rb_encoding *enc)
8307{
8308 if (rb_enc_dummy_p(enc)) {
8309 rb_raise(rb_eEncCompatError, "incompatible encoding with this operation: %s",
8310 rb_enc_name(enc));
8311 }
8312}
8313
8314static rb_encoding *
8315str_true_enc(VALUE str)
8316{
8317 rb_encoding *enc = STR_ENC_GET(str);
8318 rb_str_check_dummy_enc(enc);
8319 return enc;
8320}
8321
8322static OnigCaseFoldType
8323check_case_options(int argc, VALUE *argv, OnigCaseFoldType flags)
8324{
8325 if (argc==0)
8326 return flags;
8327 if (argc>2)
8328 rb_raise(rb_eArgError, "too many options");
8329 if (argv[0]==sym_turkic) {
8330 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8331 if (argc==2) {
8332 if (argv[1]==sym_lithuanian)
8333 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8334 else
8335 rb_raise(rb_eArgError, "invalid second option");
8336 }
8337 }
8338 else if (argv[0]==sym_lithuanian) {
8339 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8340 if (argc==2) {
8341 if (argv[1]==sym_turkic)
8342 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8343 else
8344 rb_raise(rb_eArgError, "invalid second option");
8345 }
8346 }
8347 else if (argc>1)
8348 rb_raise(rb_eArgError, "too many options");
8349 else if (argv[0]==sym_ascii)
8350 flags |= ONIGENC_CASE_ASCII_ONLY;
8351 else if (argv[0]==sym_fold) {
8352 if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
8353 flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
8354 else
8355 rb_raise(rb_eArgError, "option :fold only allowed for downcasing");
8356 }
8357 else
8358 rb_raise(rb_eArgError, "invalid option");
8359 return flags;
8360}
8361
8362static inline bool
8363case_option_single_p(OnigCaseFoldType flags, rb_encoding *enc, VALUE str)
8364{
8365 if ((flags & ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() || rb_enc_mbmaxlen(enc) == 1))
8366 return true;
8367 return !(flags & ONIGENC_CASE_FOLD_TURKISH_AZERI) &&
8368 (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT || rb_is_ascii8bit_enc(enc));
8369}
8370
8371/* 16 should be long enough to absorb any kind of single character length increase */
8372#define CASE_MAPPING_ADDITIONAL_LENGTH 20
8373#ifndef CASEMAP_DEBUG
8374# define CASEMAP_DEBUG 0
8375#endif
8376
8377struct mapping_buffer;
8378typedef struct mapping_buffer {
8379 size_t capa;
8380 size_t used;
8381 struct mapping_buffer *next;
8382 OnigUChar space[FLEX_ARY_LEN];
8384
8385static void
8386mapping_buffer_free(void *p)
8387{
8388 mapping_buffer *previous_buffer;
8389 mapping_buffer *current_buffer = p;
8390 while (current_buffer) {
8391 previous_buffer = current_buffer;
8392 current_buffer = current_buffer->next;
8393 ruby_xfree_sized(previous_buffer, offsetof(mapping_buffer, space) + previous_buffer->capa);
8394 }
8395}
8396
8397static const rb_data_type_t mapping_buffer_type = {
8398 "mapping_buffer",
8399 {0, mapping_buffer_free,},
8400 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
8401};
8402
8403static VALUE
8404rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
8405{
8406 VALUE target;
8407
8408 const OnigUChar *source_current, *source_end;
8409 int target_length = 0;
8410 VALUE buffer_anchor;
8411 mapping_buffer *current_buffer = 0;
8412 mapping_buffer **pre_buffer;
8413 size_t buffer_count = 0;
8414 int buffer_length_or_invalid;
8415
8416 if (RSTRING_LEN(source) == 0) return str_duplicate(rb_cString, source);
8417
8418 source_current = (OnigUChar*)RSTRING_PTR(source);
8419 source_end = (OnigUChar*)RSTRING_END(source);
8420
8421 buffer_anchor = TypedData_Wrap_Struct(0, &mapping_buffer_type, 0);
8422 pre_buffer = (mapping_buffer **)&DATA_PTR(buffer_anchor);
8423 while (source_current < source_end) {
8424 /* increase multiplier using buffer count to converge quickly */
8425 size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
8426 if (CASEMAP_DEBUG) {
8427 fprintf(stderr, "Buffer allocation, capa is %"PRIuSIZE"\n", capa); /* for tuning */
8428 }
8429 current_buffer = xmalloc(offsetof(mapping_buffer, space) + capa);
8430 *pre_buffer = current_buffer;
8431 pre_buffer = &current_buffer->next;
8432 current_buffer->next = NULL;
8433 current_buffer->capa = capa;
8434 buffer_length_or_invalid = enc->case_map(flags,
8435 &source_current, source_end,
8436 current_buffer->space,
8437 current_buffer->space+current_buffer->capa,
8438 enc);
8439 if (buffer_length_or_invalid < 0) {
8440 current_buffer = DATA_PTR(buffer_anchor);
8441 DATA_PTR(buffer_anchor) = 0;
8442 mapping_buffer_free(current_buffer);
8443 rb_raise(rb_eArgError, "input string invalid");
8444 }
8445 target_length += current_buffer->used = buffer_length_or_invalid;
8446 }
8447 if (CASEMAP_DEBUG) {
8448 fprintf(stderr, "Buffer count is %"PRIuSIZE"\n", buffer_count); /* for tuning */
8449 }
8450
8451 if (buffer_count==1) {
8452 target = rb_str_new((const char*)current_buffer->space, target_length);
8453 }
8454 else {
8455 char *target_current;
8456
8457 target = rb_str_new(0, target_length);
8458 target_current = RSTRING_PTR(target);
8459 current_buffer = DATA_PTR(buffer_anchor);
8460 while (current_buffer) {
8461 memcpy(target_current, current_buffer->space, current_buffer->used);
8462 target_current += current_buffer->used;
8463 current_buffer = current_buffer->next;
8464 }
8465 }
8466 current_buffer = DATA_PTR(buffer_anchor);
8467 DATA_PTR(buffer_anchor) = 0;
8468 mapping_buffer_free(current_buffer);
8469
8470 RB_GC_GUARD(buffer_anchor);
8471
8472 /* TODO: check about string terminator character */
8473 str_enc_copy_direct(target, source);
8474 /*ENC_CODERANGE_SET(mapped, cr);*/
8475
8476 return target;
8477}
8478
8479static VALUE
8480rb_str_ascii_casemap(VALUE source, VALUE target, OnigCaseFoldType *flags, rb_encoding *enc)
8481{
8482 const OnigUChar *source_current, *source_end;
8483 OnigUChar *target_current, *target_end;
8484 long old_length = RSTRING_LEN(source);
8485 int length_or_invalid;
8486
8487 if (old_length == 0) return Qnil;
8488
8489 source_current = (OnigUChar*)RSTRING_PTR(source);
8490 source_end = (OnigUChar*)RSTRING_END(source);
8491 if (source == target) {
8492 target_current = (OnigUChar*)source_current;
8493 target_end = (OnigUChar*)source_end;
8494 }
8495 else {
8496 target_current = (OnigUChar*)RSTRING_PTR(target);
8497 target_end = (OnigUChar*)RSTRING_END(target);
8498 }
8499
8500 length_or_invalid = onigenc_ascii_only_case_map(flags,
8501 &source_current, source_end,
8502 target_current, target_end, enc);
8503 if (length_or_invalid < 0)
8504 rb_raise(rb_eArgError, "input string invalid");
8505 if (CASEMAP_DEBUG && length_or_invalid != old_length) {
8506 fprintf(stderr, "problem with rb_str_ascii_casemap"
8507 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8508 rb_raise(rb_eArgError, "internal problem with rb_str_ascii_casemap"
8509 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8510 }
8511
8512 str_enc_copy(target, source);
8513
8514 return target;
8515}
8516
8517static bool
8518upcase_single(VALUE str)
8519{
8520 char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
8521 bool modified = false;
8522
8523 while (s < send) {
8524 unsigned int c = *(unsigned char*)s;
8525
8526 if ('a' <= c && c <= 'z') {
8527 *s = 'A' + (c - 'a');
8528 modified = true;
8529 }
8530 s++;
8531 }
8532 return modified;
8533}
8534
8535/*
8536 * call-seq:
8537 * upcase!(mapping) -> self or nil
8538 *
8539 * Like String#upcase, except that:
8540 *
8541 * - Changes character casings in +self+ (not in a copy of +self+).
8542 * - Returns +self+ if any changes are made, +nil+ otherwise.
8543 *
8544 * Related: See {Modifying}[rdoc-ref:String@Modifying].
8545 */
8546
8547static VALUE
8548rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
8549{
8550 rb_encoding *enc;
8551 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8552
8553 flags = check_case_options(argc, argv, flags);
8554 str_modify_keep_cr(str);
8555 enc = str_true_enc(str);
8556 if (case_option_single_p(flags, enc, str)) {
8557 if (upcase_single(str))
8558 flags |= ONIGENC_CASE_MODIFIED;
8559 }
8560 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8561 rb_str_ascii_casemap(str, str, &flags, enc);
8562 else
8563 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8564
8565 if (ONIGENC_CASE_MODIFIED&flags) return str;
8566 return Qnil;
8567}
8568
8569
8570/*
8571 * call-seq:
8572 * upcase(mapping = :ascii) -> new_string
8573 *
8574 * :include: doc/string/upcase.rdoc
8575 */
8576
8577static VALUE
8578rb_str_upcase(int argc, VALUE *argv, VALUE str)
8579{
8580 rb_encoding *enc;
8581 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8582 VALUE ret;
8583
8584 flags = check_case_options(argc, argv, flags);
8585 enc = str_true_enc(str);
8586 if (case_option_single_p(flags, enc, str)) {
8587 ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8588 str_enc_copy_direct(ret, str);
8589 upcase_single(ret);
8590 }
8591 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8592 ret = rb_str_new(0, RSTRING_LEN(str));
8593 rb_str_ascii_casemap(str, ret, &flags, enc);
8594 }
8595 else {
8596 ret = rb_str_casemap(str, &flags, enc);
8597 }
8598
8599 return ret;
8600}
8601
8602static bool
8603downcase_single(VALUE str)
8604{
8605 char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
8606 bool modified = false;
8607
8608 while (s < send) {
8609 unsigned int c = *(unsigned char*)s;
8610
8611 if ('A' <= c && c <= 'Z') {
8612 *s = 'a' + (c - 'A');
8613 modified = true;
8614 }
8615 s++;
8616 }
8617
8618 return modified;
8619}
8620
8621/*
8622 * call-seq:
8623 * downcase!(mapping) -> self or nil
8624 *
8625 * Like String#downcase, except that:
8626 *
8627 * - Changes character casings in +self+ (not in a copy of +self+).
8628 * - Returns +self+ if any changes are made, +nil+ otherwise.
8629 *
8630 * Related: See {Modifying}[rdoc-ref:String@Modifying].
8631 */
8632
8633static VALUE
8634rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
8635{
8636 rb_encoding *enc;
8637 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8638
8639 flags = check_case_options(argc, argv, flags);
8640 str_modify_keep_cr(str);
8641 enc = str_true_enc(str);
8642 if (case_option_single_p(flags, enc, str)) {
8643 if (downcase_single(str))
8644 flags |= ONIGENC_CASE_MODIFIED;
8645 }
8646 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8647 rb_str_ascii_casemap(str, str, &flags, enc);
8648 else
8649 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8650
8651 if (ONIGENC_CASE_MODIFIED&flags) return str;
8652 return Qnil;
8653}
8654
8655
8656/*
8657 * call-seq:
8658 * downcase(mapping = :ascii) -> new_string
8659 *
8660 * :include: doc/string/downcase.rdoc
8661 *
8662 */
8663
8664static VALUE
8665rb_str_downcase(int argc, VALUE *argv, VALUE str)
8666{
8667 rb_encoding *enc;
8668 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8669 VALUE ret;
8670
8671 flags = check_case_options(argc, argv, flags);
8672 enc = str_true_enc(str);
8673 if (case_option_single_p(flags, enc, str)) {
8674 ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8675 str_enc_copy_direct(ret, str);
8676 downcase_single(ret);
8677 }
8678 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8679 ret = rb_str_new(0, RSTRING_LEN(str));
8680 rb_str_ascii_casemap(str, ret, &flags, enc);
8681 }
8682 else {
8683 ret = rb_str_casemap(str, &flags, enc);
8684 }
8685
8686 return ret;
8687}
8688
8689static bool
8690capitalize_single(VALUE str)
8691{
8692 char *s = RSTRING_PTR(str), *send = RSTRING_END(str);
8693 bool modified = false;
8694
8695 if (s < send) {
8696 unsigned int c = (unsigned char)*s;
8697
8698 if ('a' <= c && c <= 'z') {
8699 *s = 'A' + (c - 'a');
8700 modified = true;
8701 }
8702 s++;
8703 }
8704 while (s < send) {
8705 unsigned int c = (unsigned char)*s;
8706
8707 if ('A' <= c && c <= 'Z') {
8708 *s = 'a' + (c - 'A');
8709 modified = true;
8710 }
8711 s++;
8712 }
8713
8714 return modified;
8715}
8716
8717/*
8718 * call-seq:
8719 * capitalize!(mapping = :ascii) -> self or nil
8720 *
8721 * Like String#capitalize, except that:
8722 *
8723 * - Changes character casings in +self+ (not in a copy of +self+).
8724 * - Returns +self+ if any changes are made, +nil+ otherwise.
8725 *
8726 * Related: See {Modifying}[rdoc-ref:String@Modifying].
8727 */
8728
8729static VALUE
8730rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
8731{
8732 rb_encoding *enc;
8733 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8734
8735 flags = check_case_options(argc, argv, flags);
8736 str_modify_keep_cr(str);
8737 enc = str_true_enc(str);
8738 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
8739 if (case_option_single_p(flags, enc, str)) {
8740 if (capitalize_single(str))
8741 flags |= ONIGENC_CASE_MODIFIED;
8742 }
8743 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8744 rb_str_ascii_casemap(str, str, &flags, enc);
8745 else
8746 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8747
8748 if (ONIGENC_CASE_MODIFIED&flags) return str;
8749 return Qnil;
8750}
8751
8752
8753/*
8754 * call-seq:
8755 * capitalize(mapping = :ascii) -> new_string
8756 *
8757 * :include: doc/string/capitalize.rdoc
8758 *
8759 */
8760
8761static VALUE
8762rb_str_capitalize(int argc, VALUE *argv, VALUE str)
8763{
8764 rb_encoding *enc;
8765 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8766 VALUE ret;
8767
8768 flags = check_case_options(argc, argv, flags);
8769 enc = str_true_enc(str);
8770 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
8771 if (case_option_single_p(flags, enc, str)) {
8772 ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8773 str_enc_copy_direct(ret, str);
8774 capitalize_single(ret);
8775 }
8776 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8777 ret = rb_str_new(0, RSTRING_LEN(str));
8778 rb_str_ascii_casemap(str, ret, &flags, enc);
8779 }
8780 else {
8781 ret = rb_str_casemap(str, &flags, enc);
8782 }
8783 return ret;
8784}
8785
8786
8787/*
8788 * call-seq:
8789 * swapcase!(mapping) -> self or nil
8790 *
8791 * Like String#swapcase, except that:
8792 *
8793 * - Changes are made to +self+, not to copy of +self+.
8794 * - Returns +self+ if any changes are made, +nil+ otherwise.
8795 *
8796 * Related: see {Modifying}[rdoc-ref:String@Modifying].
8797 */
8798
8799static VALUE
8800rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
8801{
8802 rb_encoding *enc;
8803 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8804
8805 flags = check_case_options(argc, argv, flags);
8806 str_modify_keep_cr(str);
8807 enc = str_true_enc(str);
8808 if (flags&ONIGENC_CASE_ASCII_ONLY)
8809 rb_str_ascii_casemap(str, str, &flags, enc);
8810 else
8811 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8812
8813 if (ONIGENC_CASE_MODIFIED&flags) return str;
8814 return Qnil;
8815}
8816
8817
8818/*
8819 * call-seq:
8820 * swapcase(mapping = :ascii) -> new_string
8821 *
8822 * :include: doc/string/swapcase.rdoc
8823 *
8824 */
8825
8826static VALUE
8827rb_str_swapcase(int argc, VALUE *argv, VALUE str)
8828{
8829 rb_encoding *enc;
8830 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8831 VALUE ret;
8832
8833 flags = check_case_options(argc, argv, flags);
8834 enc = str_true_enc(str);
8835 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str_duplicate(rb_cString, str);
8836 if (flags&ONIGENC_CASE_ASCII_ONLY) {
8837 ret = rb_str_new(0, RSTRING_LEN(str));
8838 rb_str_ascii_casemap(str, ret, &flags, enc);
8839 }
8840 else {
8841 ret = rb_str_casemap(str, &flags, enc);
8842 }
8843 return ret;
8844}
8845
8846typedef unsigned char *USTR;
8847
8848struct tr {
8849 int gen;
8850 unsigned int now, max;
8851 const char *p, *pend;
8852};
8853
8854static unsigned int
8855trnext(struct tr *t, rb_encoding *enc)
8856{
8857 int n;
8858
8859 for (;;) {
8860 nextpart:
8861 if (!t->gen) {
8862 if (t->p == t->pend) return -1;
8863 if (rb_enc_ascget(t->p, t->pend, &n, enc) == '\\' && t->p + n < t->pend) {
8864 t->p += n;
8865 }
8866 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8867 t->p += n;
8868 if (rb_enc_ascget(t->p, t->pend, &n, enc) == '-' && t->p + n < t->pend) {
8869 t->p += n;
8870 if (t->p < t->pend) {
8871 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8872 t->p += n;
8873 if (t->now > c) {
8874 if (t->now < 0x80 && c < 0x80) {
8875 rb_raise(rb_eArgError,
8876 "invalid range \"%c-%c\" in string transliteration",
8877 t->now, c);
8878 }
8879 else {
8880 rb_raise(rb_eArgError, "invalid range in string transliteration");
8881 }
8882 continue; /* not reached */
8883 }
8884 else if (t->now < c) {
8885 t->gen = 1;
8886 t->max = c;
8887 }
8888 }
8889 }
8890 return t->now;
8891 }
8892 else {
8893 while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
8894 if (t->now == t->max) {
8895 t->gen = 0;
8896 goto nextpart;
8897 }
8898 }
8899 if (t->now < t->max) {
8900 return t->now;
8901 }
8902 else {
8903 t->gen = 0;
8904 return t->max;
8905 }
8906 }
8907 }
8908}
8909
8910static VALUE rb_str_delete_bang(int,VALUE*,VALUE);
8911
8912static VALUE
8913tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
8914{
8915 const unsigned int errc = -1;
8916 unsigned int trans[256];
8917 rb_encoding *enc, *e1, *e2;
8918 struct tr trsrc, trrepl;
8919 int cflag = 0;
8920 unsigned int c, c0, last = 0;
8921 int modify = 0, i, l;
8922 unsigned char *s, *send;
8923 VALUE hash = 0;
8924 int singlebyte = single_byte_optimizable(str);
8925 int termlen;
8926 int cr;
8927
8928#define CHECK_IF_ASCII(c) \
8929 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
8930 (cr = ENC_CODERANGE_VALID) : 0)
8931
8932 StringValue(src);
8933 StringValue(repl);
8934 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
8935 if (RSTRING_LEN(repl) == 0) {
8936 return rb_str_delete_bang(1, &src, str);
8937 }
8938
8939 cr = ENC_CODERANGE(str);
8940 e1 = rb_enc_check(str, src);
8941 e2 = rb_enc_check(str, repl);
8942 if (e1 == e2) {
8943 enc = e1;
8944 }
8945 else {
8946 enc = rb_enc_check(src, repl);
8947 }
8948 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
8949 if (RSTRING_LEN(src) > 1 &&
8950 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) == '^' &&
8951 trsrc.p + l < trsrc.pend) {
8952 cflag = 1;
8953 trsrc.p += l;
8954 }
8955 trrepl.p = RSTRING_PTR(repl);
8956 trrepl.pend = trrepl.p + RSTRING_LEN(repl);
8957 trsrc.gen = trrepl.gen = 0;
8958 trsrc.now = trrepl.now = 0;
8959 trsrc.max = trrepl.max = 0;
8960
8961 if (cflag) {
8962 for (i=0; i<256; i++) {
8963 trans[i] = 1;
8964 }
8965 while ((c = trnext(&trsrc, enc)) != errc) {
8966 if (c < 256) {
8967 trans[c] = errc;
8968 }
8969 else {
8970 if (!hash) hash = rb_hash_new();
8971 rb_hash_aset(hash, UINT2NUM(c), Qtrue);
8972 }
8973 }
8974 while ((c = trnext(&trrepl, enc)) != errc)
8975 /* retrieve last replacer */;
8976 last = trrepl.now;
8977 for (i=0; i<256; i++) {
8978 if (trans[i] != errc) {
8979 trans[i] = last;
8980 }
8981 }
8982 }
8983 else {
8984 unsigned int r;
8985
8986 for (i=0; i<256; i++) {
8987 trans[i] = errc;
8988 }
8989 while ((c = trnext(&trsrc, enc)) != errc) {
8990 r = trnext(&trrepl, enc);
8991 if (r == errc) r = trrepl.now;
8992 if (c < 256) {
8993 trans[c] = r;
8994 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
8995 }
8996 else {
8997 if (!hash) hash = rb_hash_new();
8998 rb_hash_aset(hash, UINT2NUM(c), UINT2NUM(r));
8999 }
9000 }
9001 }
9002
9003 if (cr == ENC_CODERANGE_VALID && rb_enc_asciicompat(e1))
9004 cr = ENC_CODERANGE_7BIT;
9005 str_modify_keep_cr(str);
9006 s = (unsigned char *)RSTRING_PTR(str); send = (unsigned char *)RSTRING_END(str);
9007 termlen = rb_enc_mbminlen(enc);
9008 if (sflag) {
9009 int clen, tlen;
9010 long offset, max = RSTRING_LEN(str);
9011 unsigned int save = -1;
9012 unsigned char *buf = ALLOC_N(unsigned char, max + termlen), *t = buf;
9013
9014 while (s < send) {
9015 int may_modify = 0;
9016
9017 int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
9018 if (!MBCLEN_CHARFOUND_P(r)) {
9019 SIZED_FREE_N(buf, max + termlen);
9020 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
9021 }
9022 clen = MBCLEN_CHARFOUND_LEN(r);
9023 c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
9024
9025 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9026
9027 s += clen;
9028 if (c < 256) {
9029 c = trans[c];
9030 }
9031 else if (hash) {
9032 VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
9033 if (NIL_P(tmp)) {
9034 if (cflag) c = last;
9035 else c = errc;
9036 }
9037 else if (cflag) c = errc;
9038 else c = NUM2INT(tmp);
9039 }
9040 else {
9041 c = errc;
9042 }
9043 if (c != (unsigned int)-1) {
9044 if (save == c) {
9045 CHECK_IF_ASCII(c);
9046 continue;
9047 }
9048 save = c;
9049 tlen = rb_enc_codelen(c, enc);
9050 modify = 1;
9051 }
9052 else {
9053 save = -1;
9054 c = c0;
9055 if (enc != e1) may_modify = 1;
9056 }
9057 if ((offset = t - buf) + tlen > max) {
9058 size_t MAYBE_UNUSED(old) = max + termlen;
9059 max = offset + tlen + (send - s);
9060 SIZED_REALLOC_N(buf, unsigned char, max + termlen, old);
9061 t = buf + offset;
9062 }
9063 rb_enc_mbcput(c, t, enc);
9064 if (may_modify && memcmp(s, t, tlen) != 0) {
9065 modify = 1;
9066 }
9067 CHECK_IF_ASCII(c);
9068 t += tlen;
9069 }
9070 if (!STR_EMBED_P(str)) {
9071 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9072 }
9073 TERM_FILL((char *)t, termlen);
9074 RSTRING(str)->as.heap.ptr = (char *)buf;
9075 STR_SET_LEN(str, t - buf);
9076 STR_SET_NOEMBED(str);
9077 RSTRING(str)->as.heap.aux.capa = max;
9078 }
9079 else if (rb_enc_mbmaxlen(enc) == 1 || (singlebyte && !hash)) {
9080 while (s < send) {
9081 c = (unsigned char)*s;
9082 if (trans[c] != errc) {
9083 if (!cflag) {
9084 c = trans[c];
9085 *s = c;
9086 modify = 1;
9087 }
9088 else {
9089 *s = last;
9090 modify = 1;
9091 }
9092 }
9093 CHECK_IF_ASCII(c);
9094 s++;
9095 }
9096 }
9097 else {
9098 int clen, tlen;
9099 long offset, max = (long)((send - s) * 1.2);
9100 unsigned char *buf = ALLOC_N(unsigned char, max + termlen), *t = buf;
9101
9102 while (s < send) {
9103 int may_modify = 0;
9104
9105 int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1);
9106 if (!MBCLEN_CHARFOUND_P(r)) {
9107 SIZED_FREE_N(buf, max + termlen);
9108 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1));
9109 }
9110 clen = MBCLEN_CHARFOUND_LEN(r);
9111 c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1);
9112
9113 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9114
9115 if (c < 256) {
9116 c = trans[c];
9117 }
9118 else if (hash) {
9119 VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
9120 if (NIL_P(tmp)) {
9121 if (cflag) c = last;
9122 else c = errc;
9123 }
9124 else if (cflag) c = errc;
9125 else c = NUM2INT(tmp);
9126 }
9127 else {
9128 c = cflag ? last : errc;
9129 }
9130 if (c != errc) {
9131 tlen = rb_enc_codelen(c, enc);
9132 modify = 1;
9133 }
9134 else {
9135 c = c0;
9136 if (enc != e1) may_modify = 1;
9137 }
9138 if ((offset = t - buf) + tlen > max) {
9139 size_t MAYBE_UNUSED(old) = max + termlen;
9140 max = offset + tlen + (long)((send - s) * 1.2);
9141 SIZED_REALLOC_N(buf, unsigned char, max + termlen, old);
9142 t = buf + offset;
9143 }
9144 if (s != t) {
9145 rb_enc_mbcput(c, t, enc);
9146 if (may_modify && memcmp(s, t, tlen) != 0) {
9147 modify = 1;
9148 }
9149 }
9150 CHECK_IF_ASCII(c);
9151 s += clen;
9152 t += tlen;
9153 }
9154 if (!STR_EMBED_P(str)) {
9155 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9156 }
9157 TERM_FILL((char *)t, termlen);
9158 RSTRING(str)->as.heap.ptr = (char *)buf;
9159 STR_SET_LEN(str, t - buf);
9160 STR_SET_NOEMBED(str);
9161 RSTRING(str)->as.heap.aux.capa = max;
9162 }
9163
9164 if (modify) {
9165 if (cr != ENC_CODERANGE_BROKEN)
9166 ENC_CODERANGE_SET(str, cr);
9167 rb_enc_associate(str, enc);
9168 return str;
9169 }
9170 return Qnil;
9171}
9172
9173
9174/*
9175 * call-seq:
9176 * tr!(selector, replacements) -> self or nil
9177 *
9178 * Like String#tr, except:
9179 *
9180 * - Performs substitutions in +self+ (not in a copy of +self+).
9181 * - Returns +self+ if any modifications were made, +nil+ otherwise.
9182 *
9183 * Related: {Modifying}[rdoc-ref:String@Modifying].
9184 */
9185
9186static VALUE
9187rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
9188{
9189 return tr_trans(str, src, repl, 0);
9190}
9191
9192
9193/*
9194 * call-seq:
9195 * tr(selector, replacements) -> new_string
9196 *
9197 * Returns a copy of +self+ with each character specified by string +selector+
9198 * translated to the corresponding character in string +replacements+.
9199 * The correspondence is _positional_:
9200 *
9201 * - Each occurrence of the first character specified by +selector+
9202 * is translated to the first character in +replacements+.
9203 * - Each occurrence of the second character specified by +selector+
9204 * is translated to the second character in +replacements+.
9205 * - And so on.
9206 *
9207 * Example:
9208 *
9209 * 'hello'.tr('el', 'ip') #=> "hippo"
9210 *
9211 * If +replacements+ is shorter than +selector+,
9212 * it is implicitly padded with its own last character:
9213 *
9214 * 'hello'.tr('aeiou', '-') # => "h-ll-"
9215 * 'hello'.tr('aeiou', 'AA-') # => "hAll-"
9216 *
9217 * Arguments +selector+ and +replacements+ must be valid character selectors
9218 * (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
9219 * and may use any of its valid forms, including negation, ranges, and escapes:
9220 *
9221 * 'hello'.tr('^aeiou', '-') # => "-e--o" # Negation.
9222 * 'ibm'.tr('b-z', 'a-z') # => "hal" # Range.
9223 * 'hel^lo'.tr('\^aeiou', '-') # => "h-l-l-" # Escaped leading caret.
9224 * 'i-b-m'.tr('b\-z', 'a-z') # => "ibabm" # Escaped embedded hyphen.
9225 * 'foo\\bar'.tr('ab\\', 'XYZ') # => "fooZYXr" # Escaped backslash.
9226 *
9227 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
9228 */
9229
9230static VALUE
9231rb_str_tr(VALUE str, VALUE src, VALUE repl)
9232{
9233 str = str_duplicate(rb_cString, str);
9234 tr_trans(str, src, repl, 0);
9235 return str;
9236}
9237
9238#define TR_TABLE_MAX (UCHAR_MAX+1)
9239#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
9240static void
9241tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
9242 VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
9243{
9244 const unsigned int errc = -1;
9245 char buf[TR_TABLE_MAX];
9246 struct tr tr;
9247 unsigned int c;
9248 VALUE table = 0, ptable = 0;
9249 int i, l, cflag = 0;
9250
9251 tr.p = RSTRING_PTR(str); tr.pend = tr.p + RSTRING_LEN(str);
9252 tr.gen = tr.now = tr.max = 0;
9253
9254 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(tr.p, tr.pend, &l, enc) == '^') {
9255 cflag = 1;
9256 tr.p += l;
9257 }
9258 if (first) {
9259 for (i=0; i<TR_TABLE_MAX; i++) {
9260 stable[i] = 1;
9261 }
9262 stable[TR_TABLE_MAX] = cflag;
9263 }
9264 else if (stable[TR_TABLE_MAX] && !cflag) {
9265 stable[TR_TABLE_MAX] = 0;
9266 }
9267 for (i=0; i<TR_TABLE_MAX; i++) {
9268 buf[i] = cflag;
9269 }
9270
9271 while ((c = trnext(&tr, enc)) != errc) {
9272 if (c < TR_TABLE_MAX) {
9273 buf[(unsigned char)c] = !cflag;
9274 }
9275 else {
9276 VALUE key = UINT2NUM(c);
9277
9278 if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
9279 if (cflag) {
9280 ptable = *ctablep;
9281 table = ptable ? ptable : rb_hash_new();
9282 *ctablep = table;
9283 }
9284 else {
9285 table = rb_hash_new();
9286 ptable = *tablep;
9287 *tablep = table;
9288 }
9289 }
9290 if (table && (!ptable || (cflag ^ !NIL_P(rb_hash_aref(ptable, key))))) {
9291 rb_hash_aset(table, key, Qtrue);
9292 }
9293 }
9294 }
9295 for (i=0; i<TR_TABLE_MAX; i++) {
9296 stable[i] = stable[i] && buf[i];
9297 }
9298 if (!table && !cflag) {
9299 *tablep = 0;
9300 }
9301}
9302
9303
9304static int
9305tr_find(unsigned int c, const char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
9306{
9307 if (c < TR_TABLE_MAX) {
9308 return table[c] != 0;
9309 }
9310 else {
9311 VALUE v = UINT2NUM(c);
9312
9313 if (del) {
9314 if (!NIL_P(rb_hash_lookup(del, v)) &&
9315 (!nodel || NIL_P(rb_hash_lookup(nodel, v)))) {
9316 return TRUE;
9317 }
9318 }
9319 else if (nodel && !NIL_P(rb_hash_lookup(nodel, v))) {
9320 return FALSE;
9321 }
9322 return table[TR_TABLE_MAX] ? TRUE : FALSE;
9323 }
9324}
9325
9326/*
9327 * call-seq:
9328 * delete!(*selectors) -> self or nil
9329 *
9330 * Like String#delete, but modifies +self+ in place;
9331 * returns +self+ if any characters were deleted, +nil+ otherwise.
9332 *
9333 * Related: see {Modifying}[rdoc-ref:String@Modifying].
9334 */
9335
9336static VALUE
9337rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
9338{
9339 char squeez[TR_TABLE_SIZE];
9340 rb_encoding *enc = 0;
9341 char *s, *send, *t;
9342 VALUE del = 0, nodel = 0;
9343 int modify = 0;
9344 int i, ascompat, cr;
9345
9346 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
9348 for (i=0; i<argc; i++) {
9349 VALUE s = argv[i];
9350
9351 StringValue(s);
9352 enc = rb_enc_check(str, s);
9353 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9354 }
9355
9356 str_modify_keep_cr(str);
9357 ascompat = rb_enc_asciicompat(enc);
9358 s = t = RSTRING_PTR(str);
9359 send = RSTRING_END(str);
9360 cr = ascompat ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
9361 while (s < send) {
9362 unsigned int c;
9363 int clen;
9364
9365 if (ascompat && (c = *(unsigned char*)s) < 0x80) {
9366 if (squeez[c]) {
9367 modify = 1;
9368 }
9369 else {
9370 if (t != s) *t = c;
9371 t++;
9372 }
9373 s++;
9374 }
9375 else {
9376 c = rb_enc_codepoint_len(s, send, &clen, enc);
9377
9378 if (tr_find(c, squeez, del, nodel)) {
9379 modify = 1;
9380 }
9381 else {
9382 if (t != s) rb_enc_mbcput(c, t, enc);
9383 t += clen;
9385 }
9386 s += clen;
9387 }
9388 }
9389 TERM_FILL(t, TERM_LEN(str));
9390 STR_SET_LEN(str, t - RSTRING_PTR(str));
9391 ENC_CODERANGE_SET(str, cr);
9392
9393 if (modify) return str;
9394 return Qnil;
9395}
9396
9397
9398/*
9399 * call-seq:
9400 * delete(*selectors) -> new_string
9401 *
9402 * :include: doc/string/delete.rdoc
9403 *
9404 */
9405
9406static VALUE
9407rb_str_delete(int argc, VALUE *argv, VALUE str)
9408{
9409 str = str_duplicate(rb_cString, str);
9410 rb_str_delete_bang(argc, argv, str);
9411 return str;
9412}
9413
9414
9415/*
9416 * call-seq:
9417 * squeeze!(*selectors) -> self or nil
9418 *
9419 * Like String#squeeze, except that:
9420 *
9421 * - Characters are squeezed in +self+ (not in a copy of +self+).
9422 * - Returns +self+ if any changes are made, +nil+ otherwise.
9423 *
9424 * Related: See {Modifying}[rdoc-ref:String@Modifying].
9425 */
9426
9427static VALUE
9428rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
9429{
9430 char squeez[TR_TABLE_SIZE];
9431 rb_encoding *enc = 0;
9432 VALUE del = 0, nodel = 0;
9433 unsigned char *s, *send, *t;
9434 int i, modify = 0;
9435 int ascompat, singlebyte = single_byte_optimizable(str);
9436 unsigned int save;
9437
9438 if (argc == 0) {
9439 enc = STR_ENC_GET(str);
9440 }
9441 else {
9442 for (i=0; i<argc; i++) {
9443 VALUE s = argv[i];
9444
9445 StringValue(s);
9446 enc = rb_enc_check(str, s);
9447 if (singlebyte && !single_byte_optimizable(s))
9448 singlebyte = 0;
9449 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9450 }
9451 }
9452
9453 str_modify_keep_cr(str);
9454 s = t = (unsigned char *)RSTRING_PTR(str);
9455 if (!s || RSTRING_LEN(str) == 0) return Qnil;
9456 send = (unsigned char *)RSTRING_END(str);
9457 save = -1;
9458 ascompat = rb_enc_asciicompat(enc);
9459
9460 if (singlebyte) {
9461 while (s < send) {
9462 unsigned int c = *s++;
9463 if (c != save || (argc > 0 && !squeez[c])) {
9464 *t++ = save = c;
9465 }
9466 }
9467 }
9468 else {
9469 while (s < send) {
9470 unsigned int c;
9471 int clen;
9472
9473 if (ascompat && (c = *s) < 0x80) {
9474 if (c != save || (argc > 0 && !squeez[c])) {
9475 *t++ = save = c;
9476 }
9477 s++;
9478 }
9479 else {
9480 c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, enc);
9481
9482 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
9483 if (t != s) rb_enc_mbcput(c, t, enc);
9484 save = c;
9485 t += clen;
9486 }
9487 s += clen;
9488 }
9489 }
9490 }
9491
9492 TERM_FILL((char *)t, TERM_LEN(str));
9493 if ((char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
9494 STR_SET_LEN(str, (char *)t - RSTRING_PTR(str));
9495 modify = 1;
9496 }
9497
9498 if (modify) return str;
9499 return Qnil;
9500}
9501
9502
9503/*
9504 * call-seq:
9505 * squeeze(*selectors) -> new_string
9506 *
9507 * :include: doc/string/squeeze.rdoc
9508 *
9509 */
9510
9511static VALUE
9512rb_str_squeeze(int argc, VALUE *argv, VALUE str)
9513{
9514 str = str_duplicate(rb_cString, str);
9515 rb_str_squeeze_bang(argc, argv, str);
9516 return str;
9517}
9518
9519
9520/*
9521 * call-seq:
9522 * tr_s!(selector, replacements) -> self or nil
9523 *
9524 * Like String#tr_s, except:
9525 *
9526 * - Modifies +self+ in place (not a copy of +self+).
9527 * - Returns +self+ if any changes were made, +nil+ otherwise.
9528 *
9529 * Related: {Modifying}[rdoc-ref:String@Modifying].
9530 */
9531
9532static VALUE
9533rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
9534{
9535 return tr_trans(str, src, repl, 1);
9536}
9537
9538
9539/*
9540 * call-seq:
9541 * tr_s(selector, replacements) -> new_string
9542 *
9543 * Like String#tr, except:
9544 *
9545 * - Also squeezes the modified portions of the translated string;
9546 * see String#squeeze.
9547 * - Returns the translated and squeezed string.
9548 *
9549 * Examples:
9550 *
9551 * 'hello'.tr_s('l', 'r') #=> "hero"
9552 * 'hello'.tr_s('el', '-') #=> "h-o"
9553 * 'hello'.tr_s('el', 'hx') #=> "hhxo"
9554 *
9555 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
9556 *
9557 */
9558
9559static VALUE
9560rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
9561{
9562 str = str_duplicate(rb_cString, str);
9563 tr_trans(str, src, repl, 1);
9564 return str;
9565}
9566
9567
9568/*
9569 * call-seq:
9570 * count(*selectors) -> integer
9571 *
9572 * :include: doc/string/count.rdoc
9573 */
9574
9575static VALUE
9576rb_str_count(int argc, VALUE *argv, VALUE str)
9577{
9578 char table[TR_TABLE_SIZE];
9579 rb_encoding *enc = 0;
9580 VALUE del = 0, nodel = 0, tstr;
9581 const char *s, *send;
9582 int i;
9583 int ascompat;
9584 size_t n = 0;
9585
9587
9588 tstr = argv[0];
9589 StringValue(tstr);
9590 enc = rb_enc_check(str, tstr);
9591 if (argc == 1) {
9592 const char *ptstr;
9593 if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
9594 (ptstr = RSTRING_PTR(tstr),
9595 ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (const unsigned char *)ptstr, (const unsigned char *)ptstr+1)) &&
9596 !is_broken_string(str)) {
9597 int clen;
9598 unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
9599
9600 s = RSTRING_PTR(str);
9601 if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
9602 send = RSTRING_END(str);
9603 while (s < send) {
9604 if (*(unsigned char*)s++ == c) n++;
9605 }
9606 return SIZET2NUM(n);
9607 }
9608 }
9609
9610 tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
9611 for (i=1; i<argc; i++) {
9612 tstr = argv[i];
9613 StringValue(tstr);
9614 enc = rb_enc_check(str, tstr);
9615 tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
9616 }
9617
9618 s = RSTRING_PTR(str);
9619 if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
9620 send = RSTRING_END(str);
9621 ascompat = rb_enc_asciicompat(enc);
9622 while (s < send) {
9623 unsigned int c;
9624
9625 if (ascompat && (c = *(unsigned char*)s) < 0x80) {
9626 if (table[c]) {
9627 n++;
9628 }
9629 s++;
9630 }
9631 else {
9632 int clen;
9633 c = rb_enc_codepoint_len(s, send, &clen, enc);
9634 if (tr_find(c, table, del, nodel)) {
9635 n++;
9636 }
9637 s += clen;
9638 }
9639 }
9640
9641 return SIZET2NUM(n);
9642}
9643
9644static VALUE
9645rb_fs_check(VALUE val)
9646{
9647 if (!NIL_P(val) && !RB_TYPE_P(val, T_STRING) && !RB_TYPE_P(val, T_REGEXP)) {
9648 val = rb_check_string_type(val);
9649 if (NIL_P(val)) return 0;
9650 }
9651 return val;
9652}
9653
9654static const char isspacetable[256] = {
9655 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
9656 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9657 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9658 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9659 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9660 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9661 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9662 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9663 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9664 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9665 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9666 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9670 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
9671};
9672
9673#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
9674
9675static long
9676split_string(VALUE result, VALUE str, long beg, long len, long empty_count)
9677{
9678 if (empty_count >= 0 && len == 0) {
9679 return empty_count + 1;
9680 }
9681 if (empty_count > 0) {
9682 /* make different substrings */
9683 if (result) {
9684 do {
9685 rb_ary_push(result, str_new_empty_String(str));
9686 } while (--empty_count > 0);
9687 }
9688 else {
9689 do {
9690 rb_yield(str_new_empty_String(str));
9691 } while (--empty_count > 0);
9692 }
9693 }
9694 str = rb_str_subseq(str, beg, len);
9695 if (result) {
9696 rb_ary_push(result, str);
9697 }
9698 else {
9699 rb_yield(str);
9700 }
9701 return empty_count;
9702}
9703
9704typedef enum {
9705 SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
9706} split_type_t;
9707
9708static split_type_t
9709literal_split_pattern(VALUE spat, split_type_t default_type)
9710{
9711 rb_encoding *enc = STR_ENC_GET(spat);
9712 const char *ptr;
9713 long len;
9714 RSTRING_GETMEM(spat, ptr, len);
9715 if (len == 0) {
9716 /* Special case - split into chars */
9717 return SPLIT_TYPE_CHARS;
9718 }
9719 else if (rb_enc_asciicompat(enc)) {
9720 if (len == 1 && ptr[0] == ' ') {
9721 return SPLIT_TYPE_AWK;
9722 }
9723 }
9724 else {
9725 int l;
9726 if (rb_enc_ascget(ptr, ptr + len, &l, enc) == ' ' && len == l) {
9727 return SPLIT_TYPE_AWK;
9728 }
9729 }
9730 return default_type;
9731}
9732
9733/*
9734 * call-seq:
9735 * split(field_sep = $;, limit = 0) -> array_of_substrings
9736 * split(field_sep = $;, limit = 0) {|substring| ... } -> self
9737 *
9738 * :include: doc/string/split.rdoc
9739 *
9740 */
9741
9742static VALUE
9743rb_str_split_m(int argc, VALUE *argv, VALUE str)
9744{
9745 rb_encoding *enc;
9746 VALUE spat;
9747 VALUE limit;
9748 split_type_t split_type;
9749 long beg, end, i = 0, empty_count = -1;
9750 int lim = 0;
9751 VALUE result, tmp;
9752
9753 result = rb_block_given_p() ? Qfalse : Qnil;
9754 if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
9755 lim = NUM2INT(limit);
9756 if (lim <= 0) limit = Qnil;
9757 else if (lim == 1) {
9758 if (RSTRING_LEN(str) == 0)
9759 return result ? rb_ary_new2(0) : str;
9760 tmp = str_duplicate(rb_cString, str);
9761 if (!result) {
9762 rb_yield(tmp);
9763 return str;
9764 }
9765 return rb_ary_new3(1, tmp);
9766 }
9767 i = 1;
9768 }
9769 if (NIL_P(limit) && !lim) empty_count = 0;
9770
9771 enc = STR_ENC_GET(str);
9772 split_type = SPLIT_TYPE_REGEXP;
9773 if (!NIL_P(spat)) {
9774 spat = get_pat_quoted(spat, 0);
9775 }
9776 else if (NIL_P(spat = rb_fs)) {
9777 split_type = SPLIT_TYPE_AWK;
9778 }
9779 else if (!(spat = rb_fs_check(spat))) {
9780 rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
9781 }
9782 else {
9783 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$; is set to non-nil value");
9784 }
9785 if (split_type != SPLIT_TYPE_AWK) {
9786 switch (BUILTIN_TYPE(spat)) {
9787 case T_REGEXP:
9788 rb_reg_options(spat); /* check if uninitialized */
9789 tmp = RREGEXP_SRC(spat);
9790 split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
9791 if (split_type == SPLIT_TYPE_AWK) {
9792 spat = tmp;
9793 split_type = SPLIT_TYPE_STRING;
9794 }
9795 break;
9796
9797 case T_STRING:
9798 mustnot_broken(spat);
9799 split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
9800 break;
9801
9802 default:
9804 }
9805 }
9806
9807#define SPLIT_STR(beg, len) ( \
9808 empty_count = split_string(result, str, beg, len, empty_count), \
9809 str_mod_check(str, str_start, str_len))
9810
9811 beg = 0;
9812 const char *ptr = RSTRING_PTR(str);
9813 const char *const str_start = ptr;
9814 const long str_len = RSTRING_LEN(str);
9815 const char *const eptr = str_start + str_len;
9816 if (split_type == SPLIT_TYPE_AWK) {
9817 const char *bptr = ptr;
9818 int skip = 1;
9819 unsigned int c;
9820
9821 if (result) result = rb_ary_new();
9822 end = beg;
9823 if (is_ascii_string(str)) {
9824 while (ptr < eptr) {
9825 c = (unsigned char)*ptr++;
9826 if (skip) {
9827 if (ascii_isspace(c)) {
9828 beg = ptr - bptr;
9829 }
9830 else {
9831 end = ptr - bptr;
9832 skip = 0;
9833 if (!NIL_P(limit) && lim <= i) break;
9834 }
9835 }
9836 else if (ascii_isspace(c)) {
9837 SPLIT_STR(beg, end-beg);
9838 skip = 1;
9839 beg = ptr - bptr;
9840 if (!NIL_P(limit)) ++i;
9841 }
9842 else {
9843 end = ptr - bptr;
9844 }
9845 }
9846 }
9847 else {
9848 while (ptr < eptr) {
9849 int n;
9850
9851 c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
9852 ptr += n;
9853 if (skip) {
9854 if (rb_isspace(c)) {
9855 beg = ptr - bptr;
9856 }
9857 else {
9858 end = ptr - bptr;
9859 skip = 0;
9860 if (!NIL_P(limit) && lim <= i) break;
9861 }
9862 }
9863 else if (rb_isspace(c)) {
9864 SPLIT_STR(beg, end-beg);
9865 skip = 1;
9866 beg = ptr - bptr;
9867 if (!NIL_P(limit)) ++i;
9868 }
9869 else {
9870 end = ptr - bptr;
9871 }
9872 }
9873 }
9874 }
9875 else if (split_type == SPLIT_TYPE_STRING) {
9876 const char *substr_start = ptr;
9877 const char *sptr = RSTRING_PTR(spat);
9878 long slen = RSTRING_LEN(spat);
9879
9880 if (result) result = rb_ary_new();
9881 mustnot_broken(str);
9882 enc = rb_enc_check(str, spat);
9883 while (ptr < eptr &&
9884 (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
9885 /* Check we are at the start of a char */
9886 const char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
9887 if (t != ptr + end) {
9888 ptr = t;
9889 continue;
9890 }
9891 SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
9892 str_mod_check(spat, sptr, slen);
9893 ptr += end + slen;
9894 substr_start = ptr;
9895 if (!NIL_P(limit) && lim <= ++i) break;
9896 }
9897 beg = ptr - str_start;
9898 }
9899 else if (split_type == SPLIT_TYPE_CHARS) {
9900 int n;
9901
9902 if (result) result = rb_ary_new_capa(RSTRING_LEN(str));
9903 mustnot_broken(str);
9904 enc = rb_enc_get(str);
9905 while (ptr < eptr &&
9906 (n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
9907 SPLIT_STR(ptr - str_start, n);
9908 ptr += n;
9909 if (!NIL_P(limit) && lim <= ++i) break;
9910 }
9911 beg = ptr - str_start;
9912 }
9913 else {
9914 if (result) result = rb_ary_new();
9915 long len = RSTRING_LEN(str);
9916 long start = beg;
9917 int idx;
9918 int last_null = 0;
9919 VALUE match = 0;
9920
9921 for (; rb_reg_search(spat, str, start, 0) >= 0;
9922 (match ? (rb_match_unbusy(match), rb_backref_set(match)) : (void)0)) {
9923 match = rb_backref_get();
9924 if (!result) rb_match_busy(match);
9925 end = RMATCH_BEG(match, 0);
9926 if (start == end && RMATCH_BEG(match, 0) == RMATCH_END(match, 0)) {
9927 if (!ptr) {
9928 SPLIT_STR(0, 0);
9929 break;
9930 }
9931 else if (last_null == 1) {
9932 SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
9933 beg = start;
9934 }
9935 else {
9936 if (start == len)
9937 start++;
9938 else
9939 start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
9940 last_null = 1;
9941 continue;
9942 }
9943 }
9944 else {
9945 SPLIT_STR(beg, end-beg);
9946 beg = start = RMATCH_END(match, 0);
9947 }
9948 last_null = 0;
9949
9950 for (idx = 1; idx < RMATCH_NREGS(match); idx++) {
9951 if (RMATCH_BEG(match, idx) == -1) continue;
9952 SPLIT_STR(RMATCH_BEG(match, idx), RMATCH_END(match, idx) - RMATCH_BEG(match, idx));
9953 }
9954 if (!NIL_P(limit) && lim <= ++i) break;
9955 }
9956 if (match) rb_match_unbusy(match);
9957 }
9958 if (RSTRING_LEN(str) > 0 && (!NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
9959 SPLIT_STR(beg, RSTRING_LEN(str)-beg);
9960 }
9961
9962 return result ? result : str;
9963}
9964
9965VALUE
9966rb_str_split(VALUE str, const char *sep0)
9967{
9968 VALUE sep;
9969
9970 StringValue(str);
9971 sep = rb_str_new_cstr(sep0);
9972 return rb_str_split_m(1, &sep, str);
9973}
9974
9975#define WANTARRAY(m, size) (!rb_block_given_p() ? rb_ary_new_capa(size) : 0)
9976
9977static inline int
9978enumerator_element(VALUE ary, VALUE e)
9979{
9980 if (ary) {
9981 rb_ary_push(ary, e);
9982 return 0;
9983 }
9984 else {
9985 rb_yield(e);
9986 return 1;
9987 }
9988}
9989
9990#define ENUM_ELEM(ary, e) enumerator_element(ary, e)
9991
9992static const char *
9993chomp_newline(const char *p, const char *e, rb_encoding *enc)
9994{
9995 const char *prev = rb_enc_prev_char(p, e, e, enc);
9996 if (rb_enc_is_newline(prev, e, enc)) {
9997 e = prev;
9998 prev = rb_enc_prev_char(p, e, e, enc);
9999 if (prev && rb_enc_ascget(prev, e, NULL, enc) == '\r')
10000 e = prev;
10001 }
10002 return e;
10003}
10004
10005static VALUE
10006get_rs(void)
10007{
10008 VALUE rs = rb_rs;
10009 if (!NIL_P(rs) &&
10010 (!RB_TYPE_P(rs, T_STRING) ||
10011 RSTRING_LEN(rs) != 1 ||
10012 RSTRING_PTR(rs)[0] != '\n')) {
10013 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$/ is set to non-default value");
10014 }
10015 return rs;
10016}
10017
10018#define rb_rs get_rs()
10019
10020static VALUE
10021rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary)
10022{
10023 rb_encoding *enc;
10024 VALUE line, rs, orig = str, opts = Qnil, chomp = Qfalse;
10025 const char *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
10026 long pos, rslen;
10027 int rsnewline = 0;
10028
10029 if (rb_scan_args(argc, argv, "01:", &rs, &opts) == 0)
10030 rs = rb_rs;
10031 if (!NIL_P(opts)) {
10032 static ID keywords[1];
10033 if (!keywords[0]) {
10034 keywords[0] = rb_intern_const("chomp");
10035 }
10036 rb_get_kwargs(opts, keywords, 0, 1, &chomp);
10037 chomp = (!UNDEF_P(chomp) && RTEST(chomp));
10038 }
10039
10040 if (NIL_P(rs)) {
10041 if (!ENUM_ELEM(ary, str)) {
10042 return ary;
10043 }
10044 else {
10045 return orig;
10046 }
10047 }
10048
10049 if (!RSTRING_LEN(str)) goto end;
10050 str = rb_str_new_frozen(str);
10051 const char *const ptr = subptr = RSTRING_PTR(str);
10052 const long len = RSTRING_LEN(str);
10053 pend = RSTRING_END(str);
10054 StringValue(rs);
10055 rslen = RSTRING_LEN(rs);
10056
10057 if (rs == rb_default_rs)
10058 enc = rb_enc_get(str);
10059 else
10060 enc = rb_enc_check(str, rs);
10061
10062 if (rslen == 0) {
10063 /* paragraph mode */
10064 int n;
10065 const char *eol = NULL;
10066 subend = subptr;
10067 while (subend < pend) {
10068 long chomp_rslen = 0;
10069 do {
10070 if (rb_enc_ascget(subend, pend, &n, enc) != '\r')
10071 n = 0;
10072 rslen = n + rb_enc_mbclen(subend + n, pend, enc);
10073 if (rb_enc_is_newline(subend + n, pend, enc)) {
10074 if (eol == subend) break;
10075 subend += rslen;
10076 if (subptr) {
10077 eol = subend;
10078 chomp_rslen = -rslen;
10079 }
10080 }
10081 else {
10082 if (!subptr) subptr = subend;
10083 subend += rslen;
10084 }
10085 rslen = 0;
10086 } while (subend < pend);
10087 if (!subptr) break;
10088 if (rslen == 0) chomp_rslen = 0;
10089 line = rb_str_subseq(str, subptr - ptr,
10090 subend - subptr + (chomp ? chomp_rslen : rslen));
10091 if (ENUM_ELEM(ary, line)) {
10092 str_mod_check(str, ptr, len);
10093 }
10094 subptr = eol = NULL;
10095 }
10096 goto end;
10097 }
10098 else {
10099 rsptr = RSTRING_PTR(rs);
10100 if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
10101 rb_enc_is_newline(rsptr, rsptr + RSTRING_LEN(rs), enc)) {
10102 rsnewline = 1;
10103 }
10104 }
10105
10106 if ((rs == rb_default_rs) && !rb_enc_asciicompat(enc)) {
10107 rs = rb_str_new(rsptr, rslen);
10108 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
10109 rsptr = RSTRING_PTR(rs);
10110 rslen = RSTRING_LEN(rs);
10111 }
10112
10113 while (subptr < pend) {
10114 pos = rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
10115 if (pos < 0) break;
10116 hit = subptr + pos;
10117 adjusted = rb_enc_right_char_head(subptr, hit, pend, enc);
10118 if (hit != adjusted) {
10119 subptr = adjusted;
10120 continue;
10121 }
10122 subend = hit += rslen;
10123 if (chomp) {
10124 if (rsnewline) {
10125 subend = chomp_newline(subptr, subend, enc);
10126 }
10127 else {
10128 subend -= rslen;
10129 }
10130 }
10131 line = rb_str_subseq(str, subptr - ptr, subend - subptr);
10132 if (ENUM_ELEM(ary, line)) {
10133 str_mod_check(str, ptr, len);
10134 }
10135 subptr = hit;
10136 }
10137
10138 if (subptr != pend) {
10139 if (chomp) {
10140 if (rsnewline) {
10141 pend = chomp_newline(subptr, pend, enc);
10142 }
10143 else if (pend - subptr >= rslen &&
10144 memcmp(pend - rslen, rsptr, rslen) == 0) {
10145 pend -= rslen;
10146 }
10147 }
10148 line = rb_str_subseq(str, subptr - ptr, pend - subptr);
10149 ENUM_ELEM(ary, line);
10150 RB_GC_GUARD(str);
10151 }
10152
10153 end:
10154 if (ary)
10155 return ary;
10156 else
10157 return orig;
10158}
10159
10160/*
10161 * call-seq:
10162 * each_line(record_separator = $/, chomp: false) {|substring| ... } -> self
10163 * each_line(record_separator = $/, chomp: false) -> enumerator
10164 *
10165 * :include: doc/string/each_line.rdoc
10166 *
10167 */
10168
10169static VALUE
10170rb_str_each_line(int argc, VALUE *argv, VALUE str)
10171{
10172 RETURN_SIZED_ENUMERATOR(str, argc, argv, 0);
10173 return rb_str_enumerate_lines(argc, argv, str, 0);
10174}
10175
10176/*
10177 * call-seq:
10178 * lines(record_separator = $/, chomp: false) -> array_of_strings
10179 *
10180 * Returns substrings ("lines") of +self+
10181 * according to the given arguments:
10182 *
10183 * s = <<~EOT
10184 * This is the first line.
10185 * This is line two.
10186 *
10187 * This is line four.
10188 * This is line five.
10189 * EOT
10190 *
10191 * With the default argument values:
10192 *
10193 * $/ # => "\n"
10194 * s.lines
10195 * # =>
10196 * ["This is the first line.\n",
10197 * "This is line two.\n",
10198 * "\n",
10199 * "This is line four.\n",
10200 * "This is line five.\n"]
10201 *
10202 * With a different +record_separator+:
10203 *
10204 * record_separator = ' is '
10205 * s.lines(record_separator)
10206 * # =>
10207 * ["This is ",
10208 * "the first line.\nThis is ",
10209 * "line two.\n\nThis is ",
10210 * "line four.\nThis is ",
10211 * "line five.\n"]
10212 *
10213 * With keyword argument +chomp+ as +true+,
10214 * removes the trailing newline from each line:
10215 *
10216 * s.lines(chomp: true)
10217 * # =>
10218 * ["This is the first line.",
10219 * "This is line two.",
10220 * "",
10221 * "This is line four.",
10222 * "This is line five."]
10223 *
10224 * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non-String].
10225 */
10226
10227static VALUE
10228rb_str_lines(int argc, VALUE *argv, VALUE str)
10229{
10230 VALUE ary = WANTARRAY("lines", 0);
10231 return rb_str_enumerate_lines(argc, argv, str, ary);
10232}
10233
10234static VALUE
10235rb_str_each_byte_size(VALUE str, VALUE args, VALUE eobj)
10236{
10237 return LONG2FIX(RSTRING_LEN(str));
10238}
10239
10240static VALUE
10241rb_str_enumerate_bytes(VALUE str, VALUE ary)
10242{
10243 long i;
10244
10245 for (i=0; i<RSTRING_LEN(str); i++) {
10246 ENUM_ELEM(ary, INT2FIX((unsigned char)RSTRING_PTR(str)[i]));
10247 }
10248 if (ary)
10249 return ary;
10250 else
10251 return str;
10252}
10253
10254/*
10255 * call-seq:
10256 * each_byte {|byte| ... } -> self
10257 * each_byte -> enumerator
10258 *
10259 * :include: doc/string/each_byte.rdoc
10260 *
10261 */
10262
10263static VALUE
10264rb_str_each_byte(VALUE str)
10265{
10266 RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_byte_size);
10267 return rb_str_enumerate_bytes(str, 0);
10268}
10269
10270/*
10271 * call-seq:
10272 * bytes -> array_of_bytes
10273 *
10274 * :include: doc/string/bytes.rdoc
10275 *
10276 */
10277
10278static VALUE
10279rb_str_bytes(VALUE str)
10280{
10281 VALUE ary = WANTARRAY("bytes", RSTRING_LEN(str));
10282 return rb_str_enumerate_bytes(str, ary);
10283}
10284
10285static VALUE
10286rb_str_each_char_size(VALUE str, VALUE args, VALUE eobj)
10287{
10288 return rb_str_length(str);
10289}
10290
10291static VALUE
10292rb_str_enumerate_chars(VALUE str, VALUE ary)
10293{
10294 VALUE orig = str;
10295 long i, len, n;
10296 const char *ptr;
10297 rb_encoding *enc;
10298
10299 str = rb_str_new_frozen(str);
10300 ptr = RSTRING_PTR(str);
10301 len = RSTRING_LEN(str);
10302 enc = rb_enc_get(str);
10303
10305 for (i = 0; i < len; i += n) {
10306 n = rb_enc_fast_mbclen(ptr + i, ptr + len, enc);
10307 ENUM_ELEM(ary, rb_str_subseq(str, i, n));
10308 }
10309 }
10310 else {
10311 for (i = 0; i < len; i += n) {
10312 n = rb_enc_mbclen(ptr + i, ptr + len, enc);
10313 ENUM_ELEM(ary, rb_str_subseq(str, i, n));
10314 }
10315 }
10316 RB_GC_GUARD(str);
10317 if (ary)
10318 return ary;
10319 else
10320 return orig;
10321}
10322
10323/*
10324 * call-seq:
10325 * each_char {|char| ... } -> self
10326 * each_char -> enumerator
10327 *
10328 * :include: doc/string/each_char.rdoc
10329 *
10330 */
10331
10332static VALUE
10333rb_str_each_char(VALUE str)
10334{
10335 RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
10336 return rb_str_enumerate_chars(str, 0);
10337}
10338
10339/*
10340 * call-seq:
10341 * chars -> array_of_characters
10342 *
10343 * :include: doc/string/chars.rdoc
10344 *
10345 */
10346
10347static VALUE
10348rb_str_chars(VALUE str)
10349{
10350 VALUE ary = WANTARRAY("chars", rb_str_strlen(str));
10351 return rb_str_enumerate_chars(str, ary);
10352}
10353
10354static VALUE
10355rb_str_enumerate_codepoints(VALUE str, VALUE ary)
10356{
10357 VALUE orig = str;
10358 int n;
10359 unsigned int c;
10360 const char *ptr, *end;
10361 rb_encoding *enc;
10362 int enc_asciicompat;
10363
10364 if (single_byte_optimizable(str))
10365 return rb_str_enumerate_bytes(str, ary);
10366
10367 str = rb_str_new_frozen(str);
10368 ptr = RSTRING_PTR(str);
10369 end = RSTRING_END(str);
10370 enc = STR_ENC_GET(str);
10371 enc_asciicompat = rb_enc_asciicompat(enc);
10372
10373 while (ptr < end) {
10374 /* Fast path: ASCII byte in an ASCII-compatible encoding is its own codepoint;
10375 * skip rb_enc_codepoint_len and return the byte directly.
10376 */
10377 n = 1;
10378 c = (enc_asciicompat && ISASCII(*ptr)) ?
10379 (unsigned char)*ptr : rb_enc_codepoint_len(ptr, end, &n, enc);
10380 ENUM_ELEM(ary, UINT2NUM(c));
10381 ptr += n;
10382 }
10383 RB_GC_GUARD(str);
10384 if (ary)
10385 return ary;
10386 else
10387 return orig;
10388}
10389
10390/*
10391 * call-seq:
10392 * each_codepoint {|codepoint| ... } -> self
10393 * each_codepoint -> enumerator
10394 *
10395 * :include: doc/string/each_codepoint.rdoc
10396 *
10397 */
10398
10399static VALUE
10400rb_str_each_codepoint(VALUE str)
10401{
10402 RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_char_size);
10403 return rb_str_enumerate_codepoints(str, 0);
10404}
10405
10406/*
10407 * call-seq:
10408 * codepoints -> array_of_integers
10409 *
10410 * :include: doc/string/codepoints.rdoc
10411 *
10412 */
10413
10414static VALUE
10415rb_str_codepoints(VALUE str)
10416{
10417 VALUE ary = WANTARRAY("codepoints", rb_str_strlen(str));
10418 return rb_str_enumerate_codepoints(str, ary);
10419}
10420
10421static regex_t *
10422get_reg_grapheme_cluster(rb_encoding *enc)
10423{
10424 int encidx = rb_enc_to_index(enc);
10425
10426 const OnigUChar source_ascii[] = "\\X";
10427 const OnigUChar *source = source_ascii;
10428 size_t source_len = sizeof(source_ascii) - 1;
10429
10430 switch (encidx) {
10431#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
10432#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
10433#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
10434#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
10435#define CASE_UTF(e) \
10436 case ENCINDEX_UTF_##e: { \
10437 static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
10438 source = source_UTF_##e; \
10439 source_len = sizeof(source_UTF_##e); \
10440 break; \
10441 }
10442 CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
10443#undef CASE_UTF
10444#undef CHARS_16BE
10445#undef CHARS_16LE
10446#undef CHARS_32BE
10447#undef CHARS_32LE
10448 }
10449
10450 regex_t *reg_grapheme_cluster;
10451 OnigErrorInfo einfo;
10452 int r = onig_new(&reg_grapheme_cluster, source, source + source_len,
10453 ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
10454 if (r) {
10455 UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
10456 onig_error_code_to_str(message, r, &einfo);
10457 rb_fatal("cannot compile grapheme cluster regexp: %s", (char *)message);
10458 }
10459
10460 return reg_grapheme_cluster;
10461}
10462
10463static regex_t *
10464get_cached_reg_grapheme_cluster(rb_encoding *enc)
10465{
10466 int encidx = rb_enc_to_index(enc);
10467 static regex_t *reg_grapheme_cluster_utf8 = NULL;
10468
10469 if (encidx == rb_utf8_encindex()) {
10470 if (!reg_grapheme_cluster_utf8) {
10471 reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
10472 }
10473
10474 return reg_grapheme_cluster_utf8;
10475 }
10476
10477 return NULL;
10478}
10479
10480static VALUE
10481rb_str_each_grapheme_cluster_size(VALUE str, VALUE args, VALUE eobj)
10482{
10483 size_t grapheme_cluster_count = 0;
10484 rb_encoding *enc = get_encoding(str);
10485 const char *ptr, *end;
10486
10487 if (!rb_enc_unicode_p(enc)) {
10488 return rb_str_length(str);
10489 }
10490
10491 bool cached_reg_grapheme_cluster = true;
10492 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
10493 if (!reg_grapheme_cluster) {
10494 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
10495 cached_reg_grapheme_cluster = false;
10496 }
10497
10498 ptr = RSTRING_PTR(str);
10499 end = RSTRING_END(str);
10500
10501 while (ptr < end) {
10502 OnigPosition len = onig_match(reg_grapheme_cluster,
10503 (const OnigUChar *)ptr, (const OnigUChar *)end,
10504 (const OnigUChar *)ptr, NULL, 0);
10505 if (len <= 0) break;
10506 grapheme_cluster_count++;
10507 ptr += len;
10508 }
10509
10510 if (!cached_reg_grapheme_cluster) {
10511 onig_free(reg_grapheme_cluster);
10512 }
10513
10514 return SIZET2NUM(grapheme_cluster_count);
10515}
10516
10517static VALUE
10518rb_str_enumerate_grapheme_clusters(VALUE str, VALUE ary)
10519{
10520 VALUE orig = str;
10521 rb_encoding *enc = get_encoding(str);
10522 const char *ptr0, *ptr, *end;
10523
10524 if (!rb_enc_unicode_p(enc)) {
10525 return rb_str_enumerate_chars(str, ary);
10526 }
10527
10528 if (!ary) str = rb_str_new_frozen(str);
10529
10530 bool cached_reg_grapheme_cluster = true;
10531 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
10532 if (!reg_grapheme_cluster) {
10533 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
10534 cached_reg_grapheme_cluster = false;
10535 }
10536
10537 ptr0 = ptr = RSTRING_PTR(str);
10538 end = RSTRING_END(str);
10539
10540 while (ptr < end) {
10541 OnigPosition len = onig_match(reg_grapheme_cluster,
10542 (const OnigUChar *)ptr, (const OnigUChar *)end,
10543 (const OnigUChar *)ptr, NULL, 0);
10544 if (len <= 0) break;
10545 ENUM_ELEM(ary, rb_str_subseq(str, ptr-ptr0, len));
10546 ptr += len;
10547 }
10548
10549 if (!cached_reg_grapheme_cluster) {
10550 onig_free(reg_grapheme_cluster);
10551 }
10552
10553 RB_GC_GUARD(str);
10554 if (ary)
10555 return ary;
10556 else
10557 return orig;
10558}
10559
10560/*
10561 * call-seq:
10562 * each_grapheme_cluster {|grapheme_cluster| ... } -> self
10563 * each_grapheme_cluster -> enumerator
10564 *
10565 * :include: doc/string/each_grapheme_cluster.rdoc
10566 *
10567 */
10568
10569static VALUE
10570rb_str_each_grapheme_cluster(VALUE str)
10571{
10572 RETURN_SIZED_ENUMERATOR(str, 0, 0, rb_str_each_grapheme_cluster_size);
10573 return rb_str_enumerate_grapheme_clusters(str, 0);
10574}
10575
10576/*
10577 * call-seq:
10578 * grapheme_clusters -> array_of_grapheme_clusters
10579 *
10580 * :include: doc/string/grapheme_clusters.rdoc
10581 *
10582 */
10583
10584static VALUE
10585rb_str_grapheme_clusters(VALUE str)
10586{
10587 VALUE ary = WANTARRAY("grapheme_clusters", rb_str_strlen(str));
10588 return rb_str_enumerate_grapheme_clusters(str, ary);
10589}
10590
10591static long
10592chopped_length(VALUE str)
10593{
10594 rb_encoding *enc = STR_ENC_GET(str);
10595 const char *p, *p2, *beg, *end;
10596
10597 beg = RSTRING_PTR(str);
10598 end = beg + RSTRING_LEN(str);
10599 if (beg >= end) return 0;
10600 p = rb_enc_prev_char(beg, end, end, enc);
10601 if (!p) return 0;
10602 if (p > beg && rb_enc_ascget(p, end, 0, enc) == '\n') {
10603 p2 = rb_enc_prev_char(beg, p, end, enc);
10604 if (p2 && rb_enc_ascget(p2, end, 0, enc) == '\r') p = p2;
10605 }
10606 return p - beg;
10607}
10608
10609/*
10610 * call-seq:
10611 * chop! -> self or nil
10612 *
10613 * Like String#chop, except that:
10614 *
10615 * - Removes trailing characters from +self+ (not from a copy of +self+).
10616 * - Returns +self+ if any characters are removed, +nil+ otherwise.
10617 *
10618 * Related: see {Modifying}[rdoc-ref:String@Modifying].
10619 */
10620
10621static VALUE
10622rb_str_chop_bang(VALUE str)
10623{
10624 str_modify_keep_cr(str);
10625 if (RSTRING_LEN(str) > 0) {
10626 long len;
10627 len = chopped_length(str);
10628 STR_SET_LEN(str, len);
10629 TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
10630 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
10632 }
10633 return str;
10634 }
10635 return Qnil;
10636}
10637
10638
10639/*
10640 * call-seq:
10641 * chop -> new_string
10642 *
10643 * :include: doc/string/chop.rdoc
10644 *
10645 */
10646
10647static VALUE
10648rb_str_chop(VALUE str)
10649{
10650 return rb_str_subseq(str, 0, chopped_length(str));
10651}
10652
10653static long
10654smart_chomp(VALUE str, const char *e, const char *p)
10655{
10656 rb_encoding *enc = rb_enc_get(str);
10657 if (rb_enc_mbminlen(enc) > 1) {
10658 const char *pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
10659 if (rb_enc_is_newline(pp, e, enc)) {
10660 e = pp;
10661 }
10662 pp = e - rb_enc_mbminlen(enc);
10663 if (pp >= p) {
10664 pp = rb_enc_left_char_head(p, pp, e, enc);
10665 if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
10666 e = pp;
10667 }
10668 }
10669 }
10670 else {
10671 switch (*(e-1)) { /* not e[-1] to get rid of VC bug */
10672 case '\n':
10673 if (--e > p && *(e-1) == '\r') {
10674 --e;
10675 }
10676 break;
10677 case '\r':
10678 --e;
10679 break;
10680 }
10681 }
10682 return e - p;
10683}
10684
10685static long
10686chompped_length(VALUE str, VALUE rs)
10687{
10688 rb_encoding *enc;
10689 int newline;
10690 const char *pp, *e, *rsptr;
10691 long rslen;
10692 const char *const p = RSTRING_PTR(str);
10693 long len = RSTRING_LEN(str);
10694
10695 if (len == 0) return 0;
10696 e = p + len;
10697 if (rs == rb_default_rs) {
10698 return smart_chomp(str, e, p);
10699 }
10700
10701 enc = rb_enc_get(str);
10702 RSTRING_GETMEM(rs, rsptr, rslen);
10703 if (rslen == 0) {
10704 if (rb_enc_mbminlen(enc) > 1) {
10705 while (e > p) {
10706 pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
10707 if (!rb_enc_is_newline(pp, e, enc)) break;
10708 e = pp;
10709 pp -= rb_enc_mbminlen(enc);
10710 if (pp >= p) {
10711 pp = rb_enc_left_char_head(p, pp, e, enc);
10712 if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
10713 e = pp;
10714 }
10715 }
10716 }
10717 }
10718 else {
10719 while (e > p && *(e-1) == '\n') {
10720 --e;
10721 if (e > p && *(e-1) == '\r')
10722 --e;
10723 }
10724 }
10725 return e - p;
10726 }
10727 if (rslen > len) return len;
10728
10729 enc = rb_enc_get(rs);
10730 newline = rsptr[rslen-1];
10731 if (rslen == rb_enc_mbminlen(enc)) {
10732 if (rslen == 1) {
10733 if (newline == '\n')
10734 return smart_chomp(str, e, p);
10735 }
10736 else {
10737 if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
10738 return smart_chomp(str, e, p);
10739 }
10740 }
10741
10742 enc = rb_enc_check(str, rs);
10743 if (is_broken_string(rs)) {
10744 return len;
10745 }
10746 pp = e - rslen;
10747 if (p[len-1] == newline &&
10748 (rslen <= 1 ||
10749 memcmp(rsptr, pp, rslen) == 0)) {
10750 if (at_char_boundary(p, pp, e, enc))
10751 return len - rslen;
10752 RB_GC_GUARD(rs);
10753 }
10754 return len;
10755}
10756
10762static VALUE
10763chomp_rs(int argc, const VALUE *argv)
10764{
10765 rb_check_arity(argc, 0, 1);
10766 if (argc > 0) {
10767 VALUE rs = argv[0];
10768 if (!NIL_P(rs)) StringValue(rs);
10769 return rs;
10770 }
10771 else {
10772 return rb_rs;
10773 }
10774}
10775
10776VALUE
10777rb_str_chomp_string(VALUE str, VALUE rs)
10778{
10779 long olen = RSTRING_LEN(str);
10780 long len = chompped_length(str, rs);
10781 if (len >= olen) return Qnil;
10782 str_modify_keep_cr(str);
10783 STR_SET_LEN(str, len);
10784 TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
10785 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
10787 }
10788 return str;
10789}
10790
10791/*
10792 * call-seq:
10793 * chomp!(line_sep = $/) -> self or nil
10794 *
10795 * Like String#chomp, except that:
10796 *
10797 * - Removes trailing characters from +self+ (not from a copy of +self+).
10798 * - Returns +self+ if any characters are removed, +nil+ otherwise.
10799 *
10800 * Related: see {Modifying}[rdoc-ref:String@Modifying].
10801 */
10802
10803static VALUE
10804rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
10805{
10806 VALUE rs;
10807 str_modifiable(str);
10808 if (RSTRING_LEN(str) == 0 && argc < 2) return Qnil;
10809 rs = chomp_rs(argc, argv);
10810 if (NIL_P(rs)) return Qnil;
10811 return rb_str_chomp_string(str, rs);
10812}
10813
10814
10815/*
10816 * call-seq:
10817 * chomp(line_sep = $/) -> new_string
10818 *
10819 * :include: doc/string/chomp.rdoc
10820 *
10821 */
10822
10823static VALUE
10824rb_str_chomp(int argc, VALUE *argv, VALUE str)
10825{
10826 VALUE rs = chomp_rs(argc, argv);
10827 if (NIL_P(rs)) return str_duplicate(rb_cString, str);
10828 return rb_str_subseq(str, 0, chompped_length(str, rs));
10829}
10830
10831static void
10832tr_setup_table_multi(char table[TR_TABLE_SIZE], VALUE *tablep, VALUE *ctablep,
10833 VALUE str, int num_selectors, VALUE *selectors)
10834{
10835 int i;
10836
10837 for (i=0; i<num_selectors; i++) {
10838 VALUE selector = selectors[i];
10839 rb_encoding *enc;
10840
10841 StringValue(selector);
10842 enc = rb_enc_check(str, selector);
10843 tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
10844 }
10845}
10846
10847static long
10848lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
10849{
10850 const char *const start = s;
10851
10852 if (!s || s >= e) return 0;
10853
10854 /* remove spaces at head */
10855 if (single_byte_optimizable(str)) {
10856 while (s < e && (*s == '\0' || ascii_isspace(*s))) s++;
10857 }
10858 else {
10859 while (s < e) {
10860 int n;
10861 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10862
10863 if (cc && !rb_isspace(cc)) break;
10864 s += n;
10865 }
10866 }
10867 return s - start;
10868}
10869
10870static long
10871lstrip_offset_table(VALUE str, const char *s, const char *e, rb_encoding *enc,
10872 char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
10873{
10874 const char *const start = s;
10875
10876 if (!s || s >= e) return 0;
10877
10878 /* remove leading characters in the table */
10879 while (s < e) {
10880 int n;
10881 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10882
10883 if (!tr_find(cc, table, del, nodel)) break;
10884 s += n;
10885 }
10886 return s - start;
10887}
10888
10889/*
10890 * call-seq:
10891 * lstrip!(*selectors) -> self or nil
10892 *
10893 * Like String#lstrip, except that:
10894 *
10895 * - Performs stripping in +self+ (not in a copy of +self+).
10896 * - Returns +self+ if any characters are stripped, +nil+ otherwise.
10897 *
10898 * Related: see {Modifying}[rdoc-ref:String@Modifying].
10899 */
10900
10901static VALUE
10902rb_str_lstrip_bang(int argc, VALUE *argv, VALUE str)
10903{
10904 rb_encoding *enc;
10905 char *start;
10906 long olen, loffset;
10907
10908 str_modify_keep_cr(str);
10909 enc = STR_ENC_GET(str);
10910 RSTRING_GETMEM(str, start, olen);
10911 if (argc > 0) {
10912 char table[TR_TABLE_SIZE];
10913 VALUE del = 0, nodel = 0;
10914
10915 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10916 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10917 }
10918 else {
10919 loffset = lstrip_offset(str, start, start+olen, enc);
10920 }
10921
10922 if (loffset > 0) {
10923 long len = olen-loffset;
10924 memmove(start, start + loffset, len);
10925 STR_SET_LEN(str, len);
10926 TERM_FILL(start+len, rb_enc_mbminlen(enc));
10927 return str;
10928 }
10929 return Qnil;
10930}
10931
10932
10933/*
10934 * call-seq:
10935 * lstrip(*selectors) -> new_string
10936 *
10937 * Returns a copy of +self+ with leading whitespace removed;
10938 * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
10939 *
10940 * whitespace = "\x00\t\n\v\f\r "
10941 * s = whitespace + 'abc' + whitespace
10942 * # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
10943 * s.lstrip
10944 * # => "abc\u0000\t\n\v\f\r "
10945 *
10946 * If +selectors+ are given, removes characters of +selectors+ from the beginning of +self+:
10947 *
10948 * s = "---abc+++"
10949 * s.lstrip("-") # => "abc+++"
10950 *
10951 * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
10952 * and may use any of its valid forms, including negation, ranges, and escapes:
10953 *
10954 * "01234abc56789".lstrip("0-9") # "abc56789"
10955 * "01234abc56789".lstrip("0-9", "^4-6") # "4abc56789"
10956 *
10957 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
10958 */
10959
10960static VALUE
10961rb_str_lstrip(int argc, VALUE *argv, VALUE str)
10962{
10963 const char *start;
10964 long len, loffset;
10965
10966 RSTRING_GETMEM(str, start, len);
10967 if (argc > 0) {
10968 char table[TR_TABLE_SIZE];
10969 VALUE del = 0, nodel = 0;
10970
10971 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10972 loffset = lstrip_offset_table(str, start, start+len, STR_ENC_GET(str), table, del, nodel);
10973 }
10974 else {
10975 loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
10976 }
10977 if (loffset <= 0) return str_duplicate(rb_cString, str);
10978 return rb_str_subseq(str, loffset, len - loffset);
10979}
10980
10981static long
10982rstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
10983{
10984 const char *t;
10985
10986 rb_str_check_dummy_enc(enc);
10987 if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
10988 rb_raise(rb_eEncCompatError, "invalid byte sequence in %s", rb_enc_name(enc));
10989 }
10990 if (!s || s >= e) return 0;
10991 t = e;
10992
10993 /* remove trailing spaces or '\0's */
10994 if (single_byte_optimizable(str)) {
10995 unsigned char c;
10996 while (s < t && ((c = *(t-1)) == '\0' || ascii_isspace(c))) t--;
10997 }
10998 else {
10999 const char *tp;
11000
11001 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11002 unsigned int c = rb_enc_codepoint(tp, e, enc);
11003 if (c && !rb_isspace(c)) break;
11004 t = tp;
11005 }
11006 }
11007 return e - t;
11008}
11009
11010static long
11011rstrip_offset_table(VALUE str, const char *s, const char *e, rb_encoding *enc,
11012 char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
11013{
11014 const char *t, *tp;
11015
11016 rb_str_check_dummy_enc(enc);
11017 if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
11018 rb_raise(rb_eEncCompatError, "invalid byte sequence in %s", rb_enc_name(enc));
11019 }
11020 if (!s || s >= e) return 0;
11021 t = e;
11022
11023 /* remove trailing characters in the table */
11024 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11025 unsigned int c = rb_enc_codepoint(tp, e, enc);
11026 if (!tr_find(c, table, del, nodel)) break;
11027 t = tp;
11028 }
11029
11030 return e - t;
11031}
11032
11033/*
11034 * call-seq:
11035 * rstrip!(*selectors) -> self or nil
11036 *
11037 * Like String#rstrip, except that:
11038 *
11039 * - Performs stripping in +self+ (not in a copy of +self+).
11040 * - Returns +self+ if any characters are stripped, +nil+ otherwise.
11041 *
11042 * Related: see {Modifying}[rdoc-ref:String@Modifying].
11043 */
11044
11045static VALUE
11046rb_str_rstrip_bang(int argc, VALUE *argv, VALUE str)
11047{
11048 rb_encoding *enc;
11049 char *start;
11050 long olen, roffset;
11051
11052 str_modify_keep_cr(str);
11053 enc = STR_ENC_GET(str);
11054 RSTRING_GETMEM(str, start, olen);
11055 if (argc > 0) {
11056 char table[TR_TABLE_SIZE];
11057 VALUE del = 0, nodel = 0;
11058
11059 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11060 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11061 }
11062 else {
11063 roffset = rstrip_offset(str, start, start+olen, enc);
11064 }
11065 if (roffset > 0) {
11066 long len = olen - roffset;
11067
11068 STR_SET_LEN(str, len);
11069 TERM_FILL(start+len, rb_enc_mbminlen(enc));
11070 return str;
11071 }
11072 return Qnil;
11073}
11074
11075
11076/*
11077 * call-seq:
11078 * rstrip(*selectors) -> new_string
11079 *
11080 * Returns a copy of +self+ with trailing whitespace removed;
11081 * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
11082 *
11083 * whitespace = "\x00\t\n\v\f\r "
11084 * s = whitespace + 'abc' + whitespace
11085 * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
11086 * s.rstrip # => "\u0000\t\n\v\f\r abc"
11087 *
11088 * If +selectors+ are given, removes characters of +selectors+ from the end of +self+:
11089 *
11090 * s = "---abc+++"
11091 * s.rstrip("+") # => "---abc"
11092 *
11093 * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
11094 * and may use any of its valid forms, including negation, ranges, and escapes:
11095 *
11096 * "01234abc56789".rstrip("0-9") # "01234abc"
11097 * "01234abc56789".rstrip("0-9", "^4-6") # "01234abc56"
11098 *
11099 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
11100 */
11101
11102static VALUE
11103rb_str_rstrip(int argc, VALUE *argv, VALUE str)
11104{
11105 rb_encoding *enc;
11106 const char *start;
11107 long olen, roffset;
11108
11109 enc = STR_ENC_GET(str);
11110 RSTRING_GETMEM(str, start, olen);
11111 if (argc > 0) {
11112 char table[TR_TABLE_SIZE];
11113 VALUE del = 0, nodel = 0;
11114
11115 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11116 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11117 }
11118 else {
11119 roffset = rstrip_offset(str, start, start+olen, enc);
11120 }
11121 if (roffset <= 0) return str_duplicate(rb_cString, str);
11122 return rb_str_subseq(str, 0, olen-roffset);
11123}
11124
11125
11126/*
11127 * call-seq:
11128 * strip!(*selectors) -> self or nil
11129 *
11130 * Like String#strip, except that:
11131 *
11132 * - Any modifications are made to +self+.
11133 * - Returns +self+ if any modification are made, +nil+ otherwise.
11134 *
11135 * Related: see {Modifying}[rdoc-ref:String@Modifying].
11136 */
11137
11138static VALUE
11139rb_str_strip_bang(int argc, VALUE *argv, VALUE str)
11140{
11141 char *start;
11142 long olen, loffset, roffset;
11143 rb_encoding *enc;
11144
11145 str_modify_keep_cr(str);
11146 enc = STR_ENC_GET(str);
11147 RSTRING_GETMEM(str, start, olen);
11148
11149 if (argc > 0) {
11150 char table[TR_TABLE_SIZE];
11151 VALUE del = 0, nodel = 0;
11152
11153 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11154 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11155 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11156 }
11157 else {
11158 loffset = lstrip_offset(str, start, start+olen, enc);
11159 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11160 }
11161
11162 if (loffset > 0 || roffset > 0) {
11163 long len = olen-roffset;
11164 if (loffset > 0) {
11165 len -= loffset;
11166 memmove(start, start + loffset, len);
11167 }
11168 STR_SET_LEN(str, len);
11169 TERM_FILL(start+len, rb_enc_mbminlen(enc));
11170 return str;
11171 }
11172 return Qnil;
11173}
11174
11175
11176/*
11177 * call-seq:
11178 * strip(*selectors) -> new_string
11179 *
11180 * Returns a copy of +self+ with leading and trailing whitespace removed;
11181 * see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
11182 *
11183 * whitespace = "\x00\t\n\v\f\r "
11184 * s = whitespace + 'abc' + whitespace
11185 * # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
11186 * s.strip # => "abc"
11187 *
11188 * If +selectors+ are given, removes characters of +selectors+ from both ends of +self+:
11189 *
11190 * s = "---abc+++"
11191 * s.strip("-+") # => "abc"
11192 * s.strip("+-") # => "abc"
11193 *
11194 * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
11195 * and may use any of its valid forms, including negation, ranges, and escapes:
11196 *
11197 * "01234abc56789".strip("0-9") # "abc"
11198 * "01234abc56789".strip("0-9", "^4-6") # "4abc56"
11199 *
11200 * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
11201 */
11202
11203static VALUE
11204rb_str_strip(int argc, VALUE *argv, VALUE str)
11205{
11206 const char *start;
11207 long olen, loffset, roffset;
11208 rb_encoding *enc = STR_ENC_GET(str);
11209
11210 RSTRING_GETMEM(str, start, olen);
11211
11212 if (argc > 0) {
11213 char table[TR_TABLE_SIZE];
11214 VALUE del = 0, nodel = 0;
11215
11216 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11217 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11218 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11219 }
11220 else {
11221 loffset = lstrip_offset(str, start, start+olen, enc);
11222 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11223 }
11224
11225 if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str);
11226 return rb_str_subseq(str, loffset, olen-loffset-roffset);
11227}
11228
11229static VALUE
11230scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
11231{
11232 VALUE result = Qnil;
11233 long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
11234 if (pos >= 0) {
11235 VALUE match = Qnil;
11236 if (BUILTIN_TYPE(pat) == T_STRING) {
11237 end = pos + RSTRING_LEN(pat);
11238 }
11239 else {
11240 match = rb_backref_get();
11241 pos = RMATCH_BEG(match, 0);
11242 end = RMATCH_END(match, 0);
11243 }
11244
11245 if (pos == end) {
11246 rb_encoding *enc = STR_ENC_GET(str);
11247 /*
11248 * Always consume at least one character of the input string
11249 */
11250 if (RSTRING_LEN(str) > end)
11251 *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
11252 RSTRING_END(str), enc);
11253 else
11254 *start = end + 1;
11255 }
11256 else {
11257 *start = end;
11258 }
11259
11260 if (NIL_P(match) || RMATCH_NREGS(match) == 1) {
11261 result = rb_str_subseq(str, pos, end - pos);
11262 return result;
11263 }
11264 else {
11265 int num_regs = RMATCH_NREGS(match);
11266 result = rb_ary_new2(num_regs);
11267 for (int i = 1; i < num_regs; i++) {
11268 VALUE s = Qnil;
11269 if (RMATCH_BEG(match, i) >= 0) {
11270 s = rb_str_subseq(str, RMATCH_BEG(match, i), RMATCH_END(match, i) - RMATCH_BEG(match, i));
11271 }
11272
11273 rb_ary_push(result, s);
11274 }
11275 }
11276
11277 RB_GC_GUARD(match);
11278 }
11279
11280 return result;
11281}
11282
11283
11284/*
11285 * call-seq:
11286 * scan(pattern) -> array_of_results
11287 * scan(pattern) {|result| ... } -> self
11288 *
11289 * :include: doc/string/scan.rdoc
11290 *
11291 */
11292
11293static VALUE
11294rb_str_scan(VALUE str, VALUE pat)
11295{
11296 VALUE result;
11297 long start = 0;
11298 long last = -1, prev = 0;
11299 const char *p = RSTRING_PTR(str);
11300 long len = RSTRING_LEN(str);
11301
11302 pat = get_pat_quoted(pat, 1);
11303 mustnot_broken(str);
11304 if (!rb_block_given_p()) {
11305 VALUE ary = rb_ary_new();
11306
11307 while (!NIL_P(result = scan_once(str, pat, &start, 0))) {
11308 last = prev;
11309 prev = start;
11310 rb_ary_push(ary, result);
11311 }
11312 if (last >= 0) rb_pat_search(pat, str, last, 1);
11313 else rb_backref_set(Qnil);
11314 return ary;
11315 }
11316
11317 while (!NIL_P(result = scan_once(str, pat, &start, 1))) {
11318 last = prev;
11319 prev = start;
11320 rb_yield(result);
11321 str_mod_check(str, p, len);
11322 }
11323 if (last >= 0) rb_pat_search(pat, str, last, 1);
11324 return str;
11325}
11326
11327
11328/*
11329 * call-seq:
11330 * hex -> integer
11331 *
11332 * Interprets the leading substring of +self+ as hexadecimal, possibly signed;
11333 * returns its value as an integer.
11334 *
11335 * The leading substring is interpreted as hexadecimal when it begins with:
11336 *
11337 * - One or more character representing hexadecimal digits
11338 * (each in one of the ranges <tt>'0'..'9'</tt>, <tt>'a'..'f'</tt>, or <tt>'A'..'F'</tt>);
11339 * the string to be interpreted ends at the first character that does not represent a hexadecimal digit:
11340 *
11341 * 'f'.hex # => 15
11342 * '11'.hex # => 17
11343 * 'FFF'.hex # => 4095
11344 * 'fffg'.hex # => 4095
11345 * 'foo'.hex # => 15 # 'f' hexadecimal, 'oo' not.
11346 * 'bar'.hex # => 186 # 'ba' hexadecimal, 'r' not.
11347 * 'deadbeef'.hex # => 3735928559
11348 *
11349 * - <tt>'0x'</tt> or <tt>'0X'</tt>, followed by one or more hexadecimal digits:
11350 *
11351 * '0xfff'.hex # => 4095
11352 * '0xfffg'.hex # => 4095
11353 *
11354 * Any of the above may prefixed with <tt>'-'</tt>, which negates the interpreted value:
11355 *
11356 * '-fff'.hex # => -4095
11357 * '-0xFFF'.hex # => -4095
11358 *
11359 * For any substring not described above, returns zero:
11360 *
11361 * 'xxx'.hex # => 0
11362 * ''.hex # => 0
11363 *
11364 * Note that, unlike #oct, this method interprets only hexadecimal,
11365 * and not binary, octal, or decimal notations:
11366 *
11367 * '0b111'.hex # => 45329
11368 * '0o777'.hex # => 0
11369 * '0d999'.hex # => 55705
11370 *
11371 * Related: See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non-String].
11372 */
11373
11374static VALUE
11375rb_str_hex(VALUE str)
11376{
11377 return rb_str_to_inum(str, 16, FALSE);
11378}
11379
11380
11381/*
11382 * call-seq:
11383 * oct -> integer
11384 *
11385 * Interprets the leading substring of +self+ as octal, binary, decimal, or hexadecimal, possibly signed;
11386 * returns their value as an integer.
11387 *
11388 * In brief:
11389 *
11390 * # Interpreted as octal.
11391 * '777'.oct # => 511
11392 * '777x'.oct # => 511
11393 * '0777'.oct # => 511
11394 * '0o777'.oct # => 511
11395 * '-777'.oct # => -511
11396 * # Not interpreted as octal.
11397 * '0b111'.oct # => 7 # Interpreted as binary.
11398 * '0d999'.oct # => 999 # Interpreted as decimal.
11399 * '0xfff'.oct # => 4095 # Interpreted as hexadecimal.
11400 *
11401 * The leading substring is interpreted as octal when it begins with:
11402 *
11403 * - One or more character representing octal digits
11404 * (each in the range <tt>'0'..'7'</tt>);
11405 * the string to be interpreted ends at the first character that does not represent an octal digit:
11406 *
11407 * '7'.oct @ => 7
11408 * '11'.oct # => 9
11409 * '777'.oct # => 511
11410 * '0777'.oct # => 511
11411 * '7778'.oct # => 511
11412 * '777x'.oct # => 511
11413 *
11414 * - <tt>'0o'</tt>, followed by one or more octal digits:
11415 *
11416 * '0o777'.oct # => 511
11417 * '0o7778'.oct # => 511
11418 *
11419 * The leading substring is _not_ interpreted as octal when it begins with:
11420 *
11421 * - <tt>'0b'</tt>, followed by one or more characters representing binary digits
11422 * (each in the range <tt>'0'..'1'</tt>);
11423 * the string to be interpreted ends at the first character that does not represent a binary digit.
11424 * the string is interpreted as binary digits (base 2):
11425 *
11426 * '0b111'.oct # => 7
11427 * '0b1112'.oct # => 7
11428 *
11429 * - <tt>'0d'</tt>, followed by one or more characters representing decimal digits
11430 * (each in the range <tt>'0'..'9'</tt>);
11431 * the string to be interpreted ends at the first character that does not represent a decimal digit.
11432 * the string is interpreted as decimal digits (base 10):
11433 *
11434 * '0d999'.oct # => 999
11435 * '0d999x'.oct # => 999
11436 *
11437 * - <tt>'0x'</tt>, followed by one or more characters representing hexadecimal digits
11438 * (each in one of the ranges <tt>'0'..'9'</tt>, <tt>'a'..'f'</tt>, or <tt>'A'..'F'</tt>);
11439 * the string to be interpreted ends at the first character that does not represent a hexadecimal digit.
11440 * the string is interpreted as hexadecimal digits (base 16):
11441 *
11442 * '0xfff'.oct # => 4095
11443 * '0xfffg'.oct # => 4095
11444 *
11445 * Any of the above may prefixed with <tt>'-'</tt>, which negates the interpreted value:
11446 *
11447 * '-777'.oct # => -511
11448 * '-0777'.oct # => -511
11449 * '-0b111'.oct # => -7
11450 * '-0xfff'.oct # => -4095
11451 *
11452 * For any substring not described above, returns zero:
11453 *
11454 * 'foo'.oct # => 0
11455 * ''.oct # => 0
11456 *
11457 * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non-String].
11458 */
11459
11460static VALUE
11461rb_str_oct(VALUE str)
11462{
11463 return rb_str_to_inum(str, -8, FALSE);
11464}
11465
11466#ifndef HAVE_CRYPT_R
11467# include "ruby/thread_native.h"
11468# include "ruby/atomic.h"
11469
11470static struct {
11471 rb_nativethread_lock_t lock;
11472} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
11473#endif
11474
11475/*
11476 * call-seq:
11477 * crypt(salt_str) -> new_string
11478 *
11479 * Returns the string generated by calling <code>crypt(3)</code>
11480 * standard library function with <code>str</code> and
11481 * <code>salt_str</code>, in this order, as its arguments. Please do
11482 * not use this method any longer. It is legacy; provided only for
11483 * backward compatibility with ruby scripts in earlier days. It is
11484 * bad to use in contemporary programs for several reasons:
11485 *
11486 * * Behaviour of C's <code>crypt(3)</code> depends on the OS it is
11487 * run. The generated string lacks data portability.
11488 *
11489 * * On some OSes such as Mac OS, <code>crypt(3)</code> never fails
11490 * (i.e. silently ends up in unexpected results).
11491 *
11492 * * On some OSes such as Mac OS, <code>crypt(3)</code> is not
11493 * thread safe.
11494 *
11495 * * So-called "traditional" usage of <code>crypt(3)</code> is very
11496 * very very weak. According to its manpage, Linux's traditional
11497 * <code>crypt(3)</code> output has only 2**56 variations; too
11498 * easy to brute force today. And this is the default behaviour.
11499 *
11500 * * In order to make things robust some OSes implement so-called
11501 * "modular" usage. To go through, you have to do a complex
11502 * build-up of the <code>salt_str</code> parameter, by hand.
11503 * Failure in generation of a proper salt string tends not to
11504 * yield any errors; typos in parameters are normally not
11505 * detectable.
11506 *
11507 * * For instance, in the following example, the second invocation
11508 * of String#crypt is wrong; it has a typo in "round=" (lacks
11509 * "s"). However the call does not fail and something unexpected
11510 * is generated.
11511 *
11512 * "foo".crypt("$5$rounds=1000$salt$") # OK, proper usage
11513 * "foo".crypt("$5$round=1000$salt$") # Typo not detected
11514 *
11515 * * Even in the "modular" mode, some hash functions are considered
11516 * archaic and no longer recommended at all; for instance module
11517 * <code>$1$</code> is officially abandoned by its author: see
11518 * http://phk.freebsd.dk/sagas/md5crypt_eol/ . For another
11519 * instance module <code>$3$</code> is considered completely
11520 * broken: see the manpage of FreeBSD.
11521 *
11522 * * On some OS such as Mac OS, there is no modular mode. Yet, as
11523 * written above, <code>crypt(3)</code> on Mac OS never fails.
11524 * This means even if you build up a proper salt string it
11525 * generates a traditional DES hash anyways, and there is no way
11526 * for you to be aware of.
11527 *
11528 * "foo".crypt("$5$rounds=1000$salt$") # => "$5fNPQMxC5j6."
11529 *
11530 * If for some reason you cannot migrate to other secure contemporary
11531 * password hashing algorithms, install the string-crypt gem and
11532 * <code>require 'string/crypt'</code> to continue using it.
11533 */
11534
11535static VALUE
11536rb_str_crypt(VALUE str, VALUE salt)
11537{
11538#ifdef HAVE_CRYPT_R
11539 VALUE databuf;
11540 struct crypt_data *data;
11541# define CRYPT_END() ALLOCV_END(databuf)
11542#else
11543 char *tmp_buf;
11544 extern char *crypt(const char *, const char *);
11545# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
11546#endif
11547 VALUE result;
11548 const char *s, *saltp, *res;
11549#ifdef BROKEN_CRYPT
11550 char salt_8bit_clean[3];
11551#endif
11552
11553 StringValue(salt);
11554 mustnot_wchar(str);
11555 mustnot_wchar(salt);
11556 s = StringValueCStr(str);
11557 saltp = RSTRING_PTR(salt);
11558 if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
11559 rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
11560 }
11561
11562#ifdef BROKEN_CRYPT
11563 if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
11564 salt_8bit_clean[0] = saltp[0] & 0x7f;
11565 salt_8bit_clean[1] = saltp[1] & 0x7f;
11566 salt_8bit_clean[2] = '\0';
11567 saltp = salt_8bit_clean;
11568 }
11569#endif
11570#ifdef HAVE_CRYPT_R
11571 data = ALLOCV(databuf, sizeof(struct crypt_data));
11572# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
11573 data->initialized = 0;
11574# endif
11575 res = crypt_r(s, saltp, data);
11576#else
11577 rb_nativethread_lock_lock(&crypt_mutex.lock);
11578 res = crypt(s, saltp);
11579#endif
11580 if (!res) {
11581 int err = errno;
11582 CRYPT_END();
11583 rb_syserr_fail(err, "crypt");
11584 }
11585#ifdef HAVE_CRYPT_R
11586 result = rb_str_new_cstr(res);
11587 CRYPT_END();
11588#else
11589 // We need to copy this buffer because it's static and we need to unlock the mutex
11590 // before allocating a new object (the string to be returned). If we allocate while
11591 // holding the lock, we could run GC which fires the VM barrier and causes a deadlock
11592 // if other ractors are waiting on this lock.
11593 size_t res_size = strlen(res);
11594 tmp_buf = ALLOCA_N(char, res_size); // should be small enough to alloca
11595 memcpy(tmp_buf, res, res_size);
11596 CRYPT_END();
11597 result = rb_str_new(tmp_buf, res_size);
11598#endif
11599 return result;
11600}
11601
11602
11603/*
11604 * call-seq:
11605 * ord -> integer
11606 *
11607 * :include: doc/string/ord.rdoc
11608 *
11609 */
11610
11611static VALUE
11612rb_str_ord(VALUE s)
11613{
11614 unsigned int c;
11615
11616 c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
11617 return UINT2NUM(c);
11618}
11619/*
11620 * call-seq:
11621 * sum(n = 16) -> integer
11622 *
11623 * :include: doc/string/sum.rdoc
11624 *
11625 */
11626
11627static VALUE
11628rb_str_sum(int argc, VALUE *argv, VALUE str)
11629{
11630 int bits = 16;
11631 char *ptr, *p, *pend;
11632 long len;
11633 VALUE sum = INT2FIX(0);
11634 unsigned long sum0 = 0;
11635
11636 if (rb_check_arity(argc, 0, 1) && (bits = NUM2INT(argv[0])) < 0) {
11637 bits = 0;
11638 }
11639 ptr = p = RSTRING_PTR(str);
11640 len = RSTRING_LEN(str);
11641 pend = p + len;
11642
11643 while (p < pend) {
11644 if (FIXNUM_MAX - UCHAR_MAX < sum0) {
11645 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
11646 str_mod_check(str, ptr, len);
11647 sum0 = 0;
11648 }
11649 sum0 += (unsigned char)*p;
11650 p++;
11651 }
11652
11653 if (bits == 0) {
11654 if (sum0) {
11655 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
11656 }
11657 }
11658 else {
11659 if (sum == INT2FIX(0)) {
11660 if (bits < (int)sizeof(long)*CHAR_BIT) {
11661 sum0 &= (((unsigned long)1)<<bits)-1;
11662 }
11663 sum = LONG2FIX(sum0);
11664 }
11665 else {
11666 VALUE mod;
11667
11668 if (sum0) {
11669 sum = rb_funcall(sum, '+', 1, LONG2FIX(sum0));
11670 }
11671
11672 mod = rb_funcall(INT2FIX(1), idLTLT, 1, INT2FIX(bits));
11673 mod = rb_funcall(mod, '-', 1, INT2FIX(1));
11674 sum = rb_funcall(sum, '&', 1, mod);
11675 }
11676 }
11677 return sum;
11678}
11679
11680static VALUE
11681rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
11682{
11683 rb_encoding *enc;
11684 VALUE w;
11685 long width, len, flen = 1, fclen = 1;
11686 VALUE res;
11687 char *p;
11688 const char *f = " ";
11689 long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
11690 VALUE pad;
11691 int singlebyte = 1, cr;
11692 int termlen;
11693
11694 rb_scan_args(argc, argv, "11", &w, &pad);
11695 enc = STR_ENC_GET(str);
11696 width = NUM2LONG(w);
11697 if (argc == 2) {
11698 StringValue(pad);
11699 enc = rb_enc_check(str, pad);
11700 f = RSTRING_PTR(pad);
11701 flen = RSTRING_LEN(pad);
11702 fclen = str_strlen(pad, enc); /* rb_enc_check */
11703 singlebyte = single_byte_optimizable(pad);
11704 if (flen == 0 || fclen == 0) {
11705 rb_raise(rb_eArgError, "zero width padding");
11706 }
11707 }
11708 termlen = rb_enc_mbminlen(enc);
11709 len = str_strlen(str, enc); /* rb_enc_check */
11710 if (width < 0 || len >= width) return str_duplicate(rb_cString, str);
11711 n = width - len;
11712 llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
11713 rlen = n - llen;
11714 cr = ENC_CODERANGE(str);
11715 if (flen > 1) {
11716 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
11717 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
11718 }
11719 size = RSTRING_LEN(str);
11720 if ((len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
11721 (len *= flen) >= LONG_MAX - llen2 - rlen2 ||
11722 (len += llen2 + rlen2) >= LONG_MAX - size) {
11723 rb_raise(rb_eArgError, "argument too big");
11724 }
11725 len += size;
11726 res = str_enc_new(rb_cString, 0, len, enc);
11727 p = RSTRING_PTR(res);
11728 if (flen <= 1) {
11729 memset(p, *f, llen);
11730 p += llen;
11731 }
11732 else {
11733 while (llen >= fclen) {
11734 memcpy(p,f,flen);
11735 p += flen;
11736 llen -= fclen;
11737 }
11738 if (llen > 0) {
11739 memcpy(p, f, llen2);
11740 p += llen2;
11741 }
11742 }
11743 memcpy(p, RSTRING_PTR(str), size);
11744 p += size;
11745 if (flen <= 1) {
11746 memset(p, *f, rlen);
11747 p += rlen;
11748 }
11749 else {
11750 while (rlen >= fclen) {
11751 memcpy(p,f,flen);
11752 p += flen;
11753 rlen -= fclen;
11754 }
11755 if (rlen > 0) {
11756 memcpy(p, f, rlen2);
11757 p += rlen2;
11758 }
11759 }
11760 TERM_FILL(p, termlen);
11761 STR_SET_LEN(res, p-RSTRING_PTR(res));
11762
11763 if (argc == 2)
11764 cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
11765 if (cr != ENC_CODERANGE_BROKEN)
11766 ENC_CODERANGE_SET(res, cr);
11767
11768 RB_GC_GUARD(pad);
11769 return res;
11770}
11771
11772
11773/*
11774 * call-seq:
11775 * ljust(width, pad_string = ' ') -> new_string
11776 *
11777 * :include: doc/string/ljust.rdoc
11778 *
11779 */
11780
11781static VALUE
11782rb_str_ljust(int argc, VALUE *argv, VALUE str)
11783{
11784 return rb_str_justify(argc, argv, str, 'l');
11785}
11786
11787/*
11788 * call-seq:
11789 * rjust(width, pad_string = ' ') -> new_string
11790 *
11791 * :include: doc/string/rjust.rdoc
11792 *
11793 */
11794
11795static VALUE
11796rb_str_rjust(int argc, VALUE *argv, VALUE str)
11797{
11798 return rb_str_justify(argc, argv, str, 'r');
11799}
11800
11801
11802/*
11803 * call-seq:
11804 * center(size, pad_string = ' ') -> new_string
11805 *
11806 * :include: doc/string/center.rdoc
11807 *
11808 */
11809
11810static VALUE
11811rb_str_center(int argc, VALUE *argv, VALUE str)
11812{
11813 return rb_str_justify(argc, argv, str, 'c');
11814}
11815
11816/*
11817 * call-seq:
11818 * partition(pattern) -> [pre_match, first_match, post_match]
11819 *
11820 * :include: doc/string/partition.rdoc
11821 *
11822 */
11823
11824static VALUE
11825rb_str_partition(VALUE str, VALUE sep)
11826{
11827 long pos;
11828
11829 sep = get_pat_quoted(sep, 0);
11830 if (RB_TYPE_P(sep, T_REGEXP)) {
11831 if (rb_reg_search(sep, str, 0, 0) < 0) {
11832 goto failed;
11833 }
11834 VALUE match = rb_backref_get();
11835
11836 pos = RMATCH_BEG(match, 0);
11837 sep = rb_str_subseq(str, pos, RMATCH_END(match, 0) - pos);
11838 }
11839 else {
11840 pos = rb_str_index(str, sep, 0);
11841 if (pos < 0) goto failed;
11842 }
11843 return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
11844 sep,
11845 rb_str_subseq(str, pos+RSTRING_LEN(sep),
11846 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11847
11848 failed:
11849 return rb_ary_new3(3, str_duplicate(rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
11850}
11851
11852/*
11853 * call-seq:
11854 * rpartition(pattern) -> [pre_match, last_match, post_match]
11855 *
11856 * :include: doc/string/rpartition.rdoc
11857 *
11858 */
11859
11860static VALUE
11861rb_str_rpartition(VALUE str, VALUE sep)
11862{
11863 long pos = RSTRING_LEN(str);
11864
11865 sep = get_pat_quoted(sep, 0);
11866 if (RB_TYPE_P(sep, T_REGEXP)) {
11867 if (rb_reg_search(sep, str, pos, 1) < 0) {
11868 goto failed;
11869 }
11870 VALUE match = rb_backref_get();
11871
11872 pos = RMATCH_BEG(match, 0);
11873 sep = rb_str_subseq(str, pos, RMATCH_END(match, 0) - pos);
11874 }
11875 else {
11876 pos = rb_str_sublen(str, pos);
11877 pos = rb_str_rindex(str, sep, pos);
11878 if (pos < 0) {
11879 goto failed;
11880 }
11881 }
11882
11883 return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
11884 sep,
11885 rb_str_subseq(str, pos+RSTRING_LEN(sep),
11886 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11887 failed:
11888 return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(rb_cString, str));
11889}
11890
11891/*
11892 * call-seq:
11893 * start_with?(*patterns) -> true or false
11894 *
11895 * :include: doc/string/start_with_p.rdoc
11896 *
11897 */
11898
11899static VALUE
11900rb_str_start_with(int argc, VALUE *argv, VALUE str)
11901{
11902 int i;
11903
11904 for (i=0; i<argc; i++) {
11905 VALUE tmp = argv[i];
11906 if (RB_TYPE_P(tmp, T_REGEXP)) {
11907 if (rb_reg_start_with_p(tmp, str))
11908 return Qtrue;
11909 }
11910 else {
11911 const char *p, *s, *e;
11912 long slen, tlen;
11913 rb_encoding *enc;
11914
11915 StringValue(tmp);
11916 enc = rb_enc_check(str, tmp);
11917 if ((tlen = RSTRING_LEN(tmp)) == 0) return Qtrue;
11918 if ((slen = RSTRING_LEN(str)) < tlen) continue;
11919 p = RSTRING_PTR(str);
11920 e = p + slen;
11921 s = p + tlen;
11922 if (!at_char_right_boundary(p, s, e, enc))
11923 continue;
11924 if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
11925 return Qtrue;
11926 }
11927 }
11928 return Qfalse;
11929}
11930
11931/*
11932 * call-seq:
11933 * end_with?(*strings) -> true or false
11934 *
11935 * :include: doc/string/end_with_p.rdoc
11936 *
11937 */
11938
11939static VALUE
11940rb_str_end_with(int argc, VALUE *argv, VALUE str)
11941{
11942 int i;
11943
11944 for (i=0; i<argc; i++) {
11945 VALUE tmp = argv[i];
11946 const char *p, *s, *e;
11947 long slen, tlen;
11948 rb_encoding *enc;
11949
11950 StringValue(tmp);
11951 enc = rb_enc_check(str, tmp);
11952 if ((tlen = RSTRING_LEN(tmp)) == 0) return Qtrue;
11953 if ((slen = RSTRING_LEN(str)) < tlen) continue;
11954 p = RSTRING_PTR(str);
11955 e = p + slen;
11956 s = e - tlen;
11957 if (!at_char_boundary(p, s, e, enc))
11958 continue;
11959 if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
11960 return Qtrue;
11961 }
11962 return Qfalse;
11963}
11964
11974static long
11975deleted_prefix_length(VALUE str, VALUE prefix)
11976{
11977 const char *strptr, *prefixptr;
11978 long olen, prefixlen;
11979 rb_encoding *enc = rb_enc_get(str);
11980
11981 StringValue(prefix);
11982
11983 if (!is_broken_string(prefix) ||
11984 !rb_enc_asciicompat(enc) ||
11985 !rb_enc_asciicompat(rb_enc_get(prefix))) {
11986 enc = rb_enc_check(str, prefix);
11987 }
11988
11989 /* return 0 if not start with prefix */
11990 prefixlen = RSTRING_LEN(prefix);
11991 if (prefixlen <= 0) return 0;
11992 olen = RSTRING_LEN(str);
11993 if (olen < prefixlen) return 0;
11994 strptr = RSTRING_PTR(str);
11995 prefixptr = RSTRING_PTR(prefix);
11996 if (memcmp(strptr, prefixptr, prefixlen) != 0) return 0;
11997 if (is_broken_string(prefix)) {
11998 if (!is_broken_string(str)) {
11999 /* prefix in a valid string cannot be broken */
12000 return 0;
12001 }
12002 const char *strend = strptr + olen;
12003 const char *after_prefix = strptr + prefixlen;
12004 if (!at_char_right_boundary(strptr, after_prefix, strend, enc)) {
12005 /* prefix does not end at char-boundary */
12006 return 0;
12007 }
12008 }
12009 /* prefix part in `str` also should be valid. */
12010
12011 return prefixlen;
12012}
12013
12014/*
12015 * call-seq:
12016 * delete_prefix!(prefix) -> self or nil
12017 *
12018 * Like String#delete_prefix, except that +self+ is modified in place;
12019 * returns +self+ if the prefix is removed, +nil+ otherwise.
12020 *
12021 * Related: see {Modifying}[rdoc-ref:String@Modifying].
12022 */
12023
12024static VALUE
12025rb_str_delete_prefix_bang(VALUE str, VALUE prefix)
12026{
12027 long prefixlen;
12028 str_modify_keep_cr(str);
12029
12030 prefixlen = deleted_prefix_length(str, prefix);
12031 if (prefixlen <= 0) return Qnil;
12032
12033 return rb_str_drop_bytes(str, prefixlen);
12034}
12035
12036/*
12037 * call-seq:
12038 * delete_prefix(prefix) -> new_string
12039 *
12040 * :include: doc/string/delete_prefix.rdoc
12041 *
12042 */
12043
12044static VALUE
12045rb_str_delete_prefix(VALUE str, VALUE prefix)
12046{
12047 long prefixlen;
12048
12049 prefixlen = deleted_prefix_length(str, prefix);
12050 if (prefixlen <= 0) return str_duplicate(rb_cString, str);
12051
12052 return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
12053}
12054
12064static long
12065deleted_suffix_length(VALUE str, VALUE suffix)
12066{
12067 const char *strptr, *suffixptr;
12068 long olen, suffixlen;
12069 rb_encoding *enc;
12070
12071 StringValue(suffix);
12072 if (is_broken_string(suffix)) return 0;
12073 enc = rb_enc_check(str, suffix);
12074
12075 /* return 0 if not start with suffix */
12076 suffixlen = RSTRING_LEN(suffix);
12077 if (suffixlen <= 0) return 0;
12078 olen = RSTRING_LEN(str);
12079 if (olen < suffixlen) return 0;
12080 strptr = RSTRING_PTR(str);
12081 suffixptr = RSTRING_PTR(suffix);
12082 const char *strend = strptr + olen;
12083 const char *before_suffix = strend - suffixlen;
12084 if (memcmp(before_suffix, suffixptr, suffixlen) != 0) return 0;
12085 if (!at_char_boundary(strptr, before_suffix, strend, enc)) return 0;
12086
12087 return suffixlen;
12088}
12089
12090/*
12091 * call-seq:
12092 * delete_suffix!(suffix) -> self or nil
12093 *
12094 * Like String#delete_suffix, except that +self+ is modified in place;
12095 * returns +self+ if the suffix is removed, +nil+ otherwise.
12096 *
12097 * Related: see {Modifying}[rdoc-ref:String@Modifying].
12098 */
12099
12100static VALUE
12101rb_str_delete_suffix_bang(VALUE str, VALUE suffix)
12102{
12103 long olen, suffixlen, len;
12104 str_modifiable(str);
12105
12106 suffixlen = deleted_suffix_length(str, suffix);
12107 if (suffixlen <= 0) return Qnil;
12108
12109 olen = RSTRING_LEN(str);
12110 str_modify_keep_cr(str);
12111 len = olen - suffixlen;
12112 STR_SET_LEN(str, len);
12113 TERM_FILL(&RSTRING_PTR(str)[len], TERM_LEN(str));
12114 if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
12116 }
12117 return str;
12118}
12119
12120/*
12121 * call-seq:
12122 * delete_suffix(suffix) -> new_string
12123 *
12124 * :include: doc/string/delete_suffix.rdoc
12125 *
12126 */
12127
12128static VALUE
12129rb_str_delete_suffix(VALUE str, VALUE suffix)
12130{
12131 long suffixlen;
12132
12133 suffixlen = deleted_suffix_length(str, suffix);
12134 if (suffixlen <= 0) return str_duplicate(rb_cString, str);
12135
12136 return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
12137}
12138
12139void
12140rb_str_setter(VALUE val, ID id, VALUE *var)
12141{
12142 if (!NIL_P(val) && !RB_TYPE_P(val, T_STRING)) {
12143 rb_raise(rb_eTypeError, "value of %"PRIsVALUE" must be String", rb_id2str(id));
12144 }
12145 *var = val;
12146}
12147
12148static void
12149nil_setter_warning(ID id)
12150{
12151 rb_warn_deprecated("non-nil '%"PRIsVALUE"'", NULL, rb_id2str(id));
12152}
12153
12154void
12155rb_deprecated_str_setter(VALUE val, ID id, VALUE *var)
12156{
12157 rb_str_setter(val, id, var);
12158 if (!NIL_P(*var)) {
12159 nil_setter_warning(id);
12160 }
12161}
12162
12163static void
12164rb_fs_setter(VALUE val, ID id, VALUE *var)
12165{
12166 val = rb_fs_check(val);
12167 if (!val) {
12168 rb_raise(rb_eTypeError,
12169 "value of %"PRIsVALUE" must be String or Regexp",
12170 rb_id2str(id));
12171 }
12172 if (!NIL_P(val)) {
12173 nil_setter_warning(id);
12174 }
12175 *var = val;
12176}
12177
12178
12179/*
12180 * call-seq:
12181 * force_encoding(encoding) -> self
12182 *
12183 * :include: doc/string/force_encoding.rdoc
12184 *
12185 */
12186
12187static VALUE
12188rb_str_force_encoding(VALUE str, VALUE enc)
12189{
12190 str_modifiable(str);
12191
12192 rb_encoding *encoding = rb_to_encoding(enc);
12193 int idx = rb_enc_to_index(encoding);
12194
12195 // If the encoding is unchanged, we do nothing.
12196 if (ENCODING_GET(str) == idx) {
12197 return str;
12198 }
12199
12200 rb_enc_associate_index(str, idx);
12201
12202 // If the coderange was 7bit and the new encoding is ASCII-compatible
12203 // we can keep the coderange.
12204 if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT && encoding && rb_enc_asciicompat(encoding)) {
12205 return str;
12206 }
12207
12209 return str;
12210}
12211
12212/*
12213 * call-seq:
12214 * b -> new_string
12215 *
12216 * :include: doc/string/b.rdoc
12217 *
12218 */
12219
12220static VALUE
12221rb_str_b(VALUE str)
12222{
12223 VALUE str2;
12224 if (STR_EMBED_P(str)) {
12225 str2 = str_alloc_embed(rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
12226 }
12227 else {
12228 str2 = str_alloc_heap(rb_cString);
12229 }
12230 str_replace_shared_without_enc(str2, str);
12231
12232 if (rb_enc_asciicompat(STR_ENC_GET(str))) {
12233 // BINARY strings can never be broken; they're either 7-bit ASCII or VALID.
12234 // If we know the receiver's code range then we know the result's code range.
12235 int cr = ENC_CODERANGE(str);
12236 switch (cr) {
12237 case ENC_CODERANGE_7BIT:
12239 break;
12243 break;
12244 default:
12245 ENC_CODERANGE_CLEAR(str2);
12246 break;
12247 }
12248 }
12249
12250 return str2;
12251}
12252
12253/* Defined as a leaf builtin in string.rb, so this must never raise or call into Ruby. */
12254static VALUE
12255rb_str_valid_encoding_p(VALUE str)
12256{
12257 int cr = rb_enc_str_coderange(str);
12258
12259 return RBOOL(cr != ENC_CODERANGE_BROKEN);
12260}
12261
12262/* Defined as a leaf builtin in string.rb, so this must never raise or call into Ruby. */
12263static VALUE
12264rb_str_is_ascii_only_p(VALUE str)
12265{
12266 int cr = rb_enc_str_coderange(str);
12267
12268 return RBOOL(cr == ENC_CODERANGE_7BIT);
12269}
12270
12271VALUE
12273{
12274 static const char ellipsis[] = "...";
12275 const long ellipsislen = sizeof(ellipsis) - 1;
12276 rb_encoding *const enc = rb_enc_get(str);
12277 const long blen = RSTRING_LEN(str);
12278 const char *const p = RSTRING_PTR(str), *e = p + blen;
12279 VALUE estr, ret = 0;
12280
12281 if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
12282 if (len * rb_enc_mbminlen(enc) >= blen ||
12283 (e = rb_enc_nth(p, e, len, enc)) - p == blen) {
12284 ret = str;
12285 }
12286 else if (len <= ellipsislen ||
12287 !(e = rb_enc_step_back(p, e, e, len = ellipsislen, enc))) {
12288 if (rb_enc_asciicompat(enc)) {
12289 ret = rb_str_new(ellipsis, len);
12290 rb_enc_associate(ret, enc);
12291 }
12292 else {
12293 estr = rb_usascii_str_new(ellipsis, len);
12294 ret = rb_str_encode(estr, rb_enc_from_encoding(enc), 0, Qnil);
12295 }
12296 }
12297 else if (ret = rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
12298 rb_str_cat(ret, ellipsis, ellipsislen);
12299 }
12300 else {
12301 estr = rb_str_encode(rb_usascii_str_new(ellipsis, ellipsislen),
12302 rb_enc_from_encoding(enc), 0, Qnil);
12303 rb_str_append(ret, estr);
12304 }
12305 return ret;
12306}
12307
12308static VALUE
12309str_compat_and_valid(VALUE str, rb_encoding *enc)
12310{
12311 int cr;
12312 str = StringValue(str);
12313 cr = rb_enc_str_coderange(str);
12314 if (cr == ENC_CODERANGE_BROKEN) {
12315 rb_raise(rb_eArgError, "replacement must be valid byte sequence '%+"PRIsVALUE"'", str);
12316 }
12317 else {
12318 rb_encoding *e = STR_ENC_GET(str);
12319 if (cr == ENC_CODERANGE_7BIT ? rb_enc_mbminlen(enc) != 1 : enc != e) {
12320 rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
12321 rb_enc_inspect_name(enc), rb_enc_inspect_name(e));
12322 }
12323 }
12324 return str;
12325}
12326
12327static VALUE enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr);
12328
12329VALUE
12331{
12332 rb_encoding *enc = STR_ENC_GET(str);
12333 return enc_str_scrub(enc, str, repl, ENC_CODERANGE(str));
12334}
12335
12336VALUE
12337rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl)
12338{
12339 int cr = ENC_CODERANGE_UNKNOWN;
12340 if (enc == STR_ENC_GET(str)) {
12341 /* cached coderange makes sense only when enc equals the
12342 * actual encoding of str */
12343 cr = ENC_CODERANGE(str);
12344 }
12345 return enc_str_scrub(enc, str, repl, cr);
12346}
12347
12348static VALUE
12349enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
12350{
12351 int encidx;
12352 VALUE buf = Qnil;
12353 const char *rep, *p, *e, *p1, *sp;
12354 long replen = -1;
12355 long slen;
12356
12357 if (rb_block_given_p()) {
12358 if (!NIL_P(repl))
12359 rb_raise(rb_eArgError, "both of block and replacement given");
12360 replen = 0;
12361 }
12362
12363 if (ENC_CODERANGE_CLEAN_P(cr))
12364 return Qnil;
12365
12366 if (!NIL_P(repl)) {
12367 repl = str_compat_and_valid(repl, enc);
12368 }
12369
12370 if (rb_enc_dummy_p(enc)) {
12371 return Qnil;
12372 }
12373 encidx = rb_enc_to_index(enc);
12374
12375#define DEFAULT_REPLACE_CHAR(str) do { \
12376 RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
12377 rep = replace; replen = (int)sizeof(replace); \
12378 } while (0)
12379
12380 slen = RSTRING_LEN(str);
12381 p = RSTRING_PTR(str);
12382 e = RSTRING_END(str);
12383 p1 = p;
12384 sp = p;
12385
12386 if (rb_enc_asciicompat(enc)) {
12387 int rep7bit_p;
12388 if (!replen) {
12389 rep = NULL;
12390 rep7bit_p = FALSE;
12391 }
12392 else if (!NIL_P(repl)) {
12393 rep = RSTRING_PTR(repl);
12394 replen = RSTRING_LEN(repl);
12395 rep7bit_p = (ENC_CODERANGE(repl) == ENC_CODERANGE_7BIT);
12396 }
12397 else if (encidx == rb_utf8_encindex()) {
12398 DEFAULT_REPLACE_CHAR("\xEF\xBF\xBD");
12399 rep7bit_p = FALSE;
12400 }
12401 else {
12402 DEFAULT_REPLACE_CHAR("?");
12403 rep7bit_p = TRUE;
12404 }
12405 cr = ENC_CODERANGE_7BIT;
12406
12407 p = search_nonascii(p, e);
12408 if (!p) {
12409 p = e;
12410 }
12411 while (p < e) {
12412 int ret = rb_enc_precise_mbclen(p, e, enc);
12413 if (MBCLEN_NEEDMORE_P(ret)) {
12414 break;
12415 }
12416 else if (MBCLEN_CHARFOUND_P(ret)) {
12418 p += MBCLEN_CHARFOUND_LEN(ret);
12419 /* After a multibyte character, fast-skip the following ASCII run. */
12420 p = search_nonascii(p, e);
12421 if (!p) {
12422 p = e;
12423 break;
12424 }
12425 }
12426 else if (MBCLEN_INVALID_P(ret)) {
12427 /*
12428 * p1~p: valid ascii/multibyte chars
12429 * p ~e: invalid bytes + unknown bytes
12430 */
12431 long clen = rb_enc_mbmaxlen(enc);
12432 if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
12433 if (p > p1) {
12434 rb_str_buf_cat(buf, p1, p - p1);
12435 }
12436
12437 if (e - p < clen) clen = e - p;
12438 if (clen <= 2) {
12439 clen = 1;
12440 }
12441 else {
12442 const char *q = p;
12443 clen--;
12444 for (; clen > 1; clen--) {
12445 ret = rb_enc_precise_mbclen(q, q + clen, enc);
12446 if (MBCLEN_NEEDMORE_P(ret)) break;
12447 if (MBCLEN_INVALID_P(ret)) continue;
12449 }
12450 }
12451 if (rep) {
12452 rb_str_buf_cat(buf, rep, replen);
12453 if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
12454 }
12455 else {
12456 repl = rb_yield(rb_enc_str_new(p, clen, enc));
12457 str_mod_check(str, sp, slen);
12458 repl = str_compat_and_valid(repl, enc);
12459 rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
12462 }
12463 p += clen;
12464 p1 = p;
12465 p = search_nonascii(p, e);
12466 if (!p) {
12467 p = e;
12468 break;
12469 }
12470 }
12471 else {
12473 }
12474 }
12475 if (NIL_P(buf)) {
12476 if (p == e) {
12477 ENC_CODERANGE_SET(str, cr);
12478 return Qnil;
12479 }
12480 buf = rb_str_buf_new(RSTRING_LEN(str));
12481 }
12482 if (p1 < p) {
12483 rb_str_buf_cat(buf, p1, p - p1);
12484 }
12485 if (p < e) {
12486 if (rep) {
12487 rb_str_buf_cat(buf, rep, replen);
12488 if (!rep7bit_p) cr = ENC_CODERANGE_VALID;
12489 }
12490 else {
12491 repl = rb_yield(rb_enc_str_new(p, e-p, enc));
12492 str_mod_check(str, sp, slen);
12493 repl = str_compat_and_valid(repl, enc);
12494 rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
12497 }
12498 }
12499 }
12500 else {
12501 /* ASCII incompatible */
12502 long mbminlen = rb_enc_mbminlen(enc);
12503 if (!replen) {
12504 rep = NULL;
12505 }
12506 else if (!NIL_P(repl)) {
12507 rep = RSTRING_PTR(repl);
12508 replen = RSTRING_LEN(repl);
12509 }
12510 else if (encidx == ENCINDEX_UTF_16BE) {
12511 DEFAULT_REPLACE_CHAR("\xFF\xFD");
12512 }
12513 else if (encidx == ENCINDEX_UTF_16LE) {
12514 DEFAULT_REPLACE_CHAR("\xFD\xFF");
12515 }
12516 else if (encidx == ENCINDEX_UTF_32BE) {
12517 DEFAULT_REPLACE_CHAR("\x00\x00\xFF\xFD");
12518 }
12519 else if (encidx == ENCINDEX_UTF_32LE) {
12520 DEFAULT_REPLACE_CHAR("\xFD\xFF\x00\x00");
12521 }
12522 else {
12523 DEFAULT_REPLACE_CHAR("?");
12524 }
12525
12526 while (p < e) {
12527 int ret = rb_enc_precise_mbclen(p, e, enc);
12528 if (MBCLEN_NEEDMORE_P(ret)) {
12529 break;
12530 }
12531 else if (MBCLEN_CHARFOUND_P(ret)) {
12532 p += MBCLEN_CHARFOUND_LEN(ret);
12533 }
12534 else if (MBCLEN_INVALID_P(ret)) {
12535 const char *q = p;
12536 long clen = rb_enc_mbmaxlen(enc);
12537 if (NIL_P(buf)) buf = rb_str_buf_new(RSTRING_LEN(str));
12538 if (p > p1) rb_str_buf_cat(buf, p1, p - p1);
12539
12540 if (e - p < clen) clen = e - p;
12541 if (clen <= mbminlen * 2) {
12542 clen = mbminlen;
12543 }
12544 else {
12545 clen -= mbminlen;
12546 for (; clen > mbminlen; clen-=mbminlen) {
12547 ret = rb_enc_precise_mbclen(q, q + clen, enc);
12548 if (MBCLEN_NEEDMORE_P(ret)) break;
12549 if (MBCLEN_INVALID_P(ret)) continue;
12551 }
12552 }
12553 if (rep) {
12554 rb_str_buf_cat(buf, rep, replen);
12555 }
12556 else {
12557 repl = rb_yield(rb_enc_str_new(p, clen, enc));
12558 str_mod_check(str, sp, slen);
12559 repl = str_compat_and_valid(repl, enc);
12560 rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
12561 }
12562 p += clen;
12563 p1 = p;
12564 }
12565 else {
12567 }
12568 }
12569 if (NIL_P(buf)) {
12570 if (p == e) {
12572 return Qnil;
12573 }
12574 buf = rb_str_buf_new(RSTRING_LEN(str));
12575 }
12576 if (p1 < p) {
12577 rb_str_buf_cat(buf, p1, p - p1);
12578 }
12579 if (p < e) {
12580 if (rep) {
12581 rb_str_buf_cat(buf, rep, replen);
12582 }
12583 else {
12584 repl = rb_yield(rb_enc_str_new(p, e-p, enc));
12585 str_mod_check(str, sp, slen);
12586 repl = str_compat_and_valid(repl, enc);
12587 rb_str_buf_cat(buf, RSTRING_PTR(repl), RSTRING_LEN(repl));
12588 }
12589 }
12591 }
12592 ENCODING_CODERANGE_SET(buf, rb_enc_to_index(enc), cr);
12593 return buf;
12594}
12595
12596/*
12597 * call-seq:
12598 * scrub(replacement_string = default_replacement_string) -> new_string
12599 * scrub{|sequence| ... } -> new_string
12600 *
12601 * :include: doc/string/scrub.rdoc
12602 *
12603 */
12604static VALUE
12605str_scrub(int argc, VALUE *argv, VALUE str)
12606{
12607 VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
12608 VALUE new = rb_str_scrub(str, repl);
12609 return NIL_P(new) ? str_duplicate(rb_cString, str): new;
12610}
12611
12612/*
12613 * call-seq:
12614 * scrub!(replacement_string = default_replacement_string) -> self
12615 * scrub!{|sequence| ... } -> self
12616 *
12617 * Like String#scrub, except that:
12618 *
12619 * - Any replacements are made in +self+.
12620 * - Returns +self+.
12621 *
12622 * Related: see {Modifying}[rdoc-ref:String@Modifying].
12623 *
12624 */
12625static VALUE
12626str_scrub_bang(int argc, VALUE *argv, VALUE str)
12627{
12628 VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
12629 VALUE new = rb_str_scrub(str, repl);
12630 if (!NIL_P(new)) rb_str_replace(str, new);
12631 return str;
12632}
12633
12634static ID id_normalize;
12635static ID id_normalized_p;
12636static VALUE mUnicodeNormalize;
12637
12638static VALUE
12639unicode_normalize_common(int argc, VALUE *argv, VALUE str, ID id)
12640{
12641 static int UnicodeNormalizeRequired = 0;
12642 VALUE argv2[2];
12643
12644 if (!UnicodeNormalizeRequired) {
12645 rb_require("unicode_normalize/normalize.rb");
12646 UnicodeNormalizeRequired = 1;
12647 }
12648 argv2[0] = str;
12649 if (rb_check_arity(argc, 0, 1)) argv2[1] = argv[0];
12650 return rb_funcallv(mUnicodeNormalize, id, argc+1, argv2);
12651}
12652
12653/*
12654 * call-seq:
12655 * unicode_normalize(form = :nfc) -> string
12656 *
12657 * :include: doc/string/unicode_normalize.rdoc
12658 *
12659 */
12660static VALUE
12661rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
12662{
12663 return unicode_normalize_common(argc, argv, str, id_normalize);
12664}
12665
12666/*
12667 * call-seq:
12668 * unicode_normalize!(form = :nfc) -> self
12669 *
12670 * Like String#unicode_normalize, except that the normalization
12671 * is performed on +self+ (not on a copy of +self+).
12672 *
12673 * Related: see {Modifying}[rdoc-ref:String@Modifying].
12674 *
12675 */
12676static VALUE
12677rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
12678{
12679 return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
12680}
12681
12682/* call-seq:
12683 * unicode_normalized?(form = :nfc) -> true or false
12684 *
12685 * Returns whether +self+ is in the given +form+ of Unicode normalization;
12686 * see String#unicode_normalize.
12687 *
12688 * The +form+ must be one of +:nfc+, +:nfd+, +:nfkc+, or +:nfkd+.
12689 *
12690 * Examples:
12691 *
12692 * "a\u0300".unicode_normalized? # => false
12693 * "a\u0300".unicode_normalized?(:nfd) # => true
12694 * "\u00E0".unicode_normalized? # => true
12695 * "\u00E0".unicode_normalized?(:nfd) # => false
12696 *
12697 *
12698 * Raises an exception if +self+ is not in a Unicode encoding:
12699 *
12700 * s = "\xE0".force_encoding(Encoding::ISO_8859_1)
12701 * s.unicode_normalized? # Raises Encoding::CompatibilityError
12702 *
12703 * Related: see {Querying}[rdoc-ref:String@Querying].
12704 */
12705static VALUE
12706rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
12707{
12708 return unicode_normalize_common(argc, argv, str, id_normalized_p);
12709}
12710
12711/**********************************************************************
12712 * Document-class: Symbol
12713 *
12714 * A +Symbol+ object represents a named identifier inside the Ruby interpreter.
12715 *
12716 * You can create a +Symbol+ object explicitly with:
12717 *
12718 * - A {symbol literal}[rdoc-ref:syntax/literals.rdoc@Symbol+Literals].
12719 *
12720 * The same +Symbol+ object will be
12721 * created for a given name or string for the duration of a program's
12722 * execution, regardless of the context or meaning of that name. Thus
12723 * if <code>Fred</code> is a constant in one context, a method in
12724 * another, and a class in a third, the +Symbol+ <code>:Fred</code>
12725 * will be the same object in all three contexts.
12726 *
12727 * module One
12728 * class Fred
12729 * end
12730 * $f1 = :Fred
12731 * end
12732 * module Two
12733 * Fred = 1
12734 * $f2 = :Fred
12735 * end
12736 * def Fred()
12737 * end
12738 * $f3 = :Fred
12739 * $f1.object_id #=> 2514190
12740 * $f2.object_id #=> 2514190
12741 * $f3.object_id #=> 2514190
12742 *
12743 * Constant, method, and variable names are returned as symbols:
12744 *
12745 * module One
12746 * Two = 2
12747 * def three; 3 end
12748 * @four = 4
12749 * @@five = 5
12750 * $six = 6
12751 * end
12752 * seven = 7
12753 *
12754 * One.constants
12755 * # => [:Two]
12756 * One.instance_methods(true)
12757 * # => [:three]
12758 * One.instance_variables
12759 * # => [:@four]
12760 * One.class_variables
12761 * # => [:@@five]
12762 * global_variables.grep(/six/)
12763 * # => [:$six]
12764 * local_variables
12765 * # => [:seven]
12766 *
12767 * A +Symbol+ object differs from a String object in that
12768 * a +Symbol+ object represents an identifier, while a String object
12769 * represents text or data.
12770 *
12771 * == What's Here
12772 *
12773 * First, what's elsewhere. Class +Symbol+:
12774 *
12775 * - Inherits from {class Object}[rdoc-ref:Object@Whats+Here].
12776 * - Includes {module Comparable}[rdoc-ref:Comparable@Whats+Here].
12777 *
12778 * Here, class +Symbol+ provides methods that are useful for:
12779 *
12780 * - {Querying}[rdoc-ref:Symbol@Methods+for+Querying]
12781 * - {Comparing}[rdoc-ref:Symbol@Methods+for+Comparing]
12782 * - {Converting}[rdoc-ref:Symbol@Methods+for+Converting]
12783 *
12784 * === Methods for Querying
12785 *
12786 * - ::all_symbols: Returns an array of the symbols currently in Ruby's symbol table.
12787 * - #=~: Returns the index of the first substring in symbol that matches a
12788 * given Regexp or other object; returns +nil+ if no match is found.
12789 * - #[], #slice : Returns a substring of symbol
12790 * determined by a given index, start/length, or range, or string.
12791 * - #empty?: Returns +true+ if +self.length+ is zero; +false+ otherwise.
12792 * - #encoding: Returns the Encoding object that represents the encoding
12793 * of symbol.
12794 * - #end_with?: Returns +true+ if symbol ends with
12795 * any of the given strings.
12796 * - #match: Returns a MatchData object if symbol
12797 * matches a given Regexp; +nil+ otherwise.
12798 * - #match?: Returns +true+ if symbol
12799 * matches a given Regexp; +false+ otherwise.
12800 * - #length, #size: Returns the number of characters in symbol.
12801 * - #start_with?: Returns +true+ if symbol starts with
12802 * any of the given strings.
12803 *
12804 * === Methods for Comparing
12805 *
12806 * - #<=>: Returns -1, 0, or 1 as a given symbol is smaller than, equal to,
12807 * or larger than symbol.
12808 * - #==, #===: Returns +true+ if a given symbol has the same content and
12809 * encoding.
12810 * - #casecmp: Ignoring case, returns -1, 0, or 1 as a given
12811 * symbol is smaller than, equal to, or larger than symbol.
12812 * - #casecmp?: Returns +true+ if symbol is equal to a given symbol
12813 * after Unicode case folding; +false+ otherwise.
12814 *
12815 * === Methods for Converting
12816 *
12817 * - #capitalize: Returns symbol with the first character upcased
12818 * and all other characters downcased.
12819 * - #downcase: Returns symbol with all characters downcased.
12820 * - #inspect: Returns the string representation of +self+ as a symbol literal.
12821 * - #name: Returns the frozen string corresponding to symbol.
12822 * - #succ, #next: Returns the symbol that is the successor to symbol.
12823 * - #swapcase: Returns symbol with all upcase characters downcased
12824 * and all downcase characters upcased.
12825 * - #to_proc: Returns a Proc object which responds to the method named by symbol.
12826 * - #to_s, #id2name: Returns the string corresponding to +self+.
12827 * - #to_sym, #intern: Returns +self+.
12828 * - #upcase: Returns symbol with all characters upcased.
12829 *
12830 */
12831
12832
12833/*
12834 * call-seq:
12835 * self == other -> true or false
12836 *
12837 * Returns whether +other+ is the same object as +self+.
12838 */
12839
12840#define sym_equal rb_obj_equal
12841
12842static int
12843sym_printable(const char *s, const char *send, rb_encoding *enc)
12844{
12845 while (s < send) {
12846 int n;
12847 int c = rb_enc_precise_mbclen(s, send, enc);
12848
12849 if (!MBCLEN_CHARFOUND_P(c)) return FALSE;
12850 n = MBCLEN_CHARFOUND_LEN(c);
12851 c = rb_enc_mbc_to_codepoint(s, send, enc);
12852 if (!rb_enc_isprint(c, enc)) return FALSE;
12853 s += n;
12854 }
12855 return TRUE;
12856}
12857
12858int
12859rb_str_symname_p(VALUE sym)
12860{
12861 rb_encoding *enc;
12862 const char *ptr;
12863 long len;
12864 rb_encoding *resenc = rb_default_internal_encoding();
12865
12866 if (resenc == NULL) resenc = rb_default_external_encoding();
12867 enc = STR_ENC_GET(sym);
12868 ptr = RSTRING_PTR(sym);
12869 len = RSTRING_LEN(sym);
12870 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) || len != (long)strlen(ptr) ||
12871 !rb_enc_symname2_p(ptr, len, enc) || !sym_printable(ptr, ptr + len, enc)) {
12872 return FALSE;
12873 }
12874 return TRUE;
12875}
12876
12877VALUE
12878rb_str_quote_unprintable(VALUE str)
12879{
12880 rb_encoding *enc;
12881 const char *ptr;
12882 long len;
12883 rb_encoding *resenc;
12884
12885 Check_Type(str, T_STRING);
12886 resenc = rb_default_internal_encoding();
12887 if (resenc == NULL) resenc = rb_default_external_encoding();
12888 enc = STR_ENC_GET(str);
12889 ptr = RSTRING_PTR(str);
12890 len = RSTRING_LEN(str);
12891 if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
12892 !sym_printable(ptr, ptr + len, enc)) {
12893 return rb_str_escape(str);
12894 }
12895 return str;
12896}
12897
12898VALUE
12899rb_id_quote_unprintable(ID id)
12900{
12901 VALUE str = rb_id2str(id);
12902 if (!rb_str_symname_p(str)) {
12903 return rb_str_escape(str);
12904 }
12905 return str;
12906}
12907
12908/*
12909 * call-seq:
12910 * inspect -> string
12911 *
12912 * Returns a string representation of +self+ (including the leading colon):
12913 *
12914 * :foo.inspect # => ":foo"
12915 *
12916 * Related: Symbol#to_s, Symbol#name.
12917 *
12918 */
12919
12920static VALUE
12921sym_inspect(VALUE sym)
12922{
12923 VALUE str = rb_sym2str(sym);
12924 const char *ptr;
12925 long len;
12926 char *dest;
12927
12928 if (!rb_str_symname_p(str)) {
12929 str = rb_str_inspect(str);
12930 len = RSTRING_LEN(str);
12931 rb_str_resize(str, len + 1);
12932 dest = RSTRING_PTR(str);
12933 memmove(dest + 1, dest, len);
12934 }
12935 else {
12936 rb_encoding *enc = STR_ENC_GET(str);
12937 VALUE orig_str = str;
12938
12939 len = RSTRING_LEN(orig_str);
12940 str = rb_enc_str_new(0, len + 1, enc);
12941
12942 // Get data pointer after allocation
12943 ptr = RSTRING_PTR(orig_str);
12944 dest = RSTRING_PTR(str);
12945 memcpy(dest + 1, ptr, len);
12946
12947 RB_GC_GUARD(orig_str);
12948 }
12949 dest[0] = ':';
12950
12952
12953 return str;
12954}
12955
12956VALUE
12958{
12959 return rb_sym2str(sym);
12960}
12961
12962VALUE
12963rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc)
12964{
12965 VALUE obj;
12966
12967 if (argc < 1) {
12968 rb_raise(rb_eArgError, "no receiver given");
12969 }
12970 obj = argv[0];
12971 return rb_funcall_with_block_kw(obj, mid, argc - 1, argv + 1, passed_proc, kw_splat);
12972}
12973
12974/*
12975 * call-seq:
12976 * succ
12977 *
12978 * Equivalent to <tt>self.to_s.succ.to_sym</tt>:
12979 *
12980 * :foo.succ # => :fop
12981 *
12982 * Related: String#succ.
12983 */
12984
12985static VALUE
12986sym_succ(VALUE sym)
12987{
12988 return rb_str_intern(rb_str_succ(rb_sym2str(sym)));
12989}
12990
12991/*
12992 * call-seq:
12993 * self <=> other -> -1, 0, 1, or nil
12994 *
12995 * Compares +self+ and +other+, using String#<=>.
12996 *
12997 * Returns:
12998 *
12999 * - <tt>self.to_s <=> other.to_s</tt>, if +other+ is a symbol.
13000 * - +nil+, otherwise.
13001 *
13002 * Examples:
13003 *
13004 * :bar <=> :foo # => -1
13005 * :foo <=> :foo # => 0
13006 * :foo <=> :bar # => 1
13007 * :foo <=> 'bar' # => nil
13008 *
13009 * \Class \Symbol includes module Comparable,
13010 * each of whose methods uses Symbol#<=> for comparison.
13011 *
13012 * Related: String#<=>.
13013 */
13014
13015static VALUE
13016sym_cmp(VALUE sym, VALUE other)
13017{
13018 if (!SYMBOL_P(other)) {
13019 return Qnil;
13020 }
13021 return rb_str_cmp_m(rb_sym2str(sym), rb_sym2str(other));
13022}
13023
13024/*
13025 * call-seq:
13026 * casecmp(object) -> -1, 0, 1, or nil
13027 *
13028 * :include: doc/symbol/casecmp.rdoc
13029 *
13030 */
13031
13032static VALUE
13033sym_casecmp(VALUE sym, VALUE other)
13034{
13035 if (!SYMBOL_P(other)) {
13036 return Qnil;
13037 }
13038 return str_casecmp(rb_sym2str(sym), rb_sym2str(other));
13039}
13040
13041/*
13042 * call-seq:
13043 * casecmp?(object) -> true, false, or nil
13044 *
13045 * :include: doc/symbol/casecmp_p.rdoc
13046 *
13047 */
13048
13049static VALUE
13050sym_casecmp_p(VALUE sym, VALUE other)
13051{
13052 if (!SYMBOL_P(other)) {
13053 return Qnil;
13054 }
13055 return str_casecmp_p(rb_sym2str(sym), rb_sym2str(other));
13056}
13057
13058/*
13059 * call-seq:
13060 * self =~ other -> integer or nil
13061 *
13062 * Equivalent to <tt>self.to_s =~ other</tt>,
13063 * including possible updates to global variables;
13064 * see String#=~.
13065 *
13066 */
13067
13068static VALUE
13069sym_match(VALUE sym, VALUE other)
13070{
13071 return rb_str_match(rb_sym2str(sym), other);
13072}
13073
13074/*
13075 * call-seq:
13076 * match(pattern, offset = 0) -> matchdata or nil
13077 * match(pattern, offset = 0) {|matchdata| } -> object
13078 *
13079 * Equivalent to <tt>self.to_s.match</tt>,
13080 * including possible updates to global variables;
13081 * see String#match.
13082 *
13083 */
13084
13085static VALUE
13086sym_match_m(int argc, VALUE *argv, VALUE sym)
13087{
13088 return rb_str_match_m(argc, argv, rb_sym2str(sym));
13089}
13090
13091/*
13092 * call-seq:
13093 * match?(pattern, offset) -> true or false
13094 *
13095 * Equivalent to <tt>sym.to_s.match?</tt>;
13096 * see String#match.
13097 *
13098 */
13099
13100static VALUE
13101sym_match_m_p(int argc, VALUE *argv, VALUE sym)
13102{
13103 return rb_str_match_m_p(argc, argv, sym);
13104}
13105
13106/*
13107 * call-seq:
13108 * self[offset] -> string or nil
13109 * self[offset, size] -> string or nil
13110 * self[range] -> string or nil
13111 * self[regexp, capture = 0] -> string or nil
13112 * self[substring] -> string or nil
13113 *
13114 * Equivalent to <tt>symbol.to_s[]</tt>; see String#[].
13115 *
13116 */
13117
13118static VALUE
13119sym_aref(int argc, VALUE *argv, VALUE sym)
13120{
13121 return rb_str_aref_m(argc, argv, rb_sym2str(sym));
13122}
13123
13124/*
13125 * call-seq:
13126 * length -> integer
13127 *
13128 * Equivalent to <tt>self.to_s.length</tt>; see String#length.
13129 */
13130
13131static VALUE
13132sym_length(VALUE sym)
13133{
13134 return rb_str_length(rb_sym2str(sym));
13135}
13136
13137/*
13138 * call-seq:
13139 * upcase(mapping) -> symbol
13140 *
13141 * Equivalent to <tt>sym.to_s.upcase.to_sym</tt>.
13142 *
13143 * See String#upcase.
13144 *
13145 */
13146
13147static VALUE
13148sym_upcase(int argc, VALUE *argv, VALUE sym)
13149{
13150 return rb_str_intern(rb_str_upcase(argc, argv, rb_sym2str(sym)));
13151}
13152
13153/*
13154 * call-seq:
13155 * downcase(mapping) -> symbol
13156 *
13157 * Equivalent to <tt>sym.to_s.downcase.to_sym</tt>.
13158 *
13159 * See String#downcase.
13160 *
13161 * Related: Symbol#upcase.
13162 *
13163 */
13164
13165static VALUE
13166sym_downcase(int argc, VALUE *argv, VALUE sym)
13167{
13168 return rb_str_intern(rb_str_downcase(argc, argv, rb_sym2str(sym)));
13169}
13170
13171/*
13172 * call-seq:
13173 * capitalize(mapping) -> symbol
13174 *
13175 * Equivalent to <tt>sym.to_s.capitalize.to_sym</tt>.
13176 *
13177 * See String#capitalize.
13178 *
13179 */
13180
13181static VALUE
13182sym_capitalize(int argc, VALUE *argv, VALUE sym)
13183{
13184 return rb_str_intern(rb_str_capitalize(argc, argv, rb_sym2str(sym)));
13185}
13186
13187/*
13188 * call-seq:
13189 * swapcase(mapping) -> symbol
13190 *
13191 * Equivalent to <tt>sym.to_s.swapcase.to_sym</tt>.
13192 *
13193 * See String#swapcase.
13194 *
13195 */
13196
13197static VALUE
13198sym_swapcase(int argc, VALUE *argv, VALUE sym)
13199{
13200 return rb_str_intern(rb_str_swapcase(argc, argv, rb_sym2str(sym)));
13201}
13202
13203/*
13204 * call-seq:
13205 * start_with?(*string_or_regexp) -> true or false
13206 *
13207 * Equivalent to <tt>self.to_s.start_with?</tt>; see String#start_with?.
13208 *
13209 */
13210
13211static VALUE
13212sym_start_with(int argc, VALUE *argv, VALUE sym)
13213{
13214 return rb_str_start_with(argc, argv, rb_sym2str(sym));
13215}
13216
13217/*
13218 * call-seq:
13219 * end_with?(*strings) -> true or false
13220 *
13221 *
13222 * Equivalent to <tt>self.to_s.end_with?</tt>; see String#end_with?.
13223 *
13224 */
13225
13226static VALUE
13227sym_end_with(int argc, VALUE *argv, VALUE sym)
13228{
13229 return rb_str_end_with(argc, argv, rb_sym2str(sym));
13230}
13231
13232/*
13233 * call-seq:
13234 * encoding -> encoding
13235 *
13236 * Equivalent to <tt>self.to_s.encoding</tt>; see String#encoding.
13237 *
13238 */
13239
13240static VALUE
13241sym_encoding(VALUE sym)
13242{
13243 return rb_obj_encoding(rb_sym2str(sym));
13244}
13245
13246static VALUE
13247string_for_symbol(VALUE name)
13248{
13249 if (!RB_TYPE_P(name, T_STRING)) {
13250 VALUE tmp = rb_check_string_type(name);
13251 if (NIL_P(tmp)) {
13252 rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
13253 name);
13254 }
13255 name = tmp;
13256 }
13257 return name;
13258}
13259
13260ID
13262{
13263 if (SYMBOL_P(name)) {
13264 return SYM2ID(name);
13265 }
13266 name = string_for_symbol(name);
13267 return rb_intern_str(name);
13268}
13269
13270VALUE
13272{
13273 if (SYMBOL_P(name)) {
13274 return name;
13275 }
13276 name = string_for_symbol(name);
13277 return rb_str_intern(name);
13278}
13279
13280/*
13281 * call-seq:
13282 * Symbol.all_symbols -> array_of_symbols
13283 *
13284 * Returns an array of all symbols currently in Ruby's symbol table:
13285 *
13286 * Symbol.all_symbols.size # => 9334
13287 * Symbol.all_symbols.take(3) # => [:!, :"\"", :"#"]
13288 *
13289 */
13290
13291static VALUE
13292sym_all_symbols(VALUE _)
13293{
13294 return rb_sym_all_symbols();
13295}
13296
13297VALUE
13298rb_str_to_interned_str(VALUE str)
13299{
13300 return rb_fstring(str);
13301}
13302
13303VALUE
13304rb_interned_str(const char *ptr, long len)
13305{
13306 struct RString fake_str = {RBASIC_INIT};
13307 int encidx = ENCINDEX_US_ASCII;
13308 int coderange = ENC_CODERANGE_7BIT;
13309 if (len > 0 && search_nonascii(ptr, ptr + len)) {
13310 encidx = ENCINDEX_ASCII_8BIT;
13311 coderange = ENC_CODERANGE_VALID;
13312 }
13313 VALUE str = setup_fake_str(&fake_str, ptr, len, encidx);
13314 ENC_CODERANGE_SET(str, coderange);
13315 return register_fstring(str, true, false);
13316}
13317
13318VALUE
13320{
13321 return rb_interned_str(ptr, strlen(ptr));
13322}
13323
13324VALUE
13325rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
13326{
13327 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13328 rb_enc_autoload(enc);
13329 }
13330
13331 struct RString fake_str = {RBASIC_INIT};
13332 return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), true, false);
13333}
13334
13335VALUE
13336rb_enc_literal_str(const char *ptr, long len, rb_encoding *enc)
13337{
13338 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13339 rb_enc_autoload(enc);
13340 }
13341
13342 struct RString fake_str = {RBASIC_INIT};
13343 VALUE str = register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), true, true);
13344 RUBY_ASSERT(RB_OBJ_SHAREABLE_P(str) && (rb_gc_verify_shareable(str), 1));
13345 return str;
13346}
13347
13348VALUE
13350{
13351 return rb_enc_interned_str(ptr, strlen(ptr), enc);
13352}
13353
13354#if USE_YJIT || USE_ZJIT
13355void
13356rb_jit_str_concat_codepoint(VALUE str, VALUE codepoint)
13357{
13358 if (RB_LIKELY(ENCODING_GET_INLINED(str) == rb_ascii8bit_encindex())) {
13359 ssize_t code = RB_NUM2SSIZE(codepoint);
13360
13361 if (RB_LIKELY(code >= 0 && code < 0xff)) {
13362 rb_str_buf_cat_byte(str, (char) code);
13363 return;
13364 }
13365 }
13366
13367 rb_str_concat(str, codepoint);
13368}
13369#endif
13370
13371static int
13372fstring_set_class_i(VALUE *str, void *data)
13373{
13374 RBASIC_SET_CLASS(*str, rb_cString);
13375
13376 return ST_CONTINUE;
13377}
13378
13379void
13380Init_String(void)
13381{
13382 rb_cString = rb_define_class("String", rb_cObject);
13383
13384 rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
13385
13387 rb_define_alloc_func(rb_cString, empty_str_alloc);
13388 rb_define_singleton_method(rb_cString, "new", rb_str_s_new, -1);
13389 rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
13390 rb_define_method(rb_cString, "initialize", rb_str_init, -1);
13392 rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
13393 rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
13396 rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
13397 rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
13398 rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
13399 rb_define_method(rb_cString, "casecmp?", rb_str_casecmp_p, 1);
13402 rb_define_method(rb_cString, "%", rb_str_format_m, 1);
13403 rb_define_method(rb_cString, "[]", rb_str_aref_m, -1);
13404 rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1);
13405 rb_define_method(rb_cString, "insert", rb_str_insert, 2);
13408 rb_define_method(rb_cString, "bytesize", rb_str_bytesize, 0);
13409 rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
13410 rb_define_method(rb_cString, "=~", rb_str_match, 1);
13411 rb_define_method(rb_cString, "match", rb_str_match_m, -1);
13412 rb_define_method(rb_cString, "match?", rb_str_match_m_p, -1);
13414 rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
13416 rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
13417 rb_define_method(rb_cString, "upto", rb_str_upto, -1);
13418 rb_define_method(rb_cString, "index", rb_str_index_m, -1);
13419 rb_define_method(rb_cString, "byteindex", rb_str_byteindex_m, -1);
13420 rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
13421 rb_define_method(rb_cString, "byterindex", rb_str_byterindex_m, -1);
13422 rb_define_method(rb_cString, "clear", rb_str_clear, 0);
13423 rb_define_method(rb_cString, "chr", rb_str_chr, 0);
13424 rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1);
13425 rb_define_method(rb_cString, "setbyte", rb_str_setbyte, 2);
13426 rb_define_method(rb_cString, "bit_get", rb_str_bit_get, -1);
13427 rb_define_method(rb_cString, "bit_set?", rb_str_bit_set_p, -1);
13428 rb_define_method(rb_cString, "bit_set", rb_str_bit_set, -1);
13429 rb_define_method(rb_cString, "bit_clear", rb_str_bit_clear, -1);
13430 rb_define_method(rb_cString, "bit_flip", rb_str_bit_flip, -1);
13431 rb_define_method(rb_cString, "bit_count", rb_str_bit_count, 0);
13432 rb_define_method(rb_cString, "bitwise_not", rb_str_bitwise_not, 0);
13433 rb_define_method(rb_cString, "bitwise_not!", rb_str_bitwise_not_bang, 0);
13434 rb_define_method(rb_cString, "bitwise_and", rb_str_bitwise_and, 1);
13435 rb_define_method(rb_cString, "bitwise_and!", rb_str_bitwise_and_bang, 1);
13436 rb_define_method(rb_cString, "bitwise_or", rb_str_bitwise_or, 1);
13437 rb_define_method(rb_cString, "bitwise_or!", rb_str_bitwise_or_bang, 1);
13438 rb_define_method(rb_cString, "bitwise_xor", rb_str_bitwise_xor, 1);
13439 rb_define_method(rb_cString, "bitwise_xor!", rb_str_bitwise_xor_bang, 1);
13440 rb_define_method(rb_cString, "byteslice", rb_str_byteslice, -1);
13441 rb_define_method(rb_cString, "bytesplice", rb_str_bytesplice, -1);
13442 rb_define_method(rb_cString, "scrub", str_scrub, -1);
13443 rb_define_method(rb_cString, "scrub!", str_scrub_bang, -1);
13445 rb_define_method(rb_cString, "+@", str_uplus, 0);
13446 rb_define_method(rb_cString, "-@", str_uminus, 0);
13447 rb_define_method(rb_cString, "dup", rb_str_dup_m, 0);
13448 rb_define_alias(rb_cString, "dedup", "-@");
13449
13450 rb_define_method(rb_cString, "to_i", rb_str_to_i, -1);
13451 rb_define_method(rb_cString, "to_f", rb_str_to_f, 0);
13452 rb_define_method(rb_cString, "to_s", rb_str_to_s, 0);
13453 rb_define_method(rb_cString, "to_str", rb_str_to_s, 0);
13456 rb_define_method(rb_cString, "undump", str_undump, 0);
13457
13458 sym_ascii = ID2SYM(rb_intern_const("ascii"));
13459 sym_turkic = ID2SYM(rb_intern_const("turkic"));
13460 sym_lithuanian = ID2SYM(rb_intern_const("lithuanian"));
13461 sym_fold = ID2SYM(rb_intern_const("fold"));
13462
13463 rb_define_method(rb_cString, "upcase", rb_str_upcase, -1);
13464 rb_define_method(rb_cString, "downcase", rb_str_downcase, -1);
13465 rb_define_method(rb_cString, "capitalize", rb_str_capitalize, -1);
13466 rb_define_method(rb_cString, "swapcase", rb_str_swapcase, -1);
13467
13468 rb_define_method(rb_cString, "upcase!", rb_str_upcase_bang, -1);
13469 rb_define_method(rb_cString, "downcase!", rb_str_downcase_bang, -1);
13470 rb_define_method(rb_cString, "capitalize!", rb_str_capitalize_bang, -1);
13471 rb_define_method(rb_cString, "swapcase!", rb_str_swapcase_bang, -1);
13472
13473 rb_define_method(rb_cString, "hex", rb_str_hex, 0);
13474 rb_define_method(rb_cString, "oct", rb_str_oct, 0);
13475 rb_define_method(rb_cString, "split", rb_str_split_m, -1);
13476 rb_define_method(rb_cString, "lines", rb_str_lines, -1);
13477 rb_define_method(rb_cString, "bytes", rb_str_bytes, 0);
13478 rb_define_method(rb_cString, "chars", rb_str_chars, 0);
13479 rb_define_method(rb_cString, "codepoints", rb_str_codepoints, 0);
13480 rb_define_method(rb_cString, "grapheme_clusters", rb_str_grapheme_clusters, 0);
13481 rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
13482 rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
13483 rb_define_method(rb_cString, "concat", rb_str_concat_multi, -1);
13484 rb_define_method(rb_cString, "append_as_bytes", rb_str_append_as_bytes, -1);
13486 rb_define_method(rb_cString, "prepend", rb_str_prepend_multi, -1);
13487 rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
13488 rb_define_method(rb_cString, "intern", rb_str_intern, 0); /* in symbol.c */
13489 rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); /* in symbol.c */
13490 rb_define_method(rb_cString, "ord", rb_str_ord, 0);
13491
13492 rb_define_method(rb_cString, "include?", rb_str_include, 1);
13493 rb_define_method(rb_cString, "start_with?", rb_str_start_with, -1);
13494 rb_define_method(rb_cString, "end_with?", rb_str_end_with, -1);
13495
13496 rb_define_method(rb_cString, "scan", rb_str_scan, 1);
13497
13498 rb_define_method(rb_cString, "ljust", rb_str_ljust, -1);
13499 rb_define_method(rb_cString, "rjust", rb_str_rjust, -1);
13500 rb_define_method(rb_cString, "center", rb_str_center, -1);
13501
13502 rb_define_method(rb_cString, "sub", rb_str_sub, -1);
13503 rb_define_method(rb_cString, "gsub", rb_str_gsub, -1);
13504 rb_define_method(rb_cString, "chop", rb_str_chop, 0);
13505 rb_define_method(rb_cString, "chomp", rb_str_chomp, -1);
13506 rb_define_method(rb_cString, "strip", rb_str_strip, -1);
13507 rb_define_method(rb_cString, "lstrip", rb_str_lstrip, -1);
13508 rb_define_method(rb_cString, "rstrip", rb_str_rstrip, -1);
13509 rb_define_method(rb_cString, "delete_prefix", rb_str_delete_prefix, 1);
13510 rb_define_method(rb_cString, "delete_suffix", rb_str_delete_suffix, 1);
13511
13512 rb_define_method(rb_cString, "sub!", rb_str_sub_bang, -1);
13513 rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1);
13514 rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0);
13515 rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1);
13516 rb_define_method(rb_cString, "strip!", rb_str_strip_bang, -1);
13517 rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, -1);
13518 rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, -1);
13519 rb_define_method(rb_cString, "delete_prefix!", rb_str_delete_prefix_bang, 1);
13520 rb_define_method(rb_cString, "delete_suffix!", rb_str_delete_suffix_bang, 1);
13521
13522 rb_define_method(rb_cString, "tr", rb_str_tr, 2);
13523 rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2);
13524 rb_define_method(rb_cString, "delete", rb_str_delete, -1);
13525 rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1);
13526 rb_define_method(rb_cString, "count", rb_str_count, -1);
13527
13528 rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2);
13529 rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2);
13530 rb_define_method(rb_cString, "delete!", rb_str_delete_bang, -1);
13531 rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1);
13532
13533 rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
13534 rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
13535 rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);
13536 rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0);
13537 rb_define_method(rb_cString, "each_grapheme_cluster", rb_str_each_grapheme_cluster, 0);
13538
13539 rb_define_method(rb_cString, "sum", rb_str_sum, -1);
13540
13541 rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
13542 rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
13543
13544 rb_define_method(rb_cString, "partition", rb_str_partition, 1);
13545 rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);
13546
13547 rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */
13548 rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1);
13549 rb_define_method(rb_cString, "b", rb_str_b, 0);
13550
13551 /* define UnicodeNormalize module here so that we don't have to look it up */
13552 mUnicodeNormalize = rb_define_module("UnicodeNormalize");
13553 id_normalize = rb_intern_const("normalize");
13554 id_normalized_p = rb_intern_const("normalized?");
13555
13556 rb_define_method(rb_cString, "unicode_normalize", rb_str_unicode_normalize, -1);
13557 rb_define_method(rb_cString, "unicode_normalize!", rb_str_unicode_normalize_bang, -1);
13558 rb_define_method(rb_cString, "unicode_normalized?", rb_str_unicode_normalized_p, -1);
13559
13560 rb_fs = Qnil;
13561 rb_define_hooked_variable("$;", &rb_fs, 0, rb_fs_setter);
13562 rb_define_hooked_variable("$-F", &rb_fs, 0, rb_fs_setter);
13563 rb_gc_register_address(&rb_fs);
13564
13565 rb_cSymbol = rb_define_class("Symbol", rb_cObject);
13569 rb_define_singleton_method(rb_cSymbol, "all_symbols", sym_all_symbols, 0);
13570
13571 rb_define_method(rb_cSymbol, "==", sym_equal, 1);
13572 rb_define_method(rb_cSymbol, "===", sym_equal, 1);
13573 rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
13574 rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0); /* in proc.c */
13575 rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
13576 rb_define_method(rb_cSymbol, "next", sym_succ, 0);
13577
13578 rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
13579 rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
13580 rb_define_method(rb_cSymbol, "casecmp?", sym_casecmp_p, 1);
13581 rb_define_method(rb_cSymbol, "=~", sym_match, 1);
13582
13583 rb_define_method(rb_cSymbol, "[]", sym_aref, -1);
13584 rb_define_method(rb_cSymbol, "slice", sym_aref, -1);
13585 rb_define_method(rb_cSymbol, "length", sym_length, 0);
13586 rb_define_method(rb_cSymbol, "size", sym_length, 0);
13587 rb_define_method(rb_cSymbol, "match", sym_match_m, -1);
13588 rb_define_method(rb_cSymbol, "match?", sym_match_m_p, -1);
13589
13590 rb_define_method(rb_cSymbol, "upcase", sym_upcase, -1);
13591 rb_define_method(rb_cSymbol, "downcase", sym_downcase, -1);
13592 rb_define_method(rb_cSymbol, "capitalize", sym_capitalize, -1);
13593 rb_define_method(rb_cSymbol, "swapcase", sym_swapcase, -1);
13594
13595 rb_define_method(rb_cSymbol, "start_with?", sym_start_with, -1);
13596 rb_define_method(rb_cSymbol, "end_with?", sym_end_with, -1);
13597
13598 rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
13599}
13600
13601#include "string.rbinc"
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
Definition assert.h:199
#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.
Definition assert.h:291
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
Atomic operations.
@ RUBY_ENC_CODERANGE_7BIT
The object holds 0 to 127 inclusive and nothing else.
Definition coderange.h:39
static enum ruby_coderange_type RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b)
"Mix" two code ranges into one.
Definition coderange.h:162
static int rb_isspace(int c)
Our own locale-insensitive version of isspace(3).
Definition ctype.h:395
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
static bool rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc)
Queries if the passed pointer points to a newline character.
Definition ctype.h:43
static bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc)
Identical to rb_isprint(), except it additionally takes an encoding.
Definition ctype.h:180
static bool rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc)
Queries if the passed code point is of passed character type in the passed encoding.
Definition ctype.h:63
VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt,...)
Identical to rb_sprintf(), except it additionally takes an encoding.
Definition sprintf.c:1209
static VALUE RB_OBJ_FROZEN_RAW(VALUE obj)
This is an implementation detail of RB_OBJ_FROZEN().
Definition fl_type.h:696
static VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags)
This is an implementation detail of RB_FL_TEST().
Definition fl_type.h:404
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1608
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:2897
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition class.c:2707
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.
Definition class.c:3187
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1029
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition class.c:2976
#define TYPE(_)
Old name of rb_type.
Definition value_type.h:108
#define ENCODING_SET_INLINED(obj, i)
Old name of RB_ENCODING_SET_INLINED.
Definition encoding.h:106
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition value_type.h:87
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
Definition coderange.h:180
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
Definition coderange.h:181
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:130
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1683
#define ALLOCV
Old name of RB_ALLOCV.
Definition memory.h:404
#define ISSPACE
Old name of rb_isspace.
Definition ctype.h:88
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define ENC_CODERANGE_CLEAN_P(cr)
Old name of RB_ENC_CODERANGE_CLEAN_P.
Definition coderange.h:183
#define ENC_CODERANGE_AND(a, b)
Old name of RB_ENC_CODERANGE_AND.
Definition coderange.h:188
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
Definition fl_type.h:133
#define rb_str_cat2
Old name of rb_str_cat_cstr.
Definition string.h:1684
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
Definition assume.h:28
#define ID2SYM
Old name of RB_ID2SYM.
Definition symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:131
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
#define SYM2ID
Old name of RB_SYM2ID.
Definition symbol.h:45
#define ENC_CODERANGE(obj)
Old name of RB_ENC_CODERANGE.
Definition coderange.h:184
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define ENC_CODERANGE_UNKNOWN
Old name of RUBY_ENC_CODERANGE_UNKNOWN.
Definition coderange.h:179
#define SIZET2NUM
Old name of RB_SIZE2NUM.
Definition size_t.h:62
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
#define xmalloc
Old name of ruby_xmalloc.
Definition xmalloc.h:53
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
Definition encoding.h:109
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
#define ISDIGIT
Old name of rb_isdigit.
Definition ctype.h:93
#define ENC_CODERANGE_MASK
Old name of RUBY_ENC_CODERANGE_MASK.
Definition coderange.h:178
#define ZALLOC_N
Old name of RB_ZALLOC_N.
Definition memory.h:401
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:399
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
Definition encoding.h:517
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:128
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h:125
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:658
#define ENCODING_INLINE_MAX
Old name of RUBY_ENCODING_INLINE_MAX.
Definition encoding.h:67
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
#define FL_ANY_RAW
Old name of RB_FL_ANY_RAW.
Definition fl_type.h:122
#define ISALPHA
Old name of rb_isalpha.
Definition ctype.h:92
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
Definition encoding.h:518
#define ISASCII
Old name of rb_isascii.
Definition ctype.h:85
#define ULL2NUM
Old name of RB_ULL2NUM.
Definition long_long.h:31
#define TOLOWER
Old name of rb_tolower.
Definition ctype.h:101
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
Definition encoding.h:519
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
Definition fixnum.h:26
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
Definition coderange.h:182
#define scan_hex(s, l, e)
Old name of ruby_scan_hex.
Definition util.h:108
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:405
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
Definition encoding.h:516
#define NUM2ULL
Old name of RB_NUM2ULL.
Definition long_long.h:35
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
#define ISPRINT
Old name of rb_isprint.
Definition ctype.h:86
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition value_type.h:85
#define ENCODING_SHIFT
Old name of RUBY_ENCODING_SHIFT.
Definition encoding.h:68
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:127
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
Definition fl_type.h:65
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define ENCODING_GET_INLINED(obj)
Old name of RB_ENCODING_GET_INLINED.
Definition encoding.h:108
#define ENC_CODERANGE_CLEAR(obj)
Old name of RB_ENC_CODERANGE_CLEAR.
Definition coderange.h:187
#define FL_UNSET
Old name of RB_FL_UNSET.
Definition fl_type.h:129
#define UINT2NUM
Old name of RB_UINT2NUM.
Definition int.h:46
#define ENCODING_IS_ASCII8BIT(obj)
Old name of RB_ENCODING_IS_ASCII8BIT.
Definition encoding.h:110
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition symbol.h:47
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:657
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
Definition coderange.h:186
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
Old name of RB_ENCODING_CODERANGE_SET.
Definition coderange.h:189
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:126
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
#define OBJ_FROZEN_RAW
Old name of RB_OBJ_FROZEN_RAW.
Definition fl_type.h:134
#define T_REGEXP
Old name of RUBY_T_REGEXP.
Definition value_type.h:77
#define ENCODING_MASK
Old name of RUBY_ENCODING_MASK.
Definition encoding.h:69
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:478
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition eval.c:672
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
Definition error.c:4042
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1435
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1431
VALUE rb_eEncCompatError
Encoding::CompatibilityError exception.
Definition error.c:1438
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1429
VALUE rb_eIndexError
IndexError exception.
Definition error.c:1433
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition error.h:48
VALUE rb_cObject
Object class.
Definition object.c:58
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
Definition object.c:646
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition object.c:2239
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 ...
Definition object.c:2257
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
Definition object.c:1309
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.
Definition object.c:3629
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:232
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
Definition object.c:553
VALUE rb_cSymbol
Symbol class.
Definition string.c:85
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:138
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1297
VALUE rb_mComparable
Comparable module.
Definition compar.c:19
VALUE rb_cString
String class.
Definition string.c:84
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3315
Encoding relates APIs.
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
Definition encoding.h:683
static char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the right boundary of a character.
Definition encoding.h:704
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
Definition encoding.h:571
static int rb_enc_mbmaxlen(rb_encoding *enc)
Queries the maximum number of bytes that the passed encoding needs to represent a character.
Definition encoding.h:447
static int RB_ENCODING_GET_INLINED(VALUE obj)
Queries the encoding of the passed object.
Definition encoding.h:99
static int rb_enc_code_to_mbclen(int c, rb_encoding *enc)
Identical to rb_enc_codelen(), except it returns 0 for invalid code points.
Definition encoding.h:619
static char * rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc)
Scans the string backwards for n characters.
Definition encoding.h:726
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Encoding conversion main routine.
Definition string.c:1361
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.
Definition string.c:1226
char * rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc)
Queries the n-th character.
Definition string.c:3090
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.
Definition string.c:1245
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.
Definition string.c:13325
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.
Definition re.c:285
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.
Definition string.c:2372
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.
Definition string.c:3815
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.
Definition string.c:1174
VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc)
Identical to rb_str_export(), except it additionally takes an encoding.
Definition string.c:1466
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.
Definition string.c:1367
int rb_enc_str_asciionly_p(VALUE str)
Queries if the passed string is "ASCII only".
Definition string.c:987
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.
Definition string.c:13349
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.
Definition string.c:843
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.
Definition symbol.c:857
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.
Definition transcode.c:1485
rb_econv_result_t
return value of rb_econv_convert()
Definition transcode.h:30
@ econv_finished
The conversion stopped after converting everything.
Definition transcode.h:57
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
Definition transcode.h:46
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.
Definition transcode.c:2714
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.
Definition transcode.c:2977
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
Definition transcode.c:1742
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1123
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition vm_eval.c:1081
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...
Definition vm_eval.c:1210
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?.
Definition enumerator.h:208
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition enumerator.h:242
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
VALUE rb_fs
The field separator character for inputs, or the $;.
Definition string.c:722
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
Definition io.c:209
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
Definition vm.c:2091
VALUE rb_sym_all_symbols(void)
Collects every single bits of symbols that have ever interned in the entire history of the current pr...
Definition symbol.c:1214
void rb_backref_set(VALUE md)
Updates $~.
Definition vm.c:2097
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
Definition range.c:1970
int rb_reg_backref_number(VALUE match, VALUE backref)
Queries the index of the given named capture.
Definition re.c:1384
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
Definition re.c:4473
VALUE rb_reg_match(VALUE re, VALUE str)
This is the match operator.
Definition re.c:3967
void rb_match_busy(VALUE md)
Asserts that the given MatchData is "occupied".
Definition re.c:1628
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
Definition re.c:2068
void rb_str_free(VALUE str)
Destroys the given string for no reason.
Definition string.c:1771
VALUE rb_str_new_shared(VALUE str)
Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of C's.
Definition string.c:1531
VALUE rb_str_plus(VALUE lhs, VALUE rhs)
Generates a new string, concatenating the former to the latter.
Definition string.c:2523
#define rb_utf8_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "UTF-8" encoding.
Definition string.h:1584
#define rb_hash_end(h)
Just another name of st_hash_end.
Definition string.h:946
#define rb_hash_uint32(h, i)
Just another name of st_hash_uint32.
Definition string.h:940
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition string.c:3880
VALUE rb_filesystem_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "filesystem" encoding.
Definition string.c:1442
VALUE rb_sym_to_s(VALUE sym)
This is an rb_sym2str() + rb_str_dup() combo.
Definition string.c:12957
VALUE rb_str_times(VALUE str, VALUE num)
Repetition of a string.
Definition string.c:2597
VALUE rb_external_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "default external" encoding.
Definition string.c:1418
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
Definition string.c:1765
long rb_str_offset(VALUE str, long pos)
"Inverse" of rb_str_sublen().
Definition string.c:3118
VALUE rb_str_succ(VALUE orig)
Searches for the "successor" of a string.
Definition string.c:5419
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
Definition string.c:4243
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...
Definition string.c:3233
VALUE rb_str_ellipsize(VALUE str, long len)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
Definition string.c:12272
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
Definition random.c:1720
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1499
void rb_str_shared_replace(VALUE dst, VALUE src)
Replaces the contents of the former with the latter.
Definition string.c:1807
#define rb_str_buf_cat
Just another name of rb_str_cat.
Definition string.h:1682
VALUE rb_str_new_static(const char *ptr, long len)
Identical to rb_str_new(), except it takes a C string literal.
Definition string.c:1208
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
Definition string.h:1533
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
Definition string.c:1022
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition string.c:1537
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition string.c:2005
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
Definition string.c:4229
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
Definition string.c:3648
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.
Definition string.c:2459
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...
Definition string.c:2023
#define rb_str_buf_new_cstr(str)
Identical to rb_str_new_cstr, except done differently.
Definition string.h:1640
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
Definition string.h:1568
VALUE rb_str_replace(VALUE dst, VALUE src)
Replaces the contents of the former object with the stringised contents of the latter.
Definition string.c:6630
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.
Definition string.c:3241
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
Definition string.h:1147
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.
Definition string.c:13319
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...
Definition string.c:1448
#define rb_external_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "default external" encoding.
Definition string.h:1605
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.
Definition string.c:3846
long rb_str_sublen(VALUE str, long pos)
Byte offset to character offset conversion.
Definition string.c:3165
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
Definition string.c:4350
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3467
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
Definition string.c:7807
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition string.c:2829
VALUE rb_interned_str(const char *ptr, long len)
Identical to rb_str_new(), except it returns an infamous "f"string.
Definition string.c:13304
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
Definition string.c:4297
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
Definition string.c:4117
int rb_str_comparable(VALUE str1, VALUE str2)
Checks if two strings are comparable each other or not.
Definition string.c:4272
#define rb_strlen_lit(str)
Length of a string literal.
Definition string.h:1693
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 ...
Definition string.c:3822
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
Definition string.c:3358
void rb_str_update(VALUE dst, long beg, long len, VALUE src)
Replaces some (or all) of the contents of the given string.
Definition string.c:5906
VALUE rb_str_scrub(VALUE str, VALUE repl)
"Cleanses" the string.
Definition string.c:12330
#define rb_locale_str_new_cstr(str)
Identical to rb_external_str_new_cstr, except it generates a string of "locale" encoding instead of "...
Definition string.h:1626
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.
Definition string.c:1721
#define rb_str_dup_frozen
Just another name of rb_str_new_frozen.
Definition string.h:632
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3014
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
Definition string.c:3330
#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.
Definition string.h:1657
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
Definition string.c:3449
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...
Definition string.c:1220
#define rb_utf8_str_new(str, len)
Identical to rb_str_new, except it generates a string of "UTF-8" encoding.
Definition string.h:1550
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
Definition string.c:2783
VALUE rb_str_dump(VALUE str)
"Inverse" of rb_eval_string().
Definition string.c:7924
VALUE rb_locale_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "locale" encoding.
Definition string.c:1430
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition string.c:1737
VALUE rb_str_length(VALUE)
Identical to rb_str_strlen(), except it returns the value in rb_cInteger.
Definition string.c:2473
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
Definition string.h:1515
VALUE rb_str_drop_bytes(VALUE str, long len)
Shrinks the given string for the given number of bytes.
Definition string.c:5821
VALUE rb_str_split(VALUE str, const char *delim)
Divides the given string based on the given delimiter.
Definition string.c:9966
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...
Definition string.c:1214
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
Definition symbol.c:1084
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition string.c:1869
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.
Definition variable.c:2059
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
Definition variable.c:2119
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3552
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
Definition vm_method.c:1799
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:285
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
Definition symbol.c:1147
VALUE rb_to_symbol(VALUE name)
Identical to rb_intern_str(), except it generates a dynamic symbol if necessary.
Definition string.c:13271
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...
Definition string.c:13261
int capa
Designed capacity of the buffer.
Definition io.h:11
int off
Offset inside of ptr.
Definition io.h:5
int len
Length of the buffer.
Definition io.h:8
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
Definition ractor.h:235
long rb_reg_search(VALUE re, VALUE str, long pos, int dir)
Runs the passed regular expression over the passed string.
Definition re.c:1997
VALUE rb_reg_regcomp(VALUE str)
Creates a new instance of rb_cRegexp.
Definition re.c:3672
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition sprintf.c:227
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1378
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
#define ALLOCA_N(type, n)
Definition memory.h:292
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition memory.h:360
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
VALUE type(ANYARGS)
ANYARGS-ed function type.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
Defines RBIMPL_ATTR_NONSTRING.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition rarray.h:280
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:51
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
Definition rbasic.h:166
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
static VALUE RREGEXP_SRC(VALUE rexp)
Convenient getter function.
Definition rregexp.h:102
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
VALUE rb_str_export_locale(VALUE obj)
Identical to rb_str_export(), except it converts into the locale encoding instead.
Definition string.c:1460
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...
Definition string.c:2985
static int RSTRING_LENINT(VALUE str)
Identical to RSTRING_LEN(), except it differs for the return type.
Definition rstring.h:438
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition rstring.h:409
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition rstring.h:450
VALUE rb_string_value(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it fills the passed pointer with the converted object.
Definition string.c:2848
#define RSTRING(obj)
Convenient casting macro.
Definition rstring.h:41
VALUE rb_str_export(VALUE obj)
Identical to rb_str_to_str(), except it additionally converts the string into default external encodi...
Definition string.c:1454
char * rb_string_value_ptr(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it returns the converted string's backend memory region.
Definition string.c:2861
VALUE rb_str_to_str(VALUE obj)
Identical to rb_check_string_type(), except it raises exceptions in case of conversion failures.
Definition string.c:1798
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition rstring.h:89
#define DATA_PTR(obj)
Convenient casting macro for backward compatibility.
Definition rtypeddata.h:435
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
Definition rtypeddata.h:557
VALUE rb_require(const char *feature)
Identical to rb_require_string(), except it takes C's string instead of Ruby's.
Definition load.c:1489
#define errno
Ractor-aware version of errno.
Definition ruby.h:388
#define RB_NUM2SSIZE
Converts an instance of rb_cInteger into C's ssize_t.
Definition size_t.h:49
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
VALUE flags
Per-object flags.
Definition rbasic.h:81
Ruby's String.
Definition rstring.h:196
struct RBasic basic
Basic part, including flags and class.
Definition rstring.h:199
union RString::@60::@61::@63 aux
Auxiliary info.
long capa
Capacity of *ptr.
Definition rstring.h:232
long len
Length of the string, not including terminating NUL character.
Definition rstring.h:206
struct RString::@60::@61 heap
Strings that use separated memory region for contents use this pattern.
struct RString::@60::@62 embed
Embedded contents.
VALUE shared
Parent of the string.
Definition rstring.h:240
char * ptr
Pointer to the contents of the string.
Definition rstring.h:222
union RString::@60 as
String's specific fields.
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:238
Definition string.c:8848
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock)
Blocks until the current thread obtains a lock.
Definition thread.c:310
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
Definition value_type.h:225
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:425
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376
ruby_value_type
C-level type of an object.
Definition value_type.h:113