12#include "ruby/internal/config.h"
19#include "internal/bignum.h"
20#include "internal/encoding.h"
21#include "internal/error.h"
22#include "internal/hash.h"
23#include "internal/imemo.h"
24#include "internal/re.h"
25#include "internal/string.h"
26#include "internal/object.h"
27#include "internal/ractor.h"
28#include "internal/variable.h"
33#include "ractor_core.h"
52#define KCODE_FIXED FL_USER4
53#define REG_ENCODING_NONE FL_USER6
66#define MATCH_BUSY FL_USER0
70typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN];
71#define errcpy(err, msg) strlcpy((err), (msg), ONIG_MAX_ERROR_MESSAGE_LEN)
74static const char casetable[] = {
75 '\000',
'\001',
'\002',
'\003',
'\004',
'\005',
'\006',
'\007',
76 '\010',
'\011',
'\012',
'\013',
'\014',
'\015',
'\016',
'\017',
77 '\020',
'\021',
'\022',
'\023',
'\024',
'\025',
'\026',
'\027',
78 '\030',
'\031',
'\032',
'\033',
'\034',
'\035',
'\036',
'\037',
80 '\040',
'\041',
'\042',
'\043',
'\044',
'\045',
'\046',
'\047',
82 '\050',
'\051',
'\052',
'\053',
'\054',
'\055',
'\056',
'\057',
84 '\060',
'\061',
'\062',
'\063',
'\064',
'\065',
'\066',
'\067',
86 '\070',
'\071',
'\072',
'\073',
'\074',
'\075',
'\076',
'\077',
88 '\100',
'\141',
'\142',
'\143',
'\144',
'\145',
'\146',
'\147',
90 '\150',
'\151',
'\152',
'\153',
'\154',
'\155',
'\156',
'\157',
92 '\160',
'\161',
'\162',
'\163',
'\164',
'\165',
'\166',
'\167',
94 '\170',
'\171',
'\172',
'\133',
'\134',
'\135',
'\136',
'\137',
96 '\140',
'\141',
'\142',
'\143',
'\144',
'\145',
'\146',
'\147',
98 '\150',
'\151',
'\152',
'\153',
'\154',
'\155',
'\156',
'\157',
100 '\160',
'\161',
'\162',
'\163',
'\164',
'\165',
'\166',
'\167',
102 '\170',
'\171',
'\172',
'\173',
'\174',
'\175',
'\176',
'\177',
103 '\200',
'\201',
'\202',
'\203',
'\204',
'\205',
'\206',
'\207',
104 '\210',
'\211',
'\212',
'\213',
'\214',
'\215',
'\216',
'\217',
105 '\220',
'\221',
'\222',
'\223',
'\224',
'\225',
'\226',
'\227',
106 '\230',
'\231',
'\232',
'\233',
'\234',
'\235',
'\236',
'\237',
107 '\240',
'\241',
'\242',
'\243',
'\244',
'\245',
'\246',
'\247',
108 '\250',
'\251',
'\252',
'\253',
'\254',
'\255',
'\256',
'\257',
109 '\260',
'\261',
'\262',
'\263',
'\264',
'\265',
'\266',
'\267',
110 '\270',
'\271',
'\272',
'\273',
'\274',
'\275',
'\276',
'\277',
111 '\300',
'\301',
'\302',
'\303',
'\304',
'\305',
'\306',
'\307',
112 '\310',
'\311',
'\312',
'\313',
'\314',
'\315',
'\316',
'\317',
113 '\320',
'\321',
'\322',
'\323',
'\324',
'\325',
'\326',
'\327',
114 '\330',
'\331',
'\332',
'\333',
'\334',
'\335',
'\336',
'\337',
115 '\340',
'\341',
'\342',
'\343',
'\344',
'\345',
'\346',
'\347',
116 '\350',
'\351',
'\352',
'\353',
'\354',
'\355',
'\356',
'\357',
117 '\360',
'\361',
'\362',
'\363',
'\364',
'\365',
'\366',
'\367',
118 '\370',
'\371',
'\372',
'\373',
'\374',
'\375',
'\376',
'\377',
121# error >>> "You lose. You will need a translation table for your character set." <<<
125rb_hrtime_t rb_reg_match_time_limit = 0;
128rb_memcicmp(
const void *x,
const void *y,
long len)
130 const unsigned char *p1 = x, *p2 = y;
134 if ((tmp = casetable[(
unsigned)*p1++] - casetable[(
unsigned)*p2++]))
140#if defined(HAVE_MEMMEM) && !defined(__APPLE__)
142rb_memsearch_ss(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
144 const unsigned char *y;
146 if ((y = memmem(ys, n, xs, m)) != NULL)
153rb_memsearch_ss(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
155 const unsigned char *x = xs, *xe = xs + m;
156 const unsigned char *y = ys, *ye = ys + n;
157#define VALUE_MAX ((VALUE)~(VALUE)0)
161 rb_bug(
"!!too long pattern string!!");
163 if (!(y = memchr(y, *x, n - m + 1)))
167 for (hx = *x++, hy = *y++; x < xe; ++x, ++y) {
187rb_memsearch_qs(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
189 const unsigned char *x = xs, *xe = xs + m;
190 const unsigned char *y = ys;
191 VALUE i, qstable[256];
194 for (i = 0; i < 256; ++i)
197 qstable[*x] = xe - x;
199 for (; y + m <= ys + n; y += *(qstable + y[m])) {
200 if (*xs == *y && memcmp(xs, y, m) == 0)
206static inline unsigned int
207rb_memsearch_qs_utf8_hash(
const unsigned char *x)
209 register const unsigned int mix = 8353;
210 register unsigned int h = *x;
235 return (
unsigned char)h;
239rb_memsearch_qs_utf8(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
241 const unsigned char *x = xs, *xe = xs + m;
242 const unsigned char *y = ys;
243 VALUE i, qstable[512];
246 for (i = 0; i < 512; ++i) {
249 for (; x < xe; ++x) {
250 qstable[rb_memsearch_qs_utf8_hash(x)] = xe - x;
253 for (; y + m <= ys + n; y += qstable[rb_memsearch_qs_utf8_hash(y+m)]) {
254 if (*xs == *y && memcmp(xs, y, m) == 0)
261rb_memsearch_with_char_size(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n,
int char_size)
263 const unsigned char *x = xs, x0 = *xs, *y = ys;
265 for (n -= m; n >= 0; n -= char_size, y += char_size) {
266 if (x0 == *y && memcmp(x+1, y+1, m-1) == 0)
273rb_memsearch_wchar(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
275 return rb_memsearch_with_char_size(xs, m, ys, n, 2);
279rb_memsearch_qchar(
const unsigned char *xs,
long m,
const unsigned char *ys,
long n)
281 return rb_memsearch_with_char_size(xs, m, ys, n, 4);
287 const unsigned char *x = x0, *y = y0;
289 if (m > n)
return -1;
291 return memcmp(x0, y0, m) == 0 ? 0 : -1;
297 const unsigned char *ys = memchr(y, *x, n);
304 else if (LIKELY(rb_enc_mbminlen(enc) == 1)) {
306 return rb_memsearch_ss(x0, m, y0, n);
308 else if (enc == rb_utf8_encoding()){
309 return rb_memsearch_qs_utf8(x0, m, y0, n);
312 else if (LIKELY(rb_enc_mbminlen(enc) == 2)) {
313 return rb_memsearch_wchar(x0, m, y0, n);
315 else if (LIKELY(rb_enc_mbminlen(enc) == 4)) {
316 return rb_memsearch_qchar(x0, m, y0, n);
318 return rb_memsearch_qs(x0, m, y0, n);
328 val = ONIG_OPTION_IGNORECASE;
331 val = ONIG_OPTION_EXTEND;
334 val = ONIG_OPTION_MULTILINE;
343enum { OPTBUF_SIZE = 4 };
346option_to_str(
char str[OPTBUF_SIZE],
int options)
349 if (options & ONIG_OPTION_MULTILINE) *p++ =
'm';
350 if (options & ONIG_OPTION_IGNORECASE) *p++ =
'i';
351 if (options & ONIG_OPTION_EXTEND) *p++ =
'x';
363 *kcode = rb_ascii8bit_encindex();
364 return (*option = ARG_ENCODING_NONE);
366 *kcode = ENCINDEX_EUC_JP;
369 *kcode = ENCINDEX_Windows_31J;
372 *kcode = rb_utf8_encindex();
376 return (*option = char_to_option(c));
378 *option = ARG_ENCODING_FIXED;
383reg_initialized_p(
VALUE re)
389rb_reg_check(
VALUE re)
391 if (!reg_initialized_p(re)) {
397rb_reg_expr_str(
VALUE str,
const char *s,
long len,
400 const char *p, *pend;
405 p = s; pend = p +
len;
409 c = rb_enc_ascget(p, pend, &clen, enc);
412 p += mbclen(p, pend, enc);
436 int unicode_p = rb_enc_unicode_p(enc);
439 c = rb_enc_ascget(p, pend, &clen, enc);
440 if (c ==
'\\' && p+clen < pend) {
441 int n = clen + mbclen(p+clen, pend, enc);
447 clen = rb_enc_precise_mbclen(p, pend, enc);
449 c = (
unsigned char)*p;
454 unsigned int c = rb_enc_mbc_to_codepoint(p, pend, enc);
455 rb_str_buf_cat_escaped_char(str, c, unicode_p);
462 else if (c == term) {
470 else if (!rb_enc_isspace(c, enc)) {
474 snprintf(b,
sizeof(b),
"\\x%02X", c);
490 rb_encoding *resenc = rb_default_internal_encoding();
491 if (resenc == NULL) resenc = rb_default_external_encoding();
493 if (re && rb_enc_asciicompat(enc)) {
494 rb_enc_copy(str, re);
497 rb_enc_associate(str, rb_usascii_encoding());
501 rb_reg_expr_str(str, RSTRING_PTR(src_str), RSTRING_LEN(src_str), enc, resenc,
'/');
506 char opts[OPTBUF_SIZE];
508 if (*option_to_str(opts,
RREGEXP_PTR(re)->options))
510 if (
RBASIC(re)->flags & REG_ENCODING_NONE)
536rb_reg_source(
VALUE re)
557rb_reg_inspect(
VALUE re)
559 if (!reg_initialized_p(re)) {
562 return rb_reg_desc(re);
565static VALUE rb_reg_str_with_term(
VALUE re,
int term);
597 return rb_reg_str_with_term(re,
'/');
601rb_reg_str_with_term(
VALUE re,
int term)
604 const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
606 char optbuf[OPTBUF_SIZE + 1];
611 rb_enc_copy(str, re);
614 const UChar *ptr = (UChar *)RSTRING_PTR(src_str);
615 long len = RSTRING_LEN(src_str);
617 if (
len >= 4 && ptr[0] ==
'(' && ptr[1] ==
'?') {
620 if ((
len -= 2) > 0) {
622 opt = char_to_option((
int )*ptr);
632 if (
len > 1 && *ptr ==
'-') {
636 opt = char_to_option((
int )*ptr);
651 if (*ptr ==
':' && ptr[
len-1] ==
')') {
658 err = onig_new(&rp, ptr, ptr +
len, options,
659 enc, OnigDefaultSyntax, NULL);
672 if ((options & embeddable) != embeddable) {
674 option_to_str(optbuf + 1, ~options);
679 if (rb_enc_asciicompat(enc)) {
680 rb_reg_expr_str(str, (
char*)ptr,
len, enc, NULL, term);
688 rb_enc_associate(str, rb_usascii_encoding());
692 s = RSTRING_PTR(str);
698 rb_str_resize(str, RSTRING_LEN(str) - n);
700 rb_reg_expr_str(str, (
char*)ptr,
len, enc, NULL, term);
703 rb_enc_copy(str, re);
710NORETURN(
static void rb_reg_raise(
const char *err,
VALUE re));
713rb_reg_raise(
const char *err,
VALUE re)
715 VALUE desc = rb_reg_desc(re);
721rb_enc_reg_error_desc(
const char *s,
long len,
rb_encoding *enc,
int options,
const char *err)
723 char opts[OPTBUF_SIZE + 1];
725 rb_encoding *resenc = rb_default_internal_encoding();
726 if (resenc == NULL) resenc = rb_default_external_encoding();
728 rb_enc_associate(desc, enc);
730 rb_reg_expr_str(desc, s,
len, enc, resenc,
'/');
732 option_to_str(opts + 1, options);
737NORETURN(
static void rb_enc_reg_raise(
const char *s,
long len,
rb_encoding *enc,
int options,
const char *err));
740rb_enc_reg_raise(
const char *s,
long len,
rb_encoding *enc,
int options,
const char *err)
746rb_reg_error_desc(
VALUE str,
int options,
const char *err)
748 return rb_enc_reg_error_desc(RSTRING_PTR(str), RSTRING_LEN(str),
749 rb_enc_get(str), options, err);
752NORETURN(
static void rb_reg_raise_str(
VALUE str,
int options,
const char *err));
755rb_reg_raise_str(
VALUE str,
int options,
const char *err)
775rb_reg_casefold_p(
VALUE re)
778 return RBOOL(
RREGEXP_PTR(re)->options & ONIG_OPTION_IGNORECASE);
820rb_reg_options_m(
VALUE re)
827reg_names_iter(
const OnigUChar *name,
const OnigUChar *name_end,
828 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
831 rb_ary_push(ary, rb_enc_str_new((
const char *)name, name_end-name, regex->enc));
849rb_reg_names(
VALUE re)
854 onig_foreach_name(
RREGEXP_PTR(re), reg_names_iter, (
void*)ary);
859reg_named_captures_iter(
const OnigUChar *name,
const OnigUChar *name_end,
860 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
866 for (i = 0; i < back_num; i++)
869 rb_hash_aset(hash,
rb_str_new((
const char*)name, name_end-name),ary);
893rb_reg_named_captures(
VALUE re)
896 VALUE hash = rb_hash_new_capa(onig_number_of_names(reg));
897 onig_foreach_name(reg, reg_named_captures_iter, (
void*)hash);
902onig_new_with_source(
regex_t* reg,
const UChar* pattern,
const UChar* pattern_end,
904 OnigErrorInfo* einfo,
const char *sourcefile,
int sourceline)
908 if (IS_NULL(reg))
return ONIGERR_MEMORY;
910 r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
913 r = onig_compile_ruby(reg, pattern, pattern_end, einfo, sourcefile, sourceline);
922make_regexp(
Regexp *rp,
const char *s,
long len,
rb_encoding *enc,
int flags, onig_errmsg_buffer err,
923 const char *sourcefile,
int sourceline)
935 r = onig_new_with_source(rp, (UChar*)s, (UChar*)(s +
len), flags,
936 enc, OnigDefaultSyntax, &einfo, sourcefile, sourceline);
938 onig_error_code_to_str((UChar*)err, r, &einfo);
997match_alloc_n(
VALUE klass,
int num_regs)
999 int capa = num_regs * 2;
1000 size_t alloc_size = offsetof(
struct RMatch, as) +
sizeof(OnigPosition) *
capa;
1001 if (alloc_size <
sizeof(
struct RMatch)) {
1002 alloc_size =
sizeof(
struct RMatch);
1006 if (!rb_gc_size_allocatable_p(alloc_size)) {
1007 alloc_size =
sizeof(
struct RMatch);
1008 flags |= RMATCH_ONIG;
1012 NEWOBJ_OF(match,
struct RMatch, klass, flags, alloc_size);
1013 memset(((
char *)match) +
sizeof(
struct RBasic), 0, alloc_size -
sizeof(
struct RBasic));
1015 return (
VALUE)match;
1019match_alloc(
VALUE klass)
1021 return match_alloc_n(klass, 0);
1028 if (to->allocated)
return 0;
1031 if (to->allocated)
return 0;
1032 return ONIGERR_MEMORY;
1036match_to_onig(
VALUE match,
int num_regs,
const OnigPosition *src_beg,
const OnigPosition *src_end)
1040 if (onig_region_resize(&tmp, num_regs)) {
1043 memcpy(tmp.beg, src_beg, num_regs *
sizeof(OnigPosition));
1044 memcpy(tmp.end, src_end, num_regs *
sizeof(OnigPosition));
1050rb_match_ensure_onig(
VALUE match)
1055 match_to_onig(match, n, &rm->
as.embed[0], &rm->
as.embed[n]);
1062match_set_regs(
VALUE match,
int num_regs,
const OnigPosition *beg,
const OnigPosition *end)
1067 if (onig_region_resize(&rm->
as.onig,
num_regs)) {
1070 memcpy(rm->
as.onig.beg, beg,
num_regs *
sizeof(OnigPosition));
1071 memcpy(rm->
as.onig.end, end,
num_regs *
sizeof(OnigPosition));
1074 memcpy(&rm->
as.embed[0], beg,
num_regs *
sizeof(OnigPosition));
1078 match_to_onig(match,
num_regs, beg, end);
1087rb_match_blob_dump(
VALUE match,
VALUE *regexp_out,
VALUE *str_out,
int *num_regs_out,
bool release_source)
1091 *regexp_out = rm->
regexp;
1095 OnigPosition *blob =
ALLOC_N(OnigPosition, n ? 2 * n : 1);
1096 const OnigPosition *beg = RMATCH_BEG_PTR(match);
1097 const OnigPosition *end = RMATCH_END_PTR(match);
1098 for (
int i = 0; i < n; i++) {
1099 blob[2 * i] = beg[i];
1100 blob[2 * i + 1] = end[i];
1104 if (release_source) {
1106 onig_region_free(&rm->
as.onig, 0);
1107 memset(&rm->
as.onig, 0,
sizeof(rm->
as.onig));
1122 return match_alloc_n(klass,
num_regs);
1128 const OnigPosition *blob = blob_;
1135 for (
int i = 0; i <
num_regs; i++) {
1136 beg[i] = blob[2 * i];
1137 end[i] = blob[2 * i + 1];
1139 match_set_regs(match,
num_regs, beg, end);
1145rb_match_blob_free(
void *blob)
1156pair_byte_cmp(
const void *pair1,
const void *pair2)
1158 long diff = ((
pair_t*)pair1)->byte_pos - ((
pair_t*)pair2)->byte_pos;
1159#if SIZEOF_LONG > SIZEOF_INT
1160 return diff ? diff > 0 ? 1 : -1 : 0;
1167update_char_offset(
VALUE match)
1200 if (RMATCH_BEG(match, i) < 0)
1202 pairs[num_pos++].byte_pos = RMATCH_BEG(match, i);
1203 pairs[num_pos++].byte_pos = RMATCH_END(match, i);
1205 qsort(pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1207 s = p = RSTRING_PTR(
RMATCH(match)->
str);
1209 for (i = 0; i < num_pos; i++) {
1210 q = s + pairs[i].byte_pos;
1212 pairs[i].char_pos = c;
1218 if (RMATCH_BEG(match, i) < 0) {
1224 key.byte_pos = RMATCH_BEG(match, i);
1225 found = bsearch(&key, pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1228 key.byte_pos = RMATCH_END(match, i);
1229 found = bsearch(&key, pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1237match_check(
VALUE match)
1256 match_set_regs(obj, RMATCH_NREGS(orig), RMATCH_BEG_PTR(orig), RMATCH_END_PTR(orig));
1285match_regexp(
VALUE match)
1320match_names(
VALUE match)
1341match_size(
VALUE match)
1344 return INT2FIX(RMATCH_NREGS(match));
1347static int match_name_to_backref_number(
VALUE match,
VALUE name);
1348NORETURN(
static void name_to_backref_error(
VALUE name));
1351name_to_backref_error(
VALUE name)
1353 rb_raise(
rb_eIndexError,
"undefined group name reference: % "PRIsVALUE,
1358backref_number_check(
VALUE match,
int i)
1360 if (i < 0 || RMATCH_NREGS(match) <= i)
1365match_backref_number(
VALUE match,
VALUE backref)
1377 num = match_name_to_backref_number(match, backref);
1380 name_to_backref_error(backref);
1389 return match_backref_number(match, backref);
1404 int i = match_backref_number(match, n);
1407 backref_number_check(match, i);
1409 if (RMATCH_BEG(match, i) < 0)
1412 update_char_offset(match);
1438 int i = match_backref_number(match, n);
1441 backref_number_check(match, i);
1443 if (RMATCH_BEG(match, i) < 0)
1461 int i = match_backref_number(match, n);
1464 backref_number_check(match, i);
1466 if (RMATCH_BEG(match, i) < 0)
1468 return LONG2NUM(RMATCH_BEG(match, i));
1484 int i = match_backref_number(match, n);
1487 backref_number_check(match, i);
1489 if (RMATCH_BEG(match, i) < 0)
1491 return LONG2NUM(RMATCH_END(match, i));
1507 int i = match_backref_number(match, n);
1510 backref_number_check(match, i);
1512 if (RMATCH_BEG(match, i) < 0)
1515 update_char_offset(match);
1532 int i = match_backref_number(match, n);
1535 backref_number_check(match, i);
1537 if (RMATCH_BEG(match, i) < 0)
1540 update_char_offset(match);
1573 int i = match_backref_number(match, n);
1575 backref_number_check(match, i);
1577 long start = RMATCH_BEG(match, i), end = RMATCH_END(match, i);
1616 int i = match_backref_number(match, n);
1619 backref_number_check(match, i);
1621 if (RMATCH_BEG(match, i) < 0)
1624 update_char_offset(match);
1626 &
RMATCH(match)->char_offset[i];
1633 FL_SET(match, MATCH_BUSY);
1637rb_match_unbusy(
VALUE match)
1643rb_match_count(
VALUE match)
1645 if (
NIL_P(match))
return -1;
1646 return RMATCH_NREGS(match);
1650match_alloc_or_reuse(
VALUE existing,
int num_regs)
1656 if (!
NIL_P(existing) &&
1658 !
FL_TEST(existing, MATCH_BUSY) &&
1662 return match_alloc_n(
rb_cMatch, num_regs);
1672 OnigPosition beg = pos, end = pos +
len;
1673 match_set_regs(m, 1, &beg, &end);
1677rb_backref_set_string(
VALUE string,
long pos,
long len)
1680 match_set_string(match,
string, pos,
len);
1715rb_reg_fixed_encoding_p(
VALUE re)
1717 return RBOOL(
FL_TEST(re, KCODE_FIXED));
1721rb_reg_preprocess(
const char *p,
const char *end,
rb_encoding *enc,
1722 rb_encoding **fixed_enc, onig_errmsg_buffer err,
int options);
1730 "incompatible encoding regexp match (%s regexp with %s string)",
1731 rb_enc_inspect_name(rb_enc_get(re)),
1732 rb_enc_inspect_name(rb_enc_get(
str)));
1739 int cr = rb_enc_str_coderange(
str);
1742 rb_raise(rb_eArgError,
1743 "invalid byte sequence in %s",
1744 rb_enc_name(rb_enc_get(
str)));
1748 enc = rb_enc_get(
str);
1755 else if (!rb_enc_asciicompat(enc)) {
1756 reg_enc_error(re,
str);
1758 else if (rb_reg_fixed_encoding_p(re)) {
1761 reg_enc_error(re,
str);
1765 else if (warn && (
RBASIC(re)->flags & REG_ENCODING_NONE) &&
1766 enc != rb_ascii8bit_encoding() &&
1768 rb_warn(
"historical binary regexp match /.../n against %s string",
1784 if (reg->enc == enc)
return reg;
1789 const char *pattern = RSTRING_PTR(src_str);
1791 onig_errmsg_buffer err =
"";
1792 unescaped = rb_reg_preprocess(
1793 pattern, pattern + RSTRING_LEN(src_str), enc,
1794 &fixed_enc, err, 0);
1796 if (
NIL_P(unescaped)) {
1797 rb_raise(rb_eArgError,
"regexp preprocess failed: %s", err);
1801 rb_hrtime_t timelimit = reg->timelimit;
1808 if (ruby_single_main_ractor &&
RREGEXP(re)->usecnt == 0) {
1810 r = onig_new_without_alloc(&tmp_reg, (UChar *)ptr, (UChar *)(ptr +
len),
1812 OnigDefaultSyntax, &einfo);
1816 onig_free_body(&tmp_reg);
1819 onig_free_body(reg);
1825 r = onig_new(®, (UChar *)ptr, (UChar *)(ptr +
len),
1827 OnigDefaultSyntax, &einfo);
1831 onig_error_code_to_str((UChar*)err, r, &einfo);
1832 rb_reg_raise(err, re);
1835 reg->timelimit = timelimit;
1850 if (!tmpreg)
RREGEXP(re)->usecnt++;
1852 OnigPosition result = match(reg,
str, regs, args);
1854 if (!tmpreg)
RREGEXP(re)->usecnt--;
1863 case ONIGERR_TIMEOUT:
1864 rb_raise(rb_eRegexpTimeoutError,
"regexp match timeout");
1866 onig_errmsg_buffer err =
"";
1867 onig_error_code_to_str((UChar*)err, (
int)result);
1868 rb_reg_raise(err, re);
1883 enc = rb_reg_prepare_enc(re,
str, 0);
1889 range = RSTRING_LEN(
str) - pos;
1892 if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(
str)) {
1893 string = (UChar*)RSTRING_PTR(
str);
1896 p = onigenc_get_right_adjust_char_head(enc,
string,
string + pos,
string + RSTRING_LEN(
str));
1899 p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,
string,
string + pos,
string + RSTRING_LEN(
str));
1923 (UChar *)(ptr +
len),
1924 (UChar *)(ptr + args->pos),
1925 (UChar *)(ptr + args->range),
1932rb_reg_search_set_match(
VALUE re,
VALUE str,
long pos,
int reverse,
int set_backref_str,
VALUE *set_match)
1934 long len = RSTRING_LEN(str);
1935 if (pos >
len || pos < 0) {
1942 .range = reverse ? 0 :
len,
1950 int cap = n < ONIG_NREGION ? ONIG_NREGION : n;
1952 OnigPosition *buf =
ALLOCV_N(OnigPosition, regs_buf, (
size_t)cap * 2);
1960 OnigPosition result =
rb_reg_onig_match(re, str, reg_onig_search, &args, ®s);
1962 if (result == ONIG_MISMATCH) {
1965 return ONIG_MISMATCH;
1969 VALUE match = match_alloc_or_reuse(existing, regs.num_regs);
1971 match_set_regs(match, regs.num_regs, regs.beg, regs.end);
1974 if (set_backref_str) {
1988 if (set_match) *set_match = match;
1994rb_reg_search0(
VALUE re,
VALUE str,
long pos,
int reverse,
int set_backref_str,
VALUE *match)
1996 return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, match);
2002 return rb_reg_search_set_match(re, str, pos, reverse, 1, NULL);
2015 (UChar *)(ptr +
len),
2027 int cap = n < ONIG_NREGION ? ONIG_NREGION : n;
2029 OnigPosition *buf =
ALLOCV_N(OnigPosition, regs_buf, (
size_t)cap * 2);
2044 match_set_regs(match, regs.num_regs, regs.beg, regs.end);
2059 int num_regs = RMATCH_NREGS(match);
2060 if (nth >= num_regs) {
2065 if (nth <= 0)
return Qnil;
2067 return RBOOL(RMATCH_BEG(match, nth) != -1);
2074 long start, end,
len;
2078 int num_regs = RMATCH_NREGS(match);
2079 if (nth >= num_regs) {
2084 if (nth <= 0)
return Qnil;
2086 start = RMATCH_BEG(match, nth);
2087 if (start == -1)
return Qnil;
2088 end = RMATCH_END(match, nth);
2125 if (RMATCH_BEG(match, 0) == -1)
return Qnil;
2157 if (RMATCH_BEG(match, 0) == -1)
return Qnil;
2158 str =
RMATCH(match)->str;
2159 pos = RMATCH_END(match, 0);
2165match_last_index(
VALUE match)
2169 if (
NIL_P(match))
return -1;
2171 if (RMATCH_BEG(match, 0) == -1)
return -1;
2173 for (i = RMATCH_NREGS(match) - 1; RMATCH_BEG(match, i) == -1 && i > 0; i--)
2181 int i = match_last_index(match);
2182 if (i <= 0)
return Qnil;
2183 long start = RMATCH_BEG(match, i);
2188rb_reg_last_defined(
VALUE match)
2190 int i = match_last_index(match);
2191 if (i < 0)
return Qnil;
2196last_match_getter(
ID _x,
VALUE *_y)
2202prematch_getter(
ID _x,
VALUE *_y)
2208postmatch_getter(
ID _x,
VALUE *_y)
2214last_paren_match_getter(
ID _x,
VALUE *_y)
2220match_array(
VALUE match,
int start)
2227 int num_regs = RMATCH_NREGS(match);
2229 target =
RMATCH(match)->str;
2231 for (i = start; i < num_regs; i++) {
2232 long beg = RMATCH_BEG(match, i);
2260match_to_a(
VALUE match)
2262 return match_array(match, 0);
2282match_captures(
VALUE match)
2284 return match_array(match, 1);
2288name_to_backref_number(
const struct re_registers *regs,
VALUE regexp,
const char* name,
const char* name_end)
2290 if (
NIL_P(regexp))
return -1;
2291 return onig_name_to_backref_number(
RREGEXP_PTR(regexp),
2292 (
const unsigned char *)name, (
const unsigned char *)name_end, regs);
2295#define NAME_TO_NUMBER(regs, re, name, name_ptr, name_end) \
2297 !rb_enc_compatible(RREGEXP_SRC(re), (name)) ? 0 : \
2298 name_to_backref_number((regs), (re), (name_ptr), (name_end)))
2301match_name_to_backref_number(
VALUE match,
VALUE name)
2304 if (
NIL_P(regexp))
return -1;
2307 int n = onig_name_to_group_numbers(
RREGEXP_PTR(regexp),
2308 (
const unsigned char *)RSTRING_PTR(name),
2310 if (n < 0)
return n;
2311 if (n == 0)
return ONIGERR_PARSER_BUG;
2312 if (n == 1)
return nums[0];
2313 for (
int i = n - 1; i >= 0; i--) {
2314 if (RMATCH_BEG(match, nums[i]) != ONIG_REGION_NOTPOS)
2321namev_to_backref_number(
VALUE match,
VALUE name)
2337 num = match_name_to_backref_number(match, name);
2340 name_to_backref_error(name);
2346match_ary_subseq(
VALUE match,
long beg,
long len,
VALUE result)
2348 long olen = RMATCH_NREGS(match);
2349 long j, end = olen < beg+
len ? olen : beg+
len;
2351 if (
len == 0)
return result;
2353 for (j = beg; j < end; j++) {
2356 if (beg +
len > j) {
2366 int num_regs = RMATCH_NREGS(match);
2377 return match_ary_subseq(match, beg,
len, result);
2420match_aref(
int argc,
VALUE *argv,
VALUE match)
2427 if (
NIL_P(length)) {
2432 int num = namev_to_backref_number(match, idx);
2437 return match_ary_aref(match, idx,
Qnil);
2444 long num_regs = RMATCH_NREGS(match);
2450 if (beg < 0)
return Qnil;
2452 else if (beg > num_regs) {
2455 if (beg+
len > num_regs) {
2456 len = num_regs - beg;
2458 return match_ary_subseq(match, beg,
len,
Qnil);
2489match_values_at(
int argc,
VALUE *argv,
VALUE match)
2497 for (i=0; i<argc; i++) {
2502 int num = namev_to_backref_number(match, argv[i]);
2507 match_ary_aref(match, argv[i], result);
2534match_to_s(
VALUE match)
2549match_named_captures_iter(
const OnigUChar *name,
const OnigUChar *name_end,
2550 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
2553 VALUE hash = data->hash;
2554 VALUE match = data->match;
2556 VALUE key = rb_enc_str_new((
const char *)name, name_end-name, regex->enc);
2558 if (data->symbolize) {
2567 for (i = 0; i < back_num; i++) {
2570 rb_hash_aset(hash, key, value);
2576 rb_hash_aset(hash, key,
Qnil);
2615match_named_captures(
int argc,
VALUE *argv,
VALUE match)
2621 return rb_hash_new();
2624 int symbolize_names = 0;
2629 static ID keyword_ids[1];
2631 VALUE symbolize_names_val;
2633 if (!keyword_ids[0]) {
2636 rb_get_kwargs(opt, keyword_ids, 0, 1, &symbolize_names_val);
2637 if (!UNDEF_P(symbolize_names_val) &&
RTEST(symbolize_names_val)) {
2638 symbolize_names = 1;
2642 hash = rb_hash_new();
2645 onig_foreach_name(
RREGEXP_PTR(
RMATCH(match)->regexp), match_named_captures_iter, &data);
2667match_deconstruct_keys(
VALUE match,
VALUE keys)
2675 return rb_hash_new();
2683 onig_foreach_name(
RREGEXP_PTR(
RMATCH(match)->regexp), match_named_captures_iter, &data);
2691 return rb_hash_new();
2704 int num = match_name_to_backref_number(match, name);
2731match_string(
VALUE match)
2734 return RMATCH(match)->str;
2743match_inspect_name_iter(
const OnigUChar *name,
const OnigUChar *name_end,
2744 int back_num,
int *back_refs,
OnigRegex regex,
void *arg0)
2749 for (i = 0; i < back_num; i++) {
2750 arg[back_refs[i]].name = name;
2751 arg[back_refs[i]].len = name_end - name;
2778match_inspect(
VALUE match)
2783 int num_regs = RMATCH_NREGS(match);
2789 return rb_sprintf(
"#<%"PRIsVALUE
":%p>", cname, (
void*)match);
2791 else if (
NIL_P(regexp)) {
2792 return rb_sprintf(
"#<%"PRIsVALUE
": %"PRIsVALUE
">",
2800 match_inspect_name_iter, names);
2805 for (i = 0; i < num_regs; i++) {
2812 rb_str_catf(str,
"%d", i);
2831read_escaped_byte(
const char **pp,
const char *end, onig_errmsg_buffer err)
2833 const char *p = *pp;
2835 int meta_prefix = 0, ctrl_prefix = 0;
2838 if (p == end || *p++ !=
'\\') {
2839 errcpy(err,
"too short escaped multibyte character");
2845 errcpy(err,
"too short escape sequence");
2849 case '\\': code =
'\\';
break;
2850 case 'n': code =
'\n';
break;
2851 case 't': code =
'\t';
break;
2852 case 'r': code =
'\r';
break;
2853 case 'f': code =
'\f';
break;
2854 case 'v': code =
'\013';
break;
2855 case 'a': code =
'\007';
break;
2856 case 'e': code =
'\033';
break;
2859 case '0':
case '1':
case '2':
case '3':
2860 case '4':
case '5':
case '6':
case '7':
2869 errcpy(err,
"invalid hex escape");
2877 errcpy(err,
"duplicate meta escape");
2881 if (p+1 < end && *p++ ==
'-' && (*p & 0x80) == 0) {
2891 errcpy(err,
"too short meta escape");
2895 if (p == end || *p++ !=
'-') {
2896 errcpy(err,
"too short control escape");
2901 errcpy(err,
"duplicate control escape");
2905 if (p < end && (*p & 0x80) == 0) {
2915 errcpy(err,
"too short control escape");
2919 errcpy(err,
"unexpected escape sequence");
2922 if (code < 0 || 0xff < code) {
2923 errcpy(err,
"invalid escape code");
2937unescape_escaped_nonascii(
const char **pp,
const char *end,
rb_encoding *enc,
2940 const char *p = *pp;
2942 unsigned char *area =
ALLOCA_N(
unsigned char, chmaxlen);
2943 char *chbuf = (
char *)area;
2948 memset(chbuf, 0, chmaxlen);
2950 byte = read_escaped_byte(&p, end, err);
2955 area[chlen++] = byte;
2956 while (chlen < chmaxlen &&
2958 byte = read_escaped_byte(&p, end, err);
2962 area[chlen++] = byte;
2965 l = rb_enc_precise_mbclen(chbuf, chbuf+chlen, enc);
2967 errcpy(err,
"invalid multibyte escape");
2970 if (1 < chlen || (area[0] & 0x80)) {
2975 else if (*encp != enc) {
2976 errcpy(err,
"escaped non ASCII character in UTF-8 regexp");
2982 snprintf(escbuf,
sizeof(escbuf),
"\\x%02X", area[0]&0xff);
2990check_unicode_range(
unsigned long code, onig_errmsg_buffer err)
2992 if ((0xd800 <= code && code <= 0xdfff) ||
2994 errcpy(err,
"invalid Unicode range");
3001append_utf8(
unsigned long uv,
3004 if (check_unicode_range(uv, err) != 0)
3008 snprintf(escbuf,
sizeof(escbuf),
"\\x%02X", (
int)uv);
3018 *encp = rb_utf8_encoding();
3019 else if (*encp != rb_utf8_encoding()) {
3020 errcpy(err,
"UTF-8 character in non UTF-8 regexp");
3028unescape_unicode_list(
const char **pp,
const char *end,
3031 const char *p = *pp;
3032 int has_unicode = 0;
3036 while (p < end &&
ISSPACE(*p)) p++;
3039 code = ruby_scan_hex(p, end-p, &
len);
3043 errcpy(err,
"invalid Unicode range");
3047 if (append_utf8(code, buf, encp, err) != 0)
3051 while (p < end &&
ISSPACE(*p)) p++;
3054 if (has_unicode == 0) {
3055 errcpy(err,
"invalid Unicode list");
3065unescape_unicode_bmp(
const char **pp,
const char *end,
3068 const char *p = *pp;
3073 errcpy(err,
"invalid Unicode escape");
3076 code = ruby_scan_hex(p, 4, &
len);
3078 errcpy(err,
"invalid Unicode escape");
3081 if (append_utf8(code, buf, encp, err) != 0)
3088unescape_nonascii0(
const char **pp,
const char *end,
rb_encoding *enc,
3090 onig_errmsg_buffer err,
int options,
int recurse)
3092 const char *p = *pp;
3095 int in_char_class = 0;
3097 int extended_mode = options & ONIG_OPTION_EXTEND;
3101 int chlen = rb_enc_precise_mbclen(p, end, enc);
3104 errcpy(err,
"invalid multibyte character");
3108 if (1 < chlen || (*p & 0x80)) {
3114 else if (*encp != enc) {
3115 errcpy(err,
"non ASCII character in UTF-8 regexp");
3124 errcpy(err,
"too short escape sequence");
3127 chlen = rb_enc_precise_mbclen(p, end, enc);
3129 goto invalid_multibyte;
3138 case '1':
case '2':
case '3':
3139 case '4':
case '5':
case '6':
case '7':
3141 size_t len = end-(p-1), octlen;
3142 if (ruby_scan_oct(p-1,
len < 3 ?
len : 3, &octlen) <= 0177) {
3158 if (rb_is_usascii_enc(enc)) {
3159 const char *pbeg = p;
3160 int byte = read_escaped_byte(&p, end, err);
3161 if (
byte == -1)
return -1;
3166 if (unescape_escaped_nonascii(&p, end, enc, buf, encp, err) != 0)
3173 errcpy(err,
"too short escape sequence");
3179 if (unescape_unicode_list(&p, end, buf, encp, err) != 0)
3181 if (p == end || *p++ !=
'}') {
3182 errcpy(err,
"invalid Unicode list");
3189 if (unescape_unicode_bmp(&p, end, buf, encp, err) != 0)
3211 if (extended_mode && !in_char_class) {
3213 while ((p < end) && ((c = *p++) !=
'\n')) {
3214 if ((c & 0x80) && !*encp && enc == rb_utf8_encoding()) {
3227 if (in_char_class) {
3234 if (!in_char_class && recurse) {
3235 if (--parens == 0) {
3242 if (!in_char_class && p + 1 < end && *p ==
'?') {
3243 if (*(p+1) ==
'#') {
3245 const char *orig_p = p;
3248 while (cont && (p < end)) {
3251 if (!(c & 0x80))
break;
3252 if (!*encp && enc == rb_utf8_encoding()) {
3258 chlen = rb_enc_precise_mbclen(p, end, enc);
3260 goto invalid_multibyte;
3281 int local_extend = 0;
3288 for (s = p+1; s < end; s++) {
3291 local_extend = invert ? -1 : 1;
3298 if (local_extend == 0 ||
3299 (local_extend == -1 && !extended_mode) ||
3300 (local_extend == 1 && extended_mode)) {
3307 int local_options = options;
3308 if (local_extend == 1) {
3309 local_options |= ONIG_OPTION_EXTEND;
3312 local_options &= ~ONIG_OPTION_EXTEND;
3316 int ret = unescape_nonascii0(&p, end, enc, buf, encp,
3319 if (ret < 0)
return ret;
3324 extended_mode = local_extend == 1;
3341 else if (!in_char_class && recurse) {
3359unescape_nonascii(
const char *p,
const char *end,
rb_encoding *enc,
3361 onig_errmsg_buffer err,
int options)
3363 return unescape_nonascii0(&p, end, enc, buf, encp, has_property,
3368rb_reg_preprocess(
const char *p,
const char *end,
rb_encoding *enc,
3369 rb_encoding **fixed_enc, onig_errmsg_buffer err,
int options)
3372 int has_property = 0;
3376 if (rb_enc_asciicompat(enc))
3380 rb_enc_associate(buf, enc);
3383 if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err, options) != 0)
3386 if (has_property && !*fixed_enc) {
3391 rb_enc_associate(buf, *fixed_enc);
3398rb_reg_check_preprocess(
VALUE str)
3401 onig_errmsg_buffer err =
"";
3407 p = RSTRING_PTR(str);
3408 end = p + RSTRING_LEN(str);
3409 enc = rb_enc_get(str);
3411 buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err, 0);
3415 return rb_reg_error_desc(str, 0, err);
3421rb_reg_preprocess_dregexp(
VALUE ary,
int options)
3425 onig_errmsg_buffer err =
"";
3431 rb_raise(rb_eArgError,
"no arguments given");
3440 src_enc = rb_enc_get(str);
3441 if (options & ARG_ENCODING_NONE &&
3442 src_enc != ascii8bit) {
3444 rb_raise(
rb_eRegexpError,
"/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
3446 src_enc = ascii8bit;
3450 p = RSTRING_PTR(str);
3451 end = p + RSTRING_LEN(str);
3453 buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err, options);
3456 rb_raise(rb_eArgError,
"%s", err);
3458 if (fixed_enc != 0) {
3459 if (regexp_enc != 0 && regexp_enc != fixed_enc) {
3460 rb_raise(
rb_eRegexpError,
"encoding mismatch in dynamic regexp : %s and %s",
3461 rb_enc_name(regexp_enc), rb_enc_name(fixed_enc));
3463 regexp_enc = fixed_enc;
3472 rb_enc_associate(result, regexp_enc);
3479rb_reg_initialize_check(
VALUE obj)
3481 rb_check_frozen(obj);
3489 int options, onig_errmsg_buffer err,
3490 const char *sourcefile,
int sourceline)
3497 rb_reg_initialize_check(obj);
3499 if (rb_enc_dummy_p(enc)) {
3500 errcpy(err,
"can't make regexp with dummy encoding");
3504 unescaped = rb_reg_preprocess(s, s+
len, enc, &fixed_enc, err, options);
3505 if (
NIL_P(unescaped))
3509 if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) ||
3510 (fixed_enc != a_enc && (options & ARG_ENCODING_NONE))) {
3511 errcpy(err,
"incompatible character encoding");
3514 if (fixed_enc != a_enc) {
3515 options |= ARG_ENCODING_FIXED;
3519 else if (!(options & ARG_ENCODING_FIXED)) {
3520 enc = rb_usascii_encoding();
3523 rb_enc_associate((
VALUE)re, enc);
3524 if ((options & ARG_ENCODING_FIXED) || fixed_enc) {
3527 if (options & ARG_ENCODING_NONE) {
3531 bool success = make_regexp(
RREGEXP_PTR(obj), RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc,
3532 options & ARG_REG_OPTION_MASK, err,
3533 sourcefile, sourceline);
3534 if (!success)
return -1;
3549 if (regenc != enc) {
3551 str = rb_enc_associate(dup, enc = regenc);
3553 str = rb_fstring(str);
3558rb_reg_initialize_str(
VALUE obj,
VALUE str,
int options, onig_errmsg_buffer err,
3559 const char *sourcefile,
int sourceline)
3562 rb_encoding *str_enc = rb_enc_get(str), *enc = str_enc;
3563 if (options & ARG_ENCODING_NONE) {
3565 if (enc != ascii8bit) {
3567 errcpy(err,
"/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
3573 ret = rb_reg_initialize(obj, RSTRING_PTR(str), RSTRING_LEN(str), enc,
3574 options, err, sourcefile, sourceline);
3575 if (ret == 0) reg_set_source(obj, str, str_enc);
3580rb_reg_s_alloc(
VALUE klass)
3600 return rb_reg_init_str(rb_reg_alloc(), s, options);
3604rb_reg_init_str(
VALUE re,
VALUE s,
int options)
3606 onig_errmsg_buffer err =
"";
3608 if (rb_reg_initialize_str(re, s, options, err, NULL, 0) != 0) {
3609 rb_reg_raise_str(s, options, err);
3618 onig_errmsg_buffer err =
"";
3620 if (rb_reg_initialize(re, RSTRING_PTR(s), RSTRING_LEN(s),
3621 enc, options, err, NULL, 0) != 0) {
3622 rb_reg_raise_str(s, options, err);
3624 reg_set_source(re, s, enc);
3630rb_reg_new_from_values(
long cnt,
const VALUE *elements,
int opt)
3632 const VALUE ary = rb_ary_tmp_new_from_values(0, cnt, elements);
3641 VALUE re = rb_reg_alloc();
3642 onig_errmsg_buffer err =
"";
3644 if (rb_reg_initialize(re, s,
len, enc, options, err, NULL, 0) != 0) {
3645 rb_enc_reg_raise(s,
len, enc, options, err);
3659rb_reg_compile(
VALUE str,
int options,
const char *sourcefile,
int sourceline)
3661 VALUE re = rb_reg_alloc();
3662 onig_errmsg_buffer err =
"";
3665 if (rb_reg_initialize_str(re, str, options, err, sourcefile, sourceline) != 0) {
3666 rb_set_errinfo(rb_reg_error_desc(str, options, err));
3672static VALUE reg_cache;
3677 if (rb_ractor_main_p()) {
3680 && memcmp(
RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
3690static st_index_t reg_hash(
VALUE re);
3702rb_reg_hash(
VALUE re)
3704 st_index_t hashval = reg_hash(re);
3737 if (re1 == re2)
return Qtrue;
3739 rb_reg_check(re1); rb_reg_check(re2);
3767match_hash(
VALUE match)
3773 hashval =
rb_hash_uint(hashval, reg_hash(match_regexp(match)));
3774 int num_regs = RMATCH_NREGS(match);
3794 if (match1 == match2)
return Qtrue;
3798 if (!rb_reg_equal(match_regexp(match1), match_regexp(match2)))
return Qfalse;
3799 int num_regs = RMATCH_NREGS(match1);
3800 if (num_regs != RMATCH_NREGS(match2))
return Qfalse;
3801 if (memcmp(RMATCH_BEG_PTR(match1), RMATCH_BEG_PTR(match2), num_regs *
sizeof(OnigPosition)))
return Qfalse;
3802 if (memcmp(RMATCH_END_PTR(match1), RMATCH_END_PTR(match2), num_regs *
sizeof(OnigPosition)))
return Qfalse;
3841match_integer_at(
int argc,
VALUE *argv,
VALUE match)
3853 else if ((nth = namev_to_backref_number(match, idx)) < 0) {
3854 name_to_backref_error(idx);
3857 if (argc > 1 && (base =
NUM2INT(argv[1])) < 0) {
3858 rb_raise(rb_eArgError,
"invalid radix %d", base);
3861 if (nth >= RMATCH_NREGS(match))
return Qnil;
3862 if (nth < 0 && (nth += RMATCH_NREGS(match)) <= 0)
return Qnil;
3864 long start = RMATCH_BEG(match, nth), end = RMATCH_END(match, nth);
3865 if (start < 0)
return Qnil;
3866 RUBY_ASSERT(start <= end, "%ld > %ld
", start, end);
3868 VALUE str = RMATCH(match)->str;
3869 RUBY_ASSERT(end <= RSTRING_LEN(str), "%ld > %ld
", end, RSTRING_LEN(str));
3872 return rb_int_parse_cstr(RSTRING_PTR(str) + start, end - start, &endp, NULL,
3873 base, RB_INT_PARSE_DEFAULT);
3877reg_operand(VALUE s, int check)
3880 return rb_sym2str(s);
3882 else if (RB_TYPE_P(s, T_STRING)) {
3886 return check ? rb_str_to_str(s) : rb_check_string_type(s);
3891reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match)
3896 rb_backref_set(Qnil);
3899 *strp = str = reg_operand(str, TRUE);
3902 VALUE l = rb_str_length(str);
3905 rb_backref_set(Qnil);
3909 pos = rb_str_offset(str, pos);
3911 return rb_reg_search_set_match(re, str, pos, 0, 1, set_match);
3916 * self =~ other -> integer or nil
3918 * Returns the integer index (in characters) of the first match
3919 * for +self+ and +other+, or +nil+ if none;
3920 * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables].
3922 * /at/ =~ 'input data' # => 7
3923 * $~ # => #<MatchData "at
">
3924 * /ax/ =~ 'input data' # => nil
3927 * Assigns named captures to local variables of the same names
3928 * if and only if +self+:
3930 * - Is a regexp literal;
3931 * see {Regexp Literals}[rdoc-ref:syntax/literals.rdoc@Regexp+Literals].
3932 * - Does not contain interpolations;
3933 * see {Regexp interpolation}[rdoc-ref:Regexp@Interpolation+Mode].
3934 * - Is at the left of the expression.
3938 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = y '
3942 * Assigns +nil+ if not matched:
3944 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = '
3948 * Does not make local variable assignments if +self+ is not a regexp literal:
3950 * r = /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
3952 * p foo # Undefined local variable
3953 * p bar # Undefined local variable
3955 * The assignment does not occur if the regexp is not at the left:
3957 * ' x = y ' =~ /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
3958 * p foo, foo # Undefined local variables
3960 * A regexp interpolation, <tt>#{}</tt>, also disables
3964 * /(?<foo>\w+)\s*=\s*#{r}/ =~ 'x = y'
3965 * p foo # Undefined local variable
3970rb_reg_match(VALUE re, VALUE str)
3972 long pos = reg_match_pos(re, &str, 0, NULL);
3973 if (pos < 0) return Qnil;
3974 pos = rb_str_sublen(str, pos);
3975 return LONG2FIX(pos);
3980 * self === other -> true or false
3982 * Returns whether +self+ finds a match in +other+:
3984 * /^[a-z]*$/ === 'HELLO' # => false
3985 * /^[A-Z]*$/ === 'HELLO' # => true
3987 * This method is called in case statements:
3991 * when /\A[a-z]*\z/; print "Lower
case\n
"
3992 * when /\A[A-Z]*\z/; print "Upper
case\n
"
3993 * else print "Mixed
case\n
"
3994 * end # => "Upper
case"
3999rb_reg_eqq(VALUE re, VALUE str)
4003 str = reg_operand(str, FALSE);
4005 rb_backref_set(Qnil);
4008 start = rb_reg_search(re, str, 0, 0);
4009 return RBOOL(start >= 0);
4015 * ~ rxp -> integer or nil
4017 * Equivalent to <tt><i>rxp</i> =~ $_</tt>:
4025rb_reg_match2(VALUE re)
4028 VALUE line = rb_lastline_get();
4030 if (!RB_TYPE_P(line, T_STRING)) {
4031 rb_backref_set(Qnil);
4035 start = rb_reg_search(re, line, 0, 0);
4039 start = rb_str_sublen(line, start);
4040 return LONG2FIX(start);
4046 * match(string, offset = 0) -> matchdata or nil
4047 * match(string, offset = 0) {|matchdata| ... } -> object
4049 * With no block given, returns the MatchData object
4050 * that describes the match, if any, or +nil+ if none;
4051 * the search begins at the given character +offset+ in +string+:
4053 * /abra/.match('abracadabra') # => #<MatchData "abra
">
4054 * /abra/.match('abracadabra', 4) # => #<MatchData "abra
">
4055 * /abra/.match('abracadabra', 8) # => nil
4056 * /abra/.match('abracadabra', 800) # => nil
4058 * string = "\u{5d0 5d1 5e8 5d0}cadabra
"
4059 * /abra/.match(string, 7) #=> #<MatchData "abra
">
4060 * /abra/.match(string, 8) #=> nil
4061 * /abra/.match(string.b, 8) #=> #<MatchData "abra
">
4063 * With a block given, calls the block if and only if a match is found;
4064 * returns the block's value:
4066 * /abra/.match('abracadabra') {|matchdata| p matchdata }
4067 * # => #<MatchData "abra
">
4068 * /abra/.match('abracadabra', 4) {|matchdata| p matchdata }
4069 * # => #<MatchData "abra
">
4070 * /abra/.match('abracadabra', 8) {|matchdata| p matchdata }
4072 * /abra/.match('abracadabra', 8) {|marchdata| fail 'Cannot happen' }
4075 * Output (from the first two blocks above):
4077 * #<MatchData "abra
">
4078 * #<MatchData "abra
">
4080 * /(.)(.)(.)/.match("abc
")[2] # => "b
"
4081 * /(.)(.)/.match("abc
", 1)[2] # => "c
"
4086rb_reg_match_m(int argc, VALUE *argv, VALUE re)
4088 VALUE result = Qnil, str, initpos;
4091 if (rb_scan_args(argc, argv, "11
", &str, &initpos) == 2) {
4092 pos = NUM2LONG(initpos);
4098 pos = reg_match_pos(re, &str, pos, &result);
4102 rb_match_busy(result);
4103 if (!NIL_P(result) && rb_block_given_p()) {
4104 return rb_yield(result);
4111 * match?(string) -> true or false
4112 * match?(string, offset = 0) -> true or false
4114 * Returns <code>true</code> or <code>false</code> to indicate whether the
4115 * regexp is matched or not without updating $~ and other related variables.
4116 * If the second parameter is present, it specifies the position in the string
4117 * to begin the search.
4119 * /R.../.match?("Ruby
") # => true
4120 * /R.../.match?("Ruby
", 1) # => false
4121 * /P.../.match?("Ruby
") # => false
4126rb_reg_match_m_p(int argc, VALUE *argv, VALUE re)
4128 long pos = rb_check_arity(argc, 1, 2) > 1 ? NUM2LONG(argv[1]) : 0;
4129 return rb_reg_match_p(re, argv[0], pos);
4133rb_reg_match_p(VALUE re, VALUE str, long pos)
4135 if (NIL_P(str)) return Qfalse;
4136 str = SYMBOL_P(str) ? rb_sym2str(str) : StringValue(str);
4139 pos += NUM2LONG(rb_str_length(str));
4140 if (pos < 0) return Qfalse;
4144 const char *beg = rb_str_subpos(str, pos, &len);
4145 if (!beg) return Qfalse;
4146 pos = beg - RSTRING_PTR(str);
4150 struct reg_onig_search_args args = {
4152 .range = RSTRING_LEN(str),
4155 return rb_reg_onig_match(re, str, reg_onig_search, &args, NULL) == ONIG_MISMATCH ? Qfalse : Qtrue;
4159 * Document-method: compile
4161 * Alias for Regexp.new
4165str_to_option(VALUE str)
4170 str = rb_check_string_type(str);
4171 if (NIL_P(str)) return -1;
4172 RSTRING_GETMEM(str, ptr, len);
4173 for (long i = 0; i < len; ++i) {
4174 int f = char_to_option(ptr[i]);
4176 rb_raise(rb_eArgError, "unknown regexp option: %
"PRIsVALUE, str);
4184set_timeout(rb_hrtime_t *hrt, VALUE timeout)
4186 double timeout_d = NIL_P(timeout) ? 0.0 : NUM2DBL(timeout);
4187 if (!NIL_P(timeout) && !(timeout_d > 0)) {
4188 rb_raise(rb_eArgError, "invalid timeout: %
"PRIsVALUE, timeout);
4190 double2hrtime(hrt, timeout_d);
4194reg_copy(VALUE copy, VALUE orig)
4197 rb_reg_initialize_check(copy);
4198 if ((r = onig_reg_copy_body(RREGEXP_PTR(copy), RREGEXP_PTR(orig))) != 0) {
4199 /* ONIGERR_MEMORY only */
4200 rb_raise(rb_eRegexpError, "%s
", onig_error_code_to_format(r));
4202 FL_SET_RAW(copy, RREGEXP_INITIALIZED);
4204 RB_OBJ_WRITE(copy, &RREGEXP(copy)->src, RREGEXP(orig)->src);
4205 RREGEXP_PTR(copy)->timelimit = RREGEXP_PTR(orig)->timelimit;
4206 rb_enc_copy(copy, orig);
4207 FL_SET_RAW(copy, FL_TEST_RAW(orig, KCODE_FIXED|REG_ENCODING_NONE));
4208 if (RBASIC_CLASS(copy) == rb_cRegexp) {
4215struct reg_init_args {
4222static VALUE reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args);
4223static VALUE reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags);
4227 * Regexp.new(string, options = 0, timeout: nil) -> regexp
4228 * Regexp.new(regexp, timeout: nil) -> regexp
4230 * With argument +string+ given, returns a new regexp with the given string
4233 * r = Regexp.new('foo') # => /foo/
4234 * r.source # => "foo
"
4237 * Optional argument +options+ is one of the following:
4239 * - A String of options:
4241 * Regexp.new('foo', 'i') # => /foo/i
4242 * Regexp.new('foo', 'im') # => /foo/im
4244 * - The bit-wise OR of one or more of the constants
4245 * Regexp::EXTENDED, Regexp::IGNORECASE, Regexp::MULTILINE, and
4246 * Regexp::NOENCODING:
4248 * Regexp.new('foo', Regexp::IGNORECASE) # => /foo/i
4249 * Regexp.new('foo', Regexp::EXTENDED) # => /foo/x
4250 * Regexp.new('foo', Regexp::MULTILINE) # => /foo/m
4251 * Regexp.new('foo', Regexp::NOENCODING) # => /foo/n
4252 * flags = Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE
4253 * Regexp.new('foo', flags) # => /foo/mix
4255 * - +nil+ or +false+, which is ignored.
4256 * - Any other truthy value, in which case the regexp will be
4259 * If optional keyword argument +timeout+ is given,
4260 * its float value overrides the timeout interval for the class,
4262 * If +nil+ is passed as +timeout, it uses the timeout interval
4263 * for the class, Regexp.timeout.
4265 * With argument +regexp+ given, returns a new regexp. The source,
4266 * options, timeout are the same as +regexp+. +options+ and +n_flag+
4267 * arguments are ineffective. The timeout can be overridden by
4268 * +timeout+ keyword.
4270 * options = Regexp::MULTILINE
4271 * r = Regexp.new('foo', options, timeout: 1.1) # => /foo/m
4272 * r2 = Regexp.new(r) # => /foo/m
4273 * r2.timeout # => 1.1
4274 * r3 = Regexp.new(r, timeout: 3.14) # => /foo/m
4275 * r3.timeout # => 3.14
4280rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
4282 struct reg_init_args args;
4283 VALUE re = reg_extract_args(argc, argv, &args);
4286 reg_init_args(self, args.str, args.enc, args.flags);
4292 set_timeout(&RREGEXP_PTR(self)->timelimit, args.timeout);
4293 if (RBASIC_CLASS(self) == rb_cRegexp) {
4301reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args)
4304 rb_encoding *enc = 0;
4305 VALUE str, src, opts = Qundef, kwargs;
4308 rb_scan_args(argc, argv, "11:
", &src, &opts, &kwargs);
4310 args->timeout = Qnil;
4311 if (!NIL_P(kwargs)) {
4312 static ID keywords[1];
4314 keywords[0] = rb_intern_const("timeout
");
4316 rb_get_kwargs(kwargs, keywords, 0, 1, &args->timeout);
4319 if (RB_TYPE_P(src, T_REGEXP)) {
4323 rb_warn("flags ignored
");
4326 flags = rb_reg_options(re);
4327 str = RREGEXP_SRC(re);
4332 if (FIXNUM_P(opts)) flags = FIX2INT(opts);
4333 else if ((f = str_to_option(opts)) >= 0) flags = f;
4334 else if (rb_bool_expected(opts, "ignorecase
", FALSE))
4335 flags = ONIG_OPTION_IGNORECASE;
4337 str = StringValue(src);
4341 args->flags = flags;
4346reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags)
4348 if (enc && rb_enc_get(str) != enc)
4349 rb_reg_init_str_enc(self, str, enc, flags);
4351 rb_reg_init_str(self, str, flags);
4356rb_reg_quote(VALUE str)
4358 rb_encoding *enc = rb_enc_get(str);
4362 int ascii_only = rb_enc_str_asciionly_p(str);
4364 s = RSTRING_PTR(str);
4365 send = s + RSTRING_LEN(str);
4367 c = rb_enc_ascget(s, send, &clen, enc);
4369 s += mbclen(s, send, enc);
4373 case '[': case ']': case '{': case '}':
4374 case '(': case ')': case '|': case '-':
4375 case '*': case '.': case '\\':
4376 case '?': case '+': case '^': case '$':
4378 case '\t': case '\f': case '\v': case '\n': case '\r':
4383 tmp = rb_str_new3(str);
4385 rb_enc_associate(tmp, rb_usascii_encoding());
4390 tmp = rb_str_new(0, RSTRING_LEN(str)*2);
4392 rb_enc_associate(tmp, rb_usascii_encoding());
4395 rb_enc_copy(tmp, str);
4397 t = RSTRING_PTR(tmp);
4398 /* copy upto metacharacter */
4399 const char *p = RSTRING_PTR(str);
4400 memcpy(t, p, s - p);
4404 c = rb_enc_ascget(s, send, &clen, enc);
4406 int n = mbclen(s, send, enc);
4414 case '[': case ']': case '{': case '}':
4415 case '(': case ')': case '|': case '-':
4416 case '*': case '.': case '\\':
4417 case '?': case '+': case '^': case '$':
4419 t += rb_enc_mbcput('\\', t, enc);
4422 t += rb_enc_mbcput('\\', t, enc);
4423 t += rb_enc_mbcput(' ', t, enc);
4426 t += rb_enc_mbcput('\\', t, enc);
4427 t += rb_enc_mbcput('t', t, enc);
4430 t += rb_enc_mbcput('\\', t, enc);
4431 t += rb_enc_mbcput('n', t, enc);
4434 t += rb_enc_mbcput('\\', t, enc);
4435 t += rb_enc_mbcput('r', t, enc);
4438 t += rb_enc_mbcput('\\', t, enc);
4439 t += rb_enc_mbcput('f', t, enc);
4442 t += rb_enc_mbcput('\\', t, enc);
4443 t += rb_enc_mbcput('v', t, enc);
4446 t += rb_enc_mbcput(c, t, enc);
4448 rb_str_resize(tmp, t - RSTRING_PTR(tmp));
4455 * Regexp.escape(string) -> new_string
4457 * Returns a new string that escapes any characters
4458 * that have special meaning in a regular expression:
4460 * s = Regexp.escape('\*?{}.') # => "\\\\\\*\\?\\{\\}\\.
"
4462 * For any string +s+, this call returns a MatchData object:
4464 * r = Regexp.new(Regexp.escape(s)) # => /\\\\\\\*\\\?\\\{\\\}\\\./
4465 * r.match(s) # => #<MatchData "\\\\\\*\\?\\{\\}\\.
">
4470rb_reg_s_quote(VALUE c, VALUE str)
4472 return rb_reg_quote(reg_operand(str, TRUE));
4476rb_reg_options(VALUE re)
4481 options = RREGEXP_PTR(re)->options & ARG_REG_OPTION_MASK;
4482 if (RBASIC(re)->flags & KCODE_FIXED) options |= ARG_ENCODING_FIXED;
4483 if (RBASIC(re)->flags & REG_ENCODING_NONE) options |= ARG_ENCODING_NONE;
4488rb_check_regexp_type(VALUE re)
4490 return rb_check_convert_type(re, T_REGEXP, "Regexp
", "to_regexp
");
4495 * Regexp.try_convert(object) -> regexp or nil
4497 * Returns +object+ if it is a regexp:
4499 * Regexp.try_convert(/re/) # => /re/
4501 * Otherwise if +object+ responds to <tt>:to_regexp</tt>,
4502 * calls <tt>object.to_regexp</tt> and returns the result.
4504 * Returns +nil+ if +object+ does not respond to <tt>:to_regexp</tt>.
4506 * Regexp.try_convert('re') # => nil
4508 * Raises an exception unless <tt>object.to_regexp</tt> returns a regexp.
4512rb_reg_s_try_convert(VALUE dummy, VALUE re)
4514 return rb_check_regexp_type(re);
4518rb_reg_s_union(VALUE self, VALUE args0)
4520 long argc = RARRAY_LEN(args0);
4524 args[0] = rb_str_new2("(?!)
");
4525 return rb_class_new_instance(1, args, rb_cRegexp);
4527 else if (argc == 1) {
4528 VALUE arg = rb_ary_entry(args0, 0);
4529 VALUE re = rb_check_regexp_type(arg);
4534 quoted = rb_reg_s_quote(Qnil, arg);
4535 return rb_reg_new_str(quoted, 0);
4540 VALUE source = rb_str_buf_new(0);
4541 rb_encoding *result_enc;
4543 int has_asciionly = 0;
4544 rb_encoding *has_ascii_compat_fixed = 0;
4545 rb_encoding *has_ascii_incompat = 0;
4547 for (i = 0; i < argc; i++) {
4549 VALUE e = rb_ary_entry(args0, i);
4552 rb_str_buf_cat_ascii(source, "|
");
4554 v = rb_check_regexp_type(e);
4556 rb_encoding *enc = rb_enc_get(v);
4557 if (!rb_enc_asciicompat(enc)) {
4558 if (!has_ascii_incompat)
4559 has_ascii_incompat = enc;
4560 else if (has_ascii_incompat != enc)
4561 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
4562 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
4564 else if (rb_reg_fixed_encoding_p(v)) {
4565 if (!has_ascii_compat_fixed)
4566 has_ascii_compat_fixed = enc;
4567 else if (has_ascii_compat_fixed != enc)
4568 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
4569 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
4574 v = rb_reg_str_with_term(v, -1);
4579 enc = rb_enc_get(e);
4580 if (!rb_enc_asciicompat(enc)) {
4581 if (!has_ascii_incompat)
4582 has_ascii_incompat = enc;
4583 else if (has_ascii_incompat != enc)
4584 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
4585 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
4587 else if (rb_enc_str_asciionly_p(e)) {
4591 if (!has_ascii_compat_fixed)
4592 has_ascii_compat_fixed = enc;
4593 else if (has_ascii_compat_fixed != enc)
4594 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
4595 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
4597 v = rb_reg_s_quote(Qnil, e);
4599 if (has_ascii_incompat) {
4600 if (has_asciionly) {
4601 rb_raise(rb_eArgError, "ASCII incompatible encoding: %s
",
4602 rb_enc_name(has_ascii_incompat));
4604 if (has_ascii_compat_fixed) {
4605 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
4606 rb_enc_name(has_ascii_incompat), rb_enc_name(has_ascii_compat_fixed));
4611 rb_enc_copy(source, v);
4613 rb_str_append(source, v);
4616 if (has_ascii_incompat) {
4617 result_enc = has_ascii_incompat;
4619 else if (has_ascii_compat_fixed) {
4620 result_enc = has_ascii_compat_fixed;
4623 result_enc = rb_ascii8bit_encoding();
4626 rb_enc_associate(source, result_enc);
4627 return rb_class_new_instance(1, &source, rb_cRegexp);
4633 * Regexp.union(*patterns) -> regexp
4634 * Regexp.union(array_of_patterns) -> regexp
4636 * Returns a regexp that is the union of the given patterns:
4638 * r = Regexp.union(%w[cat dog]) # => /cat|dog/
4639 * r.match('cat') # => #<MatchData "cat
">
4640 * r.match('dog') # => #<MatchData "dog
">
4641 * r.match('cog') # => nil
4643 * Each string pattern is escaped so that it is matched literally:
4645 * Regexp.union('penzance') # => /penzance/
4646 * Regexp.union('a+b*c') # => /a\+b\*c/
4647 * Regexp.union('skiing', 'sledding') # => /skiing|sledding/
4648 * Regexp.union(['skiing', 'sledding']) # => /skiing|sledding/
4650 * For each pattern that is a regexp, it is used as is,
4651 * including its flags:
4653 * Regexp.union(/foo/i, /bar/m, /baz/x)
4654 * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
4655 * Regexp.union([/foo/i, /bar/m, /baz/x])
4656 * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
4658 * With no arguments, returns <tt>/(?!)/</tt>:
4660 * Regexp.union # => /(?!)/
4662 * If any regexp pattern contains captures, the behavior is unspecified.
4666rb_reg_s_union_m(VALUE self, VALUE args)
4669 if (RARRAY_LEN(args) == 1 &&
4670 !NIL_P(v = rb_check_array_type(rb_ary_entry(args, 0)))) {
4671 return rb_reg_s_union(self, v);
4673 return rb_reg_s_union(self, args);
4678 * Regexp.linear_time?(re)
4679 * Regexp.linear_time?(string, options = 0)
4681 * Returns +true+ if matching against <tt>re</tt> can be
4682 * done in linear time to the input string.
4684 * Regexp.linear_time?(/re/) # => true
4686 * Note that this is a property of the ruby interpreter, not of the argument
4687 * regular expression. Identical regexp can or cannot run in linear time
4688 * depending on your ruby binary. Neither forward nor backward compatibility
4689 * is guaranteed about the return value of this method. Our current algorithm
4690 * is (*1) but this is subject to change in the future. Alternative
4691 * implementations can also behave differently. They might always return
4692 * false for everything.
4694 * (*1): https://doi.org/10.1109/SP40001.2021.00032
4698rb_reg_s_linear_time_p(int argc, VALUE *argv, VALUE self)
4700 struct reg_init_args args;
4701 VALUE re = reg_extract_args(argc, argv, &args);
4704 re = reg_init_args(rb_reg_alloc(), args.str, args.enc, args.flags);
4707 return RBOOL(onig_check_linear_time(RREGEXP_PTR(re)));
4712rb_reg_init_copy(VALUE copy, VALUE re)
4714 if (!OBJ_INIT_COPY(copy, re)) return copy;
4716 return reg_copy(copy, re);
4720do_regsub(VALUE str, VALUE src, VALUE regexp, int num_regs, const OnigPosition *beg, const OnigPosition *end)
4725 rb_encoding *str_enc = rb_enc_get(str);
4726 rb_encoding *src_enc = rb_enc_get(src);
4727 int acompat = rb_enc_asciicompat(str_enc);
4729#define ASCGET(s,e,cl) (acompat ? (*(cl)=1,ISASCII((s)[0])?(s)[0]:-1) : rb_enc_ascget((s), (e), (cl), str_enc))
4731 RSTRING_GETMEM(str, s, n);
4736 int c = ASCGET(s, e, &clen);
4740 s += mbclen(s, e, str_enc);
4746 if (c != '\\' || s == e) continue;
4749 val = rb_str_buf_new(ss-p);
4751 rb_enc_str_buf_cat(val, p, ss-p, str_enc);
4753 c = ASCGET(s, e, &clen);
4755 s += mbclen(s, e, str_enc);
4756 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
4764 case '1': case '2': case '3': case '4':
4765 case '5': case '6': case '7': case '8': case '9':
4766 if (!NIL_P(regexp) && onig_noname_group_capture_is_active(RREGEXP_PTR(regexp))) {
4775 if (s < e && ASCGET(s, e, &clen) == '<') {
4776 char *name, *name_end;
4778 name_end = name = s + clen;
4779 while (name_end < e) {
4780 c = ASCGET(name_end, e, &clen);
4781 if (c == '>') break;
4782 name_end += c == -1 ? mbclen(name_end, e, str_enc) : clen;
4785 VALUE n = rb_str_subseq(str, (long)(name - RSTRING_PTR(str)),
4786 (long)(name_end - name));
4787 struct re_registers tmp = {
4788 .allocated = num_regs,
4789 .num_regs = num_regs,
4790 .beg = (OnigPosition *)beg,
4791 .end = (OnigPosition *)end,
4793 if ((no = NAME_TO_NUMBER(&tmp, regexp, n, name, name_end)) < 1) {
4794 name_to_backref_error(n);
4796 p = s = name_end + clen;
4800 rb_raise(rb_eRuntimeError, "invalid group name reference format
");
4804 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
4813 rb_enc_str_buf_cat(val, RSTRING_PTR(src), beg[0], src_enc);
4817 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+end[0], RSTRING_LEN(src)-end[0], src_enc);
4822 while (beg[no] == -1 && no > 0) no--;
4823 if (no == 0) continue;
4827 rb_enc_str_buf_cat(val, s-clen, clen, str_enc);
4831 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
4836 if (no >= num_regs) continue;
4837 if (beg[no] == -1) continue;
4838 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+beg[no], end[no]-beg[no], src_enc);
4842 if (!val) return str;
4844 rb_enc_str_buf_cat(val, p, e-p, str_enc);
4852rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
4854 return do_regsub(str, src, regexp, regs->num_regs, regs->beg, regs->end);
4858rb_reg_regsub_match(VALUE str, VALUE src, VALUE match)
4860 return do_regsub(str, src, RMATCH(match)->regexp,
4861 RMATCH_NREGS(match), RMATCH_BEG_PTR(match), RMATCH_END_PTR(match));
4865ignorecase_getter(ID _x, VALUE *_y)
4867 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective
");
4872ignorecase_setter(VALUE val, ID id, VALUE *_)
4874 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective; ignored
");
4880 VALUE match = rb_backref_get();
4882 if (NIL_P(match)) return Qnil;
4883 rb_match_busy(match);
4888get_LAST_MATCH_INFO(ID _x, VALUE *_y)
4890 return match_getter();
4894match_setter(VALUE val, ID _x, VALUE *_y)
4897 Check_Type(val, T_MATCH);
4899 rb_backref_set(val);
4904 * Regexp.last_match -> matchdata or nil
4905 * Regexp.last_match(n) -> string or nil
4906 * Regexp.last_match(name) -> string or nil
4908 * With no argument, returns the value of <tt>$~</tt>,
4909 * which is the result of the most recent pattern match
4910 * (see {Regexp global variables}[rdoc-ref:Regexp@Global+Variables]):
4912 * /c(.)t/ =~ 'cat' # => 0
4913 * Regexp.last_match # => #<MatchData "cat
" 1:"a
">
4914 * /a/ =~ 'foo' # => nil
4915 * Regexp.last_match # => nil
4917 * With non-negative integer argument +n+, returns the _n_th field in the
4918 * matchdata, if any, or nil if none:
4920 * /c(.)t/ =~ 'cat' # => 0
4921 * Regexp.last_match(0) # => "cat
"
4922 * Regexp.last_match(1) # => "a
"
4923 * Regexp.last_match(2) # => nil
4925 * With negative integer argument +n+, counts backwards from the last field:
4927 * Regexp.last_match(-1) # => "a
"
4929 * With string or symbol argument +name+,
4930 * returns the string value for the named capture, if any:
4932 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ 'var = val'
4933 * Regexp.last_match # => #<MatchData "var = val
" lhs:"var
"rhs:"val
">
4934 * Regexp.last_match(:lhs) # => "var
"
4935 * Regexp.last_match('rhs') # => "val
"
4936 * Regexp.last_match('foo') # Raises IndexError.
4941rb_reg_s_last_match(int argc, VALUE *argv, VALUE _)
4943 if (rb_check_arity(argc, 0, 1) == 1) {
4944 VALUE match = rb_backref_get();
4946 if (NIL_P(match)) return Qnil;
4947 n = match_backref_number(match, argv[0]);
4948 return rb_reg_nth_match(n, match);
4950 return match_getter();
4954re_warn(const char *s)
4959// This function is periodically called during regexp matching
4961rb_reg_timeout_p(regex_t *reg, void *end_time_)
4963 rb_hrtime_t *end_time = (rb_hrtime_t *)end_time_;
4965 if (*end_time == 0) {
4966 // This is the first time to check interrupts;
4967 // just measure the current time and determine the end time
4968 // if timeout is set.
4969 rb_hrtime_t timelimit = reg->timelimit;
4972 // no per-object timeout.
4973 timelimit = rb_reg_match_time_limit;
4977 *end_time = rb_hrtime_add(timelimit, rb_hrtime_now());
4980 // no timeout is set
4981 *end_time = RB_HRTIME_MAX;
4985 if (*end_time < rb_hrtime_now()) {
4986 // Timeout has exceeded
4996 * Regexp.timeout -> float or nil
4998 * It returns the current default timeout interval for Regexp matching in second.
4999 * +nil+ means no default timeout configuration.
5003rb_reg_s_timeout_get(VALUE dummy)
5005 double d = hrtime2double(rb_reg_match_time_limit);
5006 if (d == 0.0) return Qnil;
5012 * Regexp.timeout = float or nil
5014 * It sets the default timeout interval for Regexp matching in second.
5015 * +nil+ means no default timeout configuration.
5016 * This configuration is process-global. If you want to set timeout for
5017 * each Regexp, use +timeout+ keyword for <code>Regexp.new</code>.
5019 * Regexp.timeout = 1
5020 * /^a*b?a*$/ =~ "a
" * 100000 + "x
" #=> regexp match timeout (RuntimeError)
5024rb_reg_s_timeout_set(VALUE dummy, VALUE timeout)
5026 rb_ractor_ensure_main_ractor("can not access
Regexp.timeout from non-main Ractors
");
5028 set_timeout(&rb_reg_match_time_limit, timeout);
5035 * rxp.timeout -> float or nil
5037 * It returns the timeout interval for Regexp matching in second.
5038 * +nil+ means no default timeout configuration.
5040 * This configuration is per-object. The global configuration set by
5041 * Regexp.timeout= is ignored if per-object configuration is set.
5043 * re = Regexp.new("^a*b?a*$
", timeout: 1)
5044 * re.timeout #=> 1.0
5045 * re =~ "a
" * 100000 + "x
" #=> regexp match timeout (RuntimeError)
5049rb_reg_timeout_get(VALUE re)
5052 double d = hrtime2double(RREGEXP_PTR(re)->timelimit);
5053 if (d == 0.0) return Qnil;
5058 * Document-class: RegexpError
5060 * Raised when given an invalid regexp expression.
5064 * <em>raises the exception:</em>
5066 * RegexpError: target of repeat operator is not specified: /?/
5070 * Document-class: Regexp
5072 * :include: doc/_regexp.rdoc
5078 rb_eRegexpError = rb_define_class("RegexpError
", rb_eStandardError);
5080 onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
5081 onig_set_warn_func(re_warn);
5082 onig_set_verb_warn_func(re_warn);
5084 rb_define_virtual_variable("$~
", get_LAST_MATCH_INFO, match_setter);
5085 rb_define_virtual_variable("$&
", last_match_getter, 0);
5086 rb_define_virtual_variable("$`
", prematch_getter, 0);
5087 rb_define_virtual_variable("$
'", postmatch_getter, 0);
5088 rb_define_virtual_variable("$+", last_paren_match_getter, 0);
5090 rb_gvar_ractor_local("$~");
5091 rb_gvar_ractor_local("$&");
5092 rb_gvar_ractor_local("$`");
5093 rb_gvar_ractor_local("$'");
5094 rb_gvar_ractor_local("$+
");
5095 rb_gvar_box_dynamic("$~
");
5096 rb_gvar_box_ready("$&
");
5097 rb_gvar_box_ready("$`
");
5098 rb_gvar_box_ready("$
'");
5099 rb_gvar_box_ready("$+");
5101 rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
5103 rb_cRegexp = rb_define_class("Regexp", rb_cObject);
5104 rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
5105 rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance_pass_kw, -1);
5106 rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
5107 rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, 1);
5108 rb_define_singleton_method(rb_cRegexp, "union", rb_reg_s_union_m, -2);
5109 rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, -1);
5110 rb_define_singleton_method(rb_cRegexp, "try_convert", rb_reg_s_try_convert, 1);
5111 rb_define_singleton_method(rb_cRegexp, "linear_time?", rb_reg_s_linear_time_p, -1);
5113 rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1);
5114 rb_define_method(rb_cRegexp, "initialize_copy", rb_reg_init_copy, 1);
5115 rb_define_method(rb_cRegexp, "hash", rb_reg_hash, 0);
5116 rb_define_method(rb_cRegexp, "eql?", rb_reg_equal, 1);
5117 rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
5118 rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
5119 rb_define_method(rb_cRegexp, "===", rb_reg_eqq, 1);
5120 rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
5121 rb_define_method(rb_cRegexp, "match", rb_reg_match_m, -1);
5122 rb_define_method(rb_cRegexp, "match?", rb_reg_match_m_p, -1);
5123 rb_define_method(rb_cRegexp, "to_s", rb_reg_to_s, 0);
5124 rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
5125 rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
5126 rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
5127 rb_define_method(rb_cRegexp, "options", rb_reg_options_m, 0);
5128 rb_define_method(rb_cRegexp, "encoding", rb_obj_encoding, 0); /* in encoding.c */
5129 rb_define_method(rb_cRegexp, "fixed_encoding?", rb_reg_fixed_encoding_p, 0);
5130 rb_define_method(rb_cRegexp, "names", rb_reg_names, 0);
5131 rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
5132 rb_define_method(rb_cRegexp, "timeout", rb_reg_timeout_get, 0);
5134 /* Raised when regexp matching timed out. */
5135 rb_eRegexpTimeoutError = rb_define_class_under(rb_cRegexp, "TimeoutError", rb_eRegexpError);
5136 rb_define_singleton_method(rb_cRegexp, "timeout", rb_reg_s_timeout_get, 0);
5137 rb_define_singleton_method(rb_cRegexp, "timeout=", rb_reg_s_timeout_set, 1);
5139 /* see Regexp.options and Regexp.new */
5140 rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
5141 /* see Regexp.options and Regexp.new */
5142 rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(ONIG_OPTION_EXTEND));
5143 /* see Regexp.options and Regexp.new */
5144 rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(ONIG_OPTION_MULTILINE));
5145 /* see Regexp.options and Regexp.new */
5146 rb_define_const(rb_cRegexp, "FIXEDENCODING", INT2FIX(ARG_ENCODING_FIXED));
5147 /* see Regexp.options and Regexp.new */
5148 rb_define_const(rb_cRegexp, "NOENCODING", INT2FIX(ARG_ENCODING_NONE));
5150 rb_global_variable(®_cache);
5152 rb_cMatch = rb_define_class("MatchData", rb_cObject);
5153 rb_define_alloc_func(rb_cMatch, match_alloc);
5154 rb_undef_method(CLASS_OF(rb_cMatch), "new");
5155 rb_undef_method(CLASS_OF(rb_cMatch), "allocate");
5157 rb_define_method(rb_cMatch, "initialize_copy", rb_match_init_copy, 1);
5158 rb_define_method(rb_cMatch, "regexp", match_regexp, 0);
5159 rb_define_method(rb_cMatch, "names", match_names, 0);
5160 rb_define_method(rb_cMatch, "size", match_size, 0);
5161 rb_define_method(rb_cMatch, "length", match_size, 0);
5162 rb_define_method(rb_cMatch, "offset", match_offset, 1);
5163 rb_define_method(rb_cMatch, "byteoffset", match_byteoffset, 1);
5164 rb_define_method(rb_cMatch, "bytebegin", match_bytebegin, 1);
5165 rb_define_method(rb_cMatch, "byteend", match_byteend, 1);
5166 rb_define_method(rb_cMatch, "begin", match_begin, 1);
5167 rb_define_method(rb_cMatch, "end", match_end, 1);
5168 rb_define_method(rb_cMatch, "match", match_nth, 1);
5169 rb_define_method(rb_cMatch, "match_length", match_nth_length, 1);
5170 rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
5171 rb_define_method(rb_cMatch, "[]", match_aref, -1);
5172 rb_define_method(rb_cMatch, "captures", match_captures, 0);
5173 rb_define_alias(rb_cMatch, "deconstruct", "captures");
5174 rb_define_method(rb_cMatch, "named_captures", match_named_captures, -1);
5175 rb_define_method(rb_cMatch, "deconstruct_keys", match_deconstruct_keys, 1);
5176 rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
5177 rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
5178 rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
5179 rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
5180 rb_define_method(rb_cMatch, "inspect", match_inspect, 0);
5181 rb_define_method(rb_cMatch, "string", match_string, 0);
5182 rb_define_method(rb_cMatch, "hash", match_hash, 0);
5183 rb_define_method(rb_cMatch, "eql?", match_equal, 1);
5184 rb_define_method(rb_cMatch, "==", match_equal, 1);
5185 rb_define_method(rb_cMatch, "integer_at", match_integer_at, -1);
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
static bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc)
Identical to rb_isprint(), except it additionally takes an encoding.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
#define OBJ_INIT_COPY(obj, orig)
Old name of RB_OBJ_INIT_COPY.
#define ISSPACE
Old name of rb_isspace.
#define T_STRING
Old name of RUBY_T_STRING.
#define ENC_CODERANGE_CLEAN_P(cr)
Old name of RB_ENC_CODERANGE_CLEAN_P.
#define INT2FIX
Old name of RB_INT2FIX.
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ENC_CODERANGE_UNKNOWN
Old name of RUBY_ENC_CODERANGE_UNKNOWN.
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
#define FIX2INT
Old name of RB_FIX2INT.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define rb_str_new3
Old name of rb_str_new_shared.
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define FL_SET
Old name of RB_FL_SET.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
#define NUM2INT
Old name of RB_NUM2INT.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define scan_hex(s, l, e)
Old name of ruby_scan_hex.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
#define T_MATCH
Old name of RUBY_T_MATCH.
#define FL_TEST
Old name of RB_FL_TEST.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FL_UNSET
Old name of RB_FL_UNSET.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define scan_oct(s, l, e)
Old name of ruby_scan_oct.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define rb_str_new4
Old name of rb_str_new_frozen.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define T_REGEXP
Old name of RUBY_T_REGEXP.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_eRegexpError
RegexpError exception.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eEncCompatError
Encoding::CompatibilityError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_eIndexError
IndexError exception.
VALUE rb_obj_reveal(VALUE obj, VALUE klass)
Make a hidden object visible again.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_cMatch
MatchData class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_cRegexp
Regexp class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
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.
int rb_char_to_option_kcode(int c, int *option, int *kcode)
Converts a character option to its encoding.
static int rb_enc_mbmaxlen(rb_encoding *enc)
Queries the maximum number of bytes that the passed encoding needs to represent a character.
VALUE rb_enc_reg_new(const char *ptr, long len, rb_encoding *enc, int opts)
Identical to rb_reg_new(), except it additionally takes an encoding.
long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc)
Looks for the passed string in the passed buffer.
long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc)
Counts the number of characters of the passed string, according to the passed encoding.
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.
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.
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_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
int rb_uv_to_utf8(char buf[6], unsigned long uv)
Encodes a Unicode codepoint into its UTF-8 representation.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
void rb_backref_set(VALUE md)
Updates $~.
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
int rb_reg_backref_number(VALUE match, VALUE backref)
Queries the index of the given named capture.
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
VALUE rb_reg_last_match(VALUE md)
This just returns the argument, stringified.
void rb_match_busy(VALUE md)
Asserts that the given MatchData is "occupied".
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
VALUE rb_reg_match_post(VALUE md)
The portion of the original string after the given match.
VALUE rb_reg_nth_defined(int n, VALUE md)
Identical to rb_reg_nth_match(), except it just returns Boolean.
VALUE rb_reg_match_pre(VALUE md)
The portion of the original string before the given match.
VALUE rb_reg_new_str(VALUE src, int opts)
Identical to rb_reg_new(), except it takes the expression in Ruby's string instead of C's.
VALUE rb_reg_match_last(VALUE md)
The portion of the original string that captured at the very last.
VALUE rb_reg_new(const char *src, long len, int opts)
Creates a new Regular expression.
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
#define rb_hash_end(h)
Just another name of st_hash_end.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
#define rb_str_buf_cat
Just another name of rb_str_cat.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
long rb_reg_search(VALUE re, VALUE str, long pos, int dir)
Runs the passed regular expression over the passed string.
regex_t * rb_reg_prepare_re(VALUE re, VALUE str)
Exercises various checks and preprocesses so that the given regular expression can be applied to the ...
long rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int dir)
Tell us if this is a wrong idea, but it seems this function has no usage at all.
OnigPosition rb_reg_onig_match(VALUE re, VALUE str, OnigPosition(*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args), void *args, struct re_registers *regs)
Runs a regular expression match using function match.
VALUE rb_reg_regcomp(VALUE str)
Creates a new instance of rb_cRegexp.
VALUE rb_reg_quote(VALUE str)
Escapes any characters that would have special meaning in a regular expression.
int rb_reg_region_copy(struct re_registers *dst, const struct re_registers *src)
Duplicates a match data.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define RB_ALLOCV_N(type, v, n)
Allocates a memory region, possibly on stack.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define RB_ALLOCV_END(v)
Polite way to declare that the given array is not used any longer.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_AREF(a, i)
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define RBASIC(obj)
Convenient casting macro.
#define RMATCH(obj)
Convenient casting macro.
#define RREGEXP(obj)
Convenient casting macro.
static struct re_pattern_buffer * RREGEXP_PTR(VALUE rexp)
Convenient getter function.
static VALUE RREGEXP_SRC(VALUE rexp)
Convenient getter function.
static long RREGEXP_SRC_LEN(VALUE rexp)
Convenient getter function.
static char * RREGEXP_SRC_PTR(VALUE rexp)
Convenient getter function.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Ruby object's base components.
VALUE flags
Per-object flags.
Regular expression execution context.
VALUE regexp
The expression of this match.
union RMatch::@58 as
"Registers" of a match.
struct rmatch_offset * char_offset
Capture group offsets, in C array.
int char_offset_num_allocated
Number of rmatch_offset that ::rmatch::char_offset holds.
int num_regs
Number of capture-group registers.
int capa
Capacity of as.embed, in OnigPosition slots.
VALUE str
The target string that the match was made against.
Ruby's regular expression.
struct RBasic basic
Basic part, including flags and class.
const VALUE src
Source code of this expression.
unsigned long usecnt
Reference count.
Represents the region of a capture group.
long beg
Beginning of a group.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.