12#include "ruby/internal/config.h"
19#include "internal/bignum.h"
20#include "internal/encoding.h"
21#include "internal/error.h"
22#include "internal/gc.h"
23#include "internal/hash.h"
24#include "internal/imemo.h"
25#include "internal/re.h"
26#include "internal/string.h"
27#include "internal/object.h"
28#include "internal/ractor.h"
29#include "internal/variable.h"
35#include "ractor_core.h"
54#define KCODE_FIXED FL_USER4
55#define REG_ENCODING_NONE FL_USER6
68#define MATCH_BUSY FL_USER0
72typedef char onig_errmsg_buffer[ONIG_MAX_ERROR_MESSAGE_LEN];
73#define errcpy(err, msg) strlcpy((err), (msg), ONIG_MAX_ERROR_MESSAGE_LEN)
76static const char casetable[] = {
77 '\000',
'\001',
'\002',
'\003',
'\004',
'\005',
'\006',
'\007',
78 '\010',
'\011',
'\012',
'\013',
'\014',
'\015',
'\016',
'\017',
79 '\020',
'\021',
'\022',
'\023',
'\024',
'\025',
'\026',
'\027',
80 '\030',
'\031',
'\032',
'\033',
'\034',
'\035',
'\036',
'\037',
82 '\040',
'\041',
'\042',
'\043',
'\044',
'\045',
'\046',
'\047',
84 '\050',
'\051',
'\052',
'\053',
'\054',
'\055',
'\056',
'\057',
86 '\060',
'\061',
'\062',
'\063',
'\064',
'\065',
'\066',
'\067',
88 '\070',
'\071',
'\072',
'\073',
'\074',
'\075',
'\076',
'\077',
90 '\100',
'\141',
'\142',
'\143',
'\144',
'\145',
'\146',
'\147',
92 '\150',
'\151',
'\152',
'\153',
'\154',
'\155',
'\156',
'\157',
94 '\160',
'\161',
'\162',
'\163',
'\164',
'\165',
'\166',
'\167',
96 '\170',
'\171',
'\172',
'\133',
'\134',
'\135',
'\136',
'\137',
98 '\140',
'\141',
'\142',
'\143',
'\144',
'\145',
'\146',
'\147',
100 '\150',
'\151',
'\152',
'\153',
'\154',
'\155',
'\156',
'\157',
102 '\160',
'\161',
'\162',
'\163',
'\164',
'\165',
'\166',
'\167',
104 '\170',
'\171',
'\172',
'\173',
'\174',
'\175',
'\176',
'\177',
105 '\200',
'\201',
'\202',
'\203',
'\204',
'\205',
'\206',
'\207',
106 '\210',
'\211',
'\212',
'\213',
'\214',
'\215',
'\216',
'\217',
107 '\220',
'\221',
'\222',
'\223',
'\224',
'\225',
'\226',
'\227',
108 '\230',
'\231',
'\232',
'\233',
'\234',
'\235',
'\236',
'\237',
109 '\240',
'\241',
'\242',
'\243',
'\244',
'\245',
'\246',
'\247',
110 '\250',
'\251',
'\252',
'\253',
'\254',
'\255',
'\256',
'\257',
111 '\260',
'\261',
'\262',
'\263',
'\264',
'\265',
'\266',
'\267',
112 '\270',
'\271',
'\272',
'\273',
'\274',
'\275',
'\276',
'\277',
113 '\300',
'\301',
'\302',
'\303',
'\304',
'\305',
'\306',
'\307',
114 '\310',
'\311',
'\312',
'\313',
'\314',
'\315',
'\316',
'\317',
115 '\320',
'\321',
'\322',
'\323',
'\324',
'\325',
'\326',
'\327',
116 '\330',
'\331',
'\332',
'\333',
'\334',
'\335',
'\336',
'\337',
117 '\340',
'\341',
'\342',
'\343',
'\344',
'\345',
'\346',
'\347',
118 '\350',
'\351',
'\352',
'\353',
'\354',
'\355',
'\356',
'\357',
119 '\360',
'\361',
'\362',
'\363',
'\364',
'\365',
'\366',
'\367',
120 '\370',
'\371',
'\372',
'\373',
'\374',
'\375',
'\376',
'\377',
123# error >>> "You lose. You will need a translation table for your character set." <<<
127rb_hrtime_t rb_reg_match_time_limit = 0;
132 const unsigned char *p1 = x, *p2 = y;
136 if ((tmp = casetable[(
unsigned)*p1++] - casetable[(
unsigned)*p2++]))
142#if defined(HAVE_MEMMEM) && !defined(__APPLE__)
144rb_memsearch_ss(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
146 const unsigned char *y;
148 if ((y = memmem(ys, n, xs, m)) != NULL)
155rb_memsearch_ss(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
157 const unsigned char *x = xs, *xe = xs + m;
158 const unsigned char *y = ys, *ye = ys + n;
159#define VALUE_MAX ((VALUE)~(VALUE)0)
163 rb_bug(
"!!too long pattern string!!");
165 if (!(y = memchr(y, *x, n - m + 1)))
169 for (hx = *x++, hy = *y++; x < xe; ++x, ++y) {
189rb_memsearch_qs(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
191 const unsigned char *x = xs, *xe = xs + m;
192 const unsigned char *y = ys;
193 VALUE i, qstable[256];
196 for (i = 0; i < 256; ++i)
199 qstable[*x] = xe - x;
201 for (; y + m <= ys + n; y += *(qstable + y[m])) {
202 if (*xs == *y && memcmp(xs, y, m) == 0)
208static inline unsigned int
209rb_memsearch_qs_utf8_hash(
const unsigned char *x,
const unsigned char *e)
211 register const unsigned int mix = 8353;
212 register unsigned int h = *x;
216 else if (e - x < (h < 0xE0 ? 2 : h < 0xF0 ? 3 : 4)) {
240 return (
unsigned char)h;
244rb_memsearch_qs_utf8(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
246 const unsigned char *x = xs, *xe = xs + m;
247 const unsigned char *y = ys;
248 VALUE i, qstable[512];
251 for (i = 0; i < 512; ++i) {
254 for (; x < xe; ++x) {
255 qstable[rb_memsearch_qs_utf8_hash(x, xe)] = xe - x;
258 for (; y + m <= ys + n; y += qstable[rb_memsearch_qs_utf8_hash(y+m, ys+n)]) {
259 if (*xs == *y && memcmp(xs, y, m) == 0)
266rb_memsearch_with_char_size(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n,
int char_size)
268 const unsigned char *x = xs, x0 = *xs, *y = ys;
270 for (n -= m; n >= 0; n -= char_size, y += char_size) {
271 if (x0 == *y && memcmp(x+1, y+1, m-1) == 0)
278rb_memsearch_wchar(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
280 return rb_memsearch_with_char_size(xs, m, ys, n, 2);
284rb_memsearch_qchar(
const unsigned char *xs,
rb_len_t m,
const unsigned char *ys,
rb_len_t n)
286 return rb_memsearch_with_char_size(xs, m, ys, n, 4);
292 const unsigned char *x = x0, *y = y0;
294 if (m > n)
return -1;
296 return memcmp(x0, y0, m) == 0 ? 0 : -1;
302 const unsigned char *ys = memchr(y, *x, n);
309 else if (LIKELY(rb_enc_mbminlen(enc) == 1)) {
311 return rb_memsearch_ss(x0, m, y0, n);
313 else if (enc == rb_utf8_encoding()){
314 return rb_memsearch_qs_utf8(x0, m, y0, n);
317 else if (LIKELY(rb_enc_mbminlen(enc) == 2)) {
318 return rb_memsearch_wchar(x0, m, y0, n);
320 else if (LIKELY(rb_enc_mbminlen(enc) == 4)) {
321 return rb_memsearch_qchar(x0, m, y0, n);
323 return rb_memsearch_qs(x0, m, y0, n);
333 val = ONIG_OPTION_IGNORECASE;
336 val = ONIG_OPTION_EXTEND;
339 val = ONIG_OPTION_MULTILINE;
348enum { OPTBUF_SIZE = 4 };
351option_to_str(
char str[OPTBUF_SIZE],
int options)
354 if (options & ONIG_OPTION_MULTILINE) *p++ =
'm';
355 if (options & ONIG_OPTION_IGNORECASE) *p++ =
'i';
356 if (options & ONIG_OPTION_EXTEND) *p++ =
'x';
368 *kcode = rb_ascii8bit_encindex();
369 return (*option = ARG_ENCODING_NONE);
371 *kcode = ENCINDEX_EUC_JP;
374 *kcode = ENCINDEX_Windows_31J;
377 *kcode = rb_utf8_encindex();
381 return (*option = char_to_option(c));
383 *option = ARG_ENCODING_FIXED;
388reg_initialized_p(
VALUE re)
394rb_reg_check(
VALUE re)
396 if (!reg_initialized_p(re)) {
405 const char *p, *pend;
410 p = s; pend = p +
len;
414 c = rb_enc_ascget(p, pend, &clen, enc);
417 p += mbclen(p, pend, enc);
441 int unicode_p = rb_enc_unicode_p(enc);
444 c = rb_enc_ascget(p, pend, &clen, enc);
445 if (c ==
'\\' && p+clen < pend) {
446 int n = clen + mbclen(p+clen, pend, enc);
452 clen = rb_enc_precise_mbclen(p, pend, enc);
454 c = (
unsigned char)*p;
459 unsigned int c = rb_enc_mbc_to_codepoint(p, pend, enc);
460 rb_str_buf_cat_escaped_char(str, c, unicode_p);
467 else if (c == term) {
475 else if (!rb_enc_isspace(c, enc)) {
479 snprintf(b,
sizeof(b),
"\\x%02X", c);
495 rb_encoding *resenc = rb_default_internal_encoding();
496 if (resenc == NULL) resenc = rb_default_external_encoding();
498 if (re && rb_enc_asciicompat(enc)) {
499 rb_enc_copy(str, re);
502 rb_enc_associate(str, rb_usascii_encoding());
506 rb_reg_expr_str(str, RSTRING_PTR(src_str), RSTRING_LEN(src_str), enc, resenc,
'/');
511 char opts[OPTBUF_SIZE];
513 if (*option_to_str(opts,
RREGEXP_PTR(re)->options))
515 if (
RBASIC(re)->flags & REG_ENCODING_NONE)
541rb_reg_source(
VALUE re)
562rb_reg_inspect(
VALUE re)
564 if (!reg_initialized_p(re)) {
567 return rb_reg_desc(re);
570static VALUE rb_reg_str_with_term(
VALUE re,
int term);
602 return rb_reg_str_with_term(re,
'/');
606rb_reg_str_with_term(
VALUE re,
int term)
609 const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
611 char optbuf[OPTBUF_SIZE + 1];
616 rb_enc_copy(str, re);
619 const UChar *ptr = (UChar *)RSTRING_PTR(src_str);
622 if (
len >= 4 && ptr[0] ==
'(' && ptr[1] ==
'?') {
625 if ((
len -= 2) > 0) {
627 opt = char_to_option((
int )*ptr);
637 if (
len > 1 && *ptr ==
'-') {
641 opt = char_to_option((
int )*ptr);
656 if (*ptr ==
':' && ptr[
len-1] ==
')') {
663 err = onig_new(&rp, ptr, ptr +
len, options,
664 enc, OnigDefaultSyntax, NULL);
677 if ((options & embeddable) != embeddable) {
679 option_to_str(optbuf + 1, ~options);
684 if (rb_enc_asciicompat(enc)) {
685 rb_reg_expr_str(str, (
char*)ptr,
len, enc, NULL, term);
693 rb_enc_associate(str, rb_usascii_encoding());
697 s = RSTRING_PTR(str);
703 rb_str_resize(str, RSTRING_LEN(str) - n);
705 rb_reg_expr_str(str, (
char*)ptr,
len, enc, NULL, term);
708 rb_enc_copy(str, re);
715NORETURN(
static void rb_reg_raise(
const char *err,
VALUE re));
718rb_reg_raise(
const char *err,
VALUE re)
720 VALUE desc = rb_reg_desc(re);
728 char opts[OPTBUF_SIZE + 1];
730 rb_encoding *resenc = rb_default_internal_encoding();
731 if (resenc == NULL) resenc = rb_default_external_encoding();
733 rb_enc_associate(desc, enc);
735 rb_reg_expr_str(desc, s,
len, enc, resenc,
'/');
737 option_to_str(opts + 1, options);
742NORETURN(
static void rb_enc_reg_raise(
const char *s,
rb_len_t len,
rb_encoding *enc,
int options,
const char *err));
751rb_reg_error_desc(
VALUE str,
int options,
const char *err)
753 return rb_enc_reg_error_desc(RSTRING_PTR(str), RSTRING_LEN(str),
754 rb_enc_get(str), options, err);
757NORETURN(
static void rb_reg_raise_str(
VALUE str,
int options,
const char *err));
760rb_reg_raise_str(
VALUE str,
int options,
const char *err)
780rb_reg_casefold_p(
VALUE re)
783 return RBOOL(
RREGEXP_PTR(re)->options & ONIG_OPTION_IGNORECASE);
825rb_reg_options_m(
VALUE re)
832reg_names_iter(
const OnigUChar *name,
const OnigUChar *name_end,
833 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
836 rb_ary_push(ary, rb_enc_str_new((
const char *)name, name_end-name, regex->enc));
854rb_reg_names(
VALUE re)
859 onig_foreach_name(
RREGEXP_PTR(re), reg_names_iter, (
void*)ary);
864reg_named_captures_iter(
const OnigUChar *name,
const OnigUChar *name_end,
865 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
871 for (i = 0; i < back_num; i++)
874 rb_hash_aset(hash,
rb_str_new((
const char*)name, name_end-name),ary);
898rb_reg_named_captures(
VALUE re)
901 VALUE hash = rb_hash_new_capa(onig_number_of_names(reg));
902 onig_foreach_name(reg, reg_named_captures_iter, (
void*)hash);
907onig_new_with_source(
regex_t* reg,
const UChar* pattern,
const UChar* pattern_end,
909 OnigErrorInfo* einfo,
const char *sourcefile,
int sourceline)
913 if (IS_NULL(reg))
return ONIGERR_MEMORY;
915 r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax);
918 r = onig_compile_ruby(reg, pattern, pattern_end, einfo, sourcefile, sourceline);
928 const char *sourcefile,
int sourceline)
940 r = onig_new_with_source(rp, (UChar*)s, (UChar*)(s +
len), flags,
941 enc, OnigDefaultSyntax, &einfo, sourcefile, sourceline);
943 onig_error_code_to_str((UChar*)err, r, &einfo);
1107match_alloc_n(
VALUE klass,
int num_regs)
1109 int capa = num_regs * 2;
1110 size_t alloc_size = offsetof(
struct RMatch, as) +
sizeof(OnigPosition) *
capa;
1111 if (alloc_size <
sizeof(
struct RMatch)) {
1112 alloc_size =
sizeof(
struct RMatch);
1116 if (!rb_gc_size_allocatable_p(alloc_size)) {
1117 alloc_size =
sizeof(
struct RMatch);
1118 flags |= RMATCH_ONIG;
1122 NEWOBJ_OF(match,
struct RMatch, klass, flags, alloc_size);
1123 memset(((
char *)match) +
sizeof(
struct RBasic), 0, alloc_size -
sizeof(
struct RBasic));
1125 return (
VALUE)match;
1129match_alloc(
VALUE klass)
1131 return match_alloc_n(klass, 0);
1138 if (to->allocated)
return 0;
1141 if (to->allocated)
return 0;
1142 return ONIGERR_MEMORY;
1146match_to_onig(
VALUE match,
int num_regs,
const OnigPosition *src_beg,
const OnigPosition *src_end)
1150 if (onig_region_resize(&tmp, num_regs)) {
1153 memcpy(tmp.beg, src_beg, num_regs *
sizeof(OnigPosition));
1154 memcpy(tmp.end, src_end, num_regs *
sizeof(OnigPosition));
1160rb_match_ensure_onig(
VALUE match)
1165 match_to_onig(match, n, &rm->
as.embed[0], &rm->
as.embed[n]);
1172match_set_regs(
VALUE match,
int num_regs,
const OnigPosition *beg,
const OnigPosition *end)
1177 if (onig_region_resize(&rm->
as.onig,
num_regs)) {
1180 memcpy(rm->
as.onig.beg, beg,
num_regs *
sizeof(OnigPosition));
1181 memcpy(rm->
as.onig.end, end,
num_regs *
sizeof(OnigPosition));
1184 memcpy(&rm->
as.embed[0], beg,
num_regs *
sizeof(OnigPosition));
1188 match_to_onig(match,
num_regs, beg, end);
1197rb_match_blob_dump(
VALUE match,
VALUE *regexp_out,
VALUE *str_out,
int *num_regs_out,
bool release_source)
1201 *regexp_out = rm->
regexp;
1205 OnigPosition *blob =
ALLOC_N(OnigPosition, n ? 2 * n : 1);
1206 const OnigPosition *beg = RMATCH_BEG_PTR(match);
1207 const OnigPosition *end = RMATCH_END_PTR(match);
1208 for (
int i = 0; i < n; i++) {
1209 blob[2 * i] = beg[i];
1210 blob[2 * i + 1] = end[i];
1214 if (release_source) {
1216 onig_region_free(&rm->
as.onig, 0);
1217 memset(&rm->
as.onig, 0,
sizeof(rm->
as.onig));
1232 return match_alloc_n(klass,
num_regs);
1238 const OnigPosition *blob = blob_;
1245 for (
int i = 0; i <
num_regs; i++) {
1246 beg[i] = blob[2 * i];
1247 end[i] = blob[2 * i + 1];
1249 match_set_regs(match,
num_regs, beg, end);
1255rb_match_blob_free(
void *blob)
1266pair_byte_cmp(
const void *pair1,
const void *pair2)
1269#if SIZEOF_RB_LEN_T > SIZEOF_INT
1270 return diff ? diff > 0 ? 1 : -1 : 0;
1277update_char_offset(
VALUE match)
1310 if (RMATCH_BEG(match, i) < 0)
1312 pairs[num_pos++].byte_pos = RMATCH_BEG(match, i);
1313 pairs[num_pos++].byte_pos = RMATCH_END(match, i);
1315 qsort(pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1317 s = p = RSTRING_PTR(
RMATCH(match)->
str);
1319 for (i = 0; i < num_pos; i++) {
1320 q = s + pairs[i].byte_pos;
1322 pairs[i].char_pos = c;
1328 if (RMATCH_BEG(match, i) < 0) {
1334 key.byte_pos = RMATCH_BEG(match, i);
1335 found = bsearch(&key, pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1338 key.byte_pos = RMATCH_END(match, i);
1339 found = bsearch(&key, pairs, num_pos,
sizeof(
pair_t), pair_byte_cmp);
1347match_check(
VALUE match)
1366 match_set_regs(obj, RMATCH_NREGS(orig), RMATCH_BEG_PTR(orig), RMATCH_END_PTR(orig));
1402match_regexp(
VALUE match)
1433match_names(
VALUE match)
1459match_size(
VALUE match)
1462 return INT2FIX(RMATCH_NREGS(match));
1465static int match_name_to_backref_number(
VALUE match,
VALUE name);
1466NORETURN(
static void name_to_backref_error(
VALUE name));
1469name_to_backref_error(
VALUE name)
1471 rb_raise(
rb_eIndexError,
"undefined group name reference: % "PRIsVALUE,
1476backref_number_check(
VALUE match,
int i)
1478 if (i < 0 || RMATCH_NREGS(match) <= i)
1483match_backref_number(
VALUE match,
VALUE backref)
1495 num = match_name_to_backref_number(match, backref);
1498 name_to_backref_error(backref);
1507 return match_backref_number(match, backref);
1561 int i = match_backref_number(match, n);
1564 backref_number_check(match, i);
1566 if (RMATCH_BEG(match, i) < 0)
1569 update_char_offset(match);
1622 int i = match_backref_number(match, n);
1625 backref_number_check(match, i);
1627 if (RMATCH_BEG(match, i) < 0)
1681 int i = match_backref_number(match, n);
1684 backref_number_check(match, i);
1686 if (RMATCH_BEG(match, i) < 0)
1688 return LEN2NUM(RMATCH_BEG(match, i));
1741 int i = match_backref_number(match, n);
1744 backref_number_check(match, i);
1746 if (RMATCH_BEG(match, i) < 0)
1748 return LEN2NUM(RMATCH_END(match, i));
1800 int i = match_backref_number(match, n);
1803 backref_number_check(match, i);
1805 if (RMATCH_BEG(match, i) < 0)
1808 update_char_offset(match);
1860 int i = match_backref_number(match, n);
1863 backref_number_check(match, i);
1865 if (RMATCH_BEG(match, i) < 0)
1868 update_char_offset(match);
1943 int i = match_backref_number(match, n);
1945 backref_number_check(match, i);
1947 rb_len_t start = RMATCH_BEG(match, i), end = RMATCH_END(match, i);
2004 int i = match_backref_number(match, n);
2007 backref_number_check(match, i);
2009 if (RMATCH_BEG(match, i) < 0)
2012 update_char_offset(match);
2014 &
RMATCH(match)->char_offset[i];
2021 FL_SET(match, MATCH_BUSY);
2025rb_match_unbusy(
VALUE match)
2031rb_match_count(
VALUE match)
2033 if (
NIL_P(match))
return -1;
2034 return RMATCH_NREGS(match);
2038match_alloc_or_reuse(
VALUE existing,
int num_regs)
2044 if (!
NIL_P(existing) &&
2046 !
FL_TEST(existing, MATCH_BUSY) &&
2050 return match_alloc_n(
rb_cMatch, num_regs);
2060 OnigPosition beg = pos, end = pos +
len;
2061 match_set_regs(m, 1, &beg, &end);
2068 match_set_string(match,
string, pos,
len);
2103rb_reg_fixed_encoding_p(
VALUE re)
2105 return RBOOL(
FL_TEST(re, KCODE_FIXED));
2109rb_reg_preprocess(
const char *p,
const char *end,
rb_encoding *enc,
2110 rb_encoding **fixed_enc, onig_errmsg_buffer err,
int options);
2118 "incompatible encoding regexp match (%s regexp with %s string)",
2119 rb_enc_inspect_name(rb_enc_get(re)),
2120 rb_enc_inspect_name(rb_enc_get(
str)));
2127 int cr = rb_enc_str_coderange(
str);
2130 rb_raise(rb_eArgError,
2131 "invalid byte sequence in %s",
2132 rb_enc_name(rb_enc_get(
str)));
2136 enc = rb_enc_get(
str);
2143 else if (!rb_enc_asciicompat(enc)) {
2144 reg_enc_error(re,
str);
2146 else if (rb_reg_fixed_encoding_p(re)) {
2149 reg_enc_error(re,
str);
2153 else if (warn && (
RBASIC(re)->flags & REG_ENCODING_NONE) &&
2154 enc != rb_ascii8bit_encoding() &&
2156 rb_warn(
"historical binary regexp match /.../n against %s string",
2165 for (; variant; variant = variant->next) {
2166 if (variant->reg.enc == enc)
return &variant->reg;
2181 if (reg->enc == enc)
return reg;
2184 regex_t *cached = reg_find_encoding(head, enc);
2185 if (cached && !caller_owned)
return cached;
2188 const char *pattern = RSTRING_PTR(src_str);
2190 onig_errmsg_buffer err =
"";
2191 unescaped = rb_reg_preprocess(
2192 pattern, pattern + RSTRING_LEN(src_str), enc,
2193 &fixed_enc, err, reg->options);
2195 if (
NIL_P(unescaped)) {
2196 rb_raise(rb_eArgError,
"regexp preprocess failed: %s", err);
2200 rb_hrtime_t timelimit = reg->timelimit;
2207 r = onig_new_without_alloc(&variant->reg, (UChar *)ptr, (UChar *)(ptr +
len),
2208 reg->options, enc, OnigDefaultSyntax, &einfo);
2211 onig_free_body(&variant->reg);
2212 SIZED_FREE(variant);
2213 onig_error_code_to_str((UChar*)err, r, &einfo);
2214 rb_reg_raise(err, re);
2217 reg = &variant->reg;
2218 reg->timelimit = timelimit;
2220 rb_bug(
"group count mismatch in the recompiled regexp: %d != %d", reg->num_mem,
RREGEXP_PTR(re)->num_mem);
2225 reg = malloc(
sizeof(
regex_t));
2227 onig_free_body(&variant->reg);
2228 SIZED_FREE(variant);
2231 *reg = variant->reg;
2232 SIZED_FREE(variant);
2240 variant->next = head;
2242 if (previous == head)
break;
2245 cached = reg_find_encoding(head, enc);
2248 onig_free_body(&variant->reg);
2249 SIZED_FREE(variant);
2266 return reg_prepare_re(re, str,
true);
2274 regex_t *reg = reg_prepare_re(re, str,
false);
2276 OnigPosition result = match(reg, str, regs, args);
2284 case ONIGERR_TIMEOUT:
2285 rb_raise(rb_eRegexpTimeoutError,
"regexp match timeout");
2287 onig_errmsg_buffer err =
"";
2288 onig_error_code_to_str((UChar*)err, (
int)result);
2289 rb_reg_raise(err, re);
2304 enc = rb_reg_prepare_enc(re, str, 0);
2310 range = RSTRING_LEN(str) - pos;
2313 if (pos > 0 && ONIGENC_MBC_MAXLEN(enc) != 1 && pos < RSTRING_LEN(str)) {
2314 string = (UChar*)RSTRING_PTR(str);
2317 p = onigenc_get_right_adjust_char_head(enc,
string,
string + pos,
string + RSTRING_LEN(str));
2320 p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,
string,
string + pos,
string + RSTRING_LEN(str));
2344 (UChar *)(ptr +
len),
2345 (UChar *)(ptr + args->pos),
2346 (UChar *)(ptr + args->range),
2356 if (pos >
len || pos < 0) {
2363 .range = reverse ? 0 :
len,
2371 int cap = n < ONIG_NREGION ? ONIG_NREGION : n;
2373 OnigPosition *buf =
ALLOCV_N(OnigPosition, regs_buf, (
size_t)cap * 2);
2381 OnigPosition result =
rb_reg_onig_match(re, str, reg_onig_search, &args, ®s);
2383 if (result == ONIG_MISMATCH) {
2386 return ONIG_MISMATCH;
2390 VALUE match = match_alloc_or_reuse(existing, regs.num_regs);
2392 match_set_regs(match, regs.num_regs, regs.beg, regs.end);
2395 if (set_backref_str) {
2409 if (set_match) *set_match = match;
2417 return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, match);
2423 return rb_reg_search_set_match(re, str, pos, reverse, 1, NULL);
2436 (UChar *)(ptr +
len),
2448 int cap = n < ONIG_NREGION ? ONIG_NREGION : n;
2450 OnigPosition *buf =
ALLOCV_N(OnigPosition, regs_buf, (
size_t)cap * 2);
2465 match_set_regs(match, regs.num_regs, regs.beg, regs.end);
2480 int num_regs = RMATCH_NREGS(match);
2481 if (nth >= num_regs) {
2486 if (nth <= 0)
return Qnil;
2488 return RBOOL(RMATCH_BEG(match, nth) != -1);
2499 int num_regs = RMATCH_NREGS(match);
2500 if (nth >= num_regs) {
2505 if (nth <= 0)
return Qnil;
2507 start = RMATCH_BEG(match, nth);
2508 if (start == -1)
return Qnil;
2509 end = RMATCH_END(match, nth);
2548 if (RMATCH_BEG(match, 0) == -1)
return Qnil;
2581 if (RMATCH_BEG(match, 0) == -1)
return Qnil;
2582 str =
RMATCH(match)->str;
2583 pos = RMATCH_END(match, 0);
2589match_last_index(
VALUE match)
2593 if (
NIL_P(match))
return -1;
2595 if (RMATCH_BEG(match, 0) == -1)
return -1;
2597 for (i = RMATCH_NREGS(match) - 1; RMATCH_BEG(match, i) == -1 && i > 0; i--)
2605 int i = match_last_index(match);
2606 if (i <= 0)
return Qnil;
2607 rb_len_t start = RMATCH_BEG(match, i);
2612rb_reg_last_defined(
VALUE match)
2614 int i = match_last_index(match);
2615 if (i < 0)
return Qnil;
2620last_match_getter(
ID _x,
VALUE *_y)
2626prematch_getter(
ID _x,
VALUE *_y)
2632postmatch_getter(
ID _x,
VALUE *_y)
2638last_paren_match_getter(
ID _x,
VALUE *_y)
2644match_array(
VALUE match,
int start)
2651 int num_regs = RMATCH_NREGS(match);
2653 target =
RMATCH(match)->str;
2655 for (i = start; i < num_regs; i++) {
2656 rb_len_t beg = RMATCH_BEG(match, i);
2687match_to_a(
VALUE match)
2689 return match_array(match, 0);
2715match_captures(
VALUE match)
2717 return match_array(match, 1);
2721name_to_backref_number(
const struct re_registers *regs,
VALUE regexp,
const char* name,
const char* name_end)
2723 if (
NIL_P(regexp))
return -1;
2724 return onig_name_to_backref_number(
RREGEXP_PTR(regexp),
2725 (
const unsigned char *)name, (
const unsigned char *)name_end, regs);
2728#define NAME_TO_NUMBER(regs, re, name, name_ptr, name_end) \
2730 !rb_enc_compatible(RREGEXP_SRC(re), (name)) ? 0 : \
2731 name_to_backref_number((regs), (re), (name_ptr), (name_end)))
2734match_name_to_backref_number(
VALUE match,
VALUE name)
2737 if (
NIL_P(regexp))
return -1;
2740 int n = onig_name_to_group_numbers(
RREGEXP_PTR(regexp),
2741 (
const unsigned char *)RSTRING_PTR(name),
2743 if (n < 0)
return n;
2744 if (n == 0)
return ONIGERR_PARSER_BUG;
2745 if (n == 1)
return nums[0];
2746 for (
int i = n - 1; i >= 0; i--) {
2747 if (RMATCH_BEG(match, nums[i]) != ONIG_REGION_NOTPOS)
2754namev_to_backref_number(
VALUE match,
VALUE name)
2770 num = match_name_to_backref_number(match, name);
2773 name_to_backref_error(name);
2781 rb_len_t olen = RMATCH_NREGS(match);
2784 if (
len == 0)
return result;
2786 for (j = beg; j < end; j++) {
2789 if (beg +
len > j) {
2799 int num_regs = RMATCH_NREGS(match);
2810 return match_ary_subseq(match, beg,
len, result);
2912match_aref(
int argc,
VALUE *argv,
VALUE match)
2919 if (
NIL_P(length)) {
2924 int num = namev_to_backref_number(match, idx);
2929 return match_ary_aref(match, idx,
Qnil);
2936 rb_len_t num_regs = RMATCH_NREGS(match);
2942 if (beg < 0)
return Qnil;
2944 else if (beg > num_regs) {
2947 if (beg+
len > num_regs) {
2948 len = num_regs - beg;
2950 return match_ary_subseq(match, beg,
len,
Qnil);
3030match_values_at(
int argc,
VALUE *argv,
VALUE match)
3038 for (i=0; i<argc; i++) {
3043 int num = namev_to_backref_number(match, argv[i]);
3048 match_ary_aref(match, argv[i], result);
3075match_to_s(
VALUE match)
3090match_named_captures_iter(
const OnigUChar *name,
const OnigUChar *name_end,
3091 int back_num,
int *back_refs,
OnigRegex regex,
void *arg)
3094 VALUE hash = data->hash;
3095 VALUE match = data->match;
3097 VALUE key = rb_enc_str_new((
const char *)name, name_end-name, regex->enc);
3099 if (data->symbolize) {
3108 for (i = 0; i < back_num; i++) {
3111 rb_hash_aset(hash, key, value);
3117 rb_hash_aset(hash, key,
Qnil);
3159match_named_captures(
int argc,
VALUE *argv,
VALUE match)
3165 return rb_hash_new();
3168 int symbolize_names = 0;
3173 static ID keyword_ids[1];
3175 VALUE symbolize_names_val;
3177 if (!keyword_ids[0]) {
3180 rb_get_kwargs(opt, keyword_ids, 0, 1, &symbolize_names_val);
3181 if (!UNDEF_P(symbolize_names_val) &&
RTEST(symbolize_names_val)) {
3182 symbolize_names = 1;
3186 hash = rb_hash_new();
3189 onig_foreach_name(
RREGEXP_PTR(
RMATCH(match)->regexp), match_named_captures_iter, &data);
3235match_deconstruct_keys(
VALUE match,
VALUE keys)
3243 return rb_hash_new();
3251 onig_foreach_name(
RREGEXP_PTR(
RMATCH(match)->regexp), match_named_captures_iter, &data);
3259 return rb_hash_new();
3272 int num = match_name_to_backref_number(match, name);
3304match_string(
VALUE match)
3307 return RMATCH(match)->str;
3316match_inspect_name_iter(
const OnigUChar *name,
const OnigUChar *name_end,
3317 int back_num,
int *back_refs,
OnigRegex regex,
void *arg0)
3322 for (i = 0; i < back_num; i++) {
3323 arg[back_refs[i]].name = name;
3324 arg[back_refs[i]].len = name_end - name;
3354match_inspect(
VALUE match)
3359 int num_regs = RMATCH_NREGS(match);
3365 return rb_sprintf(
"#<%"PRIsVALUE
":%p>", cname, (
void*)match);
3367 else if (
NIL_P(regexp)) {
3368 return rb_sprintf(
"#<%"PRIsVALUE
": %"PRIsVALUE
">",
3376 match_inspect_name_iter, names);
3381 for (i = 0; i < num_regs; i++) {
3388 rb_str_catf(str,
"%d", i);
3407read_escaped_byte(
const char **pp,
const char *end, onig_errmsg_buffer err)
3409 const char *p = *pp;
3411 int meta_prefix = 0, ctrl_prefix = 0;
3414 if (p == end || *p++ !=
'\\') {
3415 errcpy(err,
"too short escaped multibyte character");
3421 errcpy(err,
"too short escape sequence");
3425 case '\\': code =
'\\';
break;
3426 case 'n': code =
'\n';
break;
3427 case 't': code =
'\t';
break;
3428 case 'r': code =
'\r';
break;
3429 case 'f': code =
'\f';
break;
3430 case 'v': code =
'\013';
break;
3431 case 'a': code =
'\007';
break;
3432 case 'e': code =
'\033';
break;
3435 case '0':
case '1':
case '2':
case '3':
3436 case '4':
case '5':
case '6':
case '7':
3445 errcpy(err,
"invalid hex escape");
3453 errcpy(err,
"duplicate meta escape");
3457 if (p+1 < end && *p++ ==
'-' && (*p & 0x80) == 0) {
3467 errcpy(err,
"too short meta escape");
3471 if (p == end || *p++ !=
'-') {
3472 errcpy(err,
"too short control escape");
3477 errcpy(err,
"duplicate control escape");
3481 if (p < end && (*p & 0x80) == 0) {
3491 errcpy(err,
"too short control escape");
3495 errcpy(err,
"unexpected escape sequence");
3498 if (code < 0 || 0xff < code) {
3499 errcpy(err,
"invalid escape code");
3513unescape_escaped_nonascii(
const char **pp,
const char *end,
rb_encoding *enc,
3516 const char *p = *pp;
3518 unsigned char *area =
ALLOCA_N(
unsigned char, chmaxlen);
3519 char *chbuf = (
char *)area;
3524 memset(chbuf, 0, chmaxlen);
3526 byte = read_escaped_byte(&p, end, err);
3531 area[chlen++] = byte;
3532 while (chlen < chmaxlen &&
3534 byte = read_escaped_byte(&p, end, err);
3538 area[chlen++] = byte;
3541 l = rb_enc_precise_mbclen(chbuf, chbuf+chlen, enc);
3543 errcpy(err,
"invalid multibyte escape");
3546 if (1 < chlen || (area[0] & 0x80)) {
3551 else if (*encp != enc) {
3552 errcpy(err,
"escaped non ASCII character in UTF-8 regexp");
3558 snprintf(escbuf,
sizeof(escbuf),
"\\x%02X", area[0]&0xff);
3566check_unicode_range(
unsigned long code, onig_errmsg_buffer err)
3568 if ((0xd800 <= code && code <= 0xdfff) ||
3570 errcpy(err,
"invalid Unicode range");
3577append_utf8(
unsigned long uv,
3580 if (check_unicode_range(uv, err) != 0)
3584 snprintf(escbuf,
sizeof(escbuf),
"\\x%02X", (
int)uv);
3594 *encp = rb_utf8_encoding();
3595 else if (*encp != rb_utf8_encoding()) {
3596 errcpy(err,
"UTF-8 character in non UTF-8 regexp");
3604unescape_unicode_list(
const char **pp,
const char *end,
3607 const char *p = *pp;
3608 int has_unicode = 0;
3612 while (p < end &&
ISSPACE(*p)) p++;
3619 errcpy(err,
"invalid Unicode range");
3623 if (append_utf8(code, buf, encp, err) != 0)
3627 while (p < end &&
ISSPACE(*p)) p++;
3630 if (has_unicode == 0) {
3631 errcpy(err,
"invalid Unicode list");
3641unescape_unicode_bmp(
const char **pp,
const char *end,
3644 const char *p = *pp;
3649 errcpy(err,
"invalid Unicode escape");
3654 errcpy(err,
"invalid Unicode escape");
3657 if (append_utf8(code, buf, encp, err) != 0)
3664unescape_nonascii0(
const char **pp,
const char *end,
rb_encoding *enc,
3666 onig_errmsg_buffer err,
int options,
int recurse)
3668 const char *p = *pp;
3671 int in_char_class = 0;
3673 int extended_mode = options & ONIG_OPTION_EXTEND;
3677 int chlen = rb_enc_precise_mbclen(p, end, enc);
3680 errcpy(err,
"invalid multibyte character");
3684 if (1 < chlen || (*p & 0x80)) {
3690 else if (*encp != enc) {
3691 errcpy(err,
"non ASCII character in UTF-8 regexp");
3700 errcpy(err,
"too short escape sequence");
3703 chlen = rb_enc_precise_mbclen(p, end, enc);
3705 goto invalid_multibyte;
3714 case '1':
case '2':
case '3':
3715 case '4':
case '5':
case '6':
case '7':
3717 size_t len = end-(p-1), octlen;
3734 if (rb_is_usascii_enc(enc)) {
3735 const char *pbeg = p;
3736 int byte = read_escaped_byte(&p, end, err);
3737 if (
byte == -1)
return -1;
3742 if (unescape_escaped_nonascii(&p, end, enc, buf, encp, err) != 0)
3749 errcpy(err,
"too short escape sequence");
3755 if (unescape_unicode_list(&p, end, buf, encp, err) != 0)
3757 if (p == end || *p++ !=
'}') {
3758 errcpy(err,
"invalid Unicode list");
3765 if (unescape_unicode_bmp(&p, end, buf, encp, err) != 0)
3787 if (extended_mode && !in_char_class) {
3789 while ((p < end) && ((c = *p++) !=
'\n')) {
3790 if ((c & 0x80) && !*encp && enc == rb_utf8_encoding()) {
3803 if (in_char_class) {
3810 if (!in_char_class && recurse) {
3811 if (--parens == 0) {
3818 if (!in_char_class && p + 1 < end && *p ==
'?') {
3819 if (*(p+1) ==
'#') {
3821 const char *orig_p = p;
3824 while (cont && (p < end)) {
3827 if (!(c & 0x80))
break;
3828 if (!*encp && enc == rb_utf8_encoding()) {
3834 chlen = rb_enc_precise_mbclen(p, end, enc);
3836 goto invalid_multibyte;
3857 int local_extend = 0;
3864 for (s = p+1; s < end; s++) {
3867 local_extend = invert ? -1 : 1;
3874 if (local_extend == 0 ||
3875 (local_extend == -1 && !extended_mode) ||
3876 (local_extend == 1 && extended_mode)) {
3883 int local_options = options;
3884 if (local_extend == 1) {
3885 local_options |= ONIG_OPTION_EXTEND;
3888 local_options &= ~ONIG_OPTION_EXTEND;
3892 int ret = unescape_nonascii0(&p, end, enc, buf, encp,
3895 if (ret < 0)
return ret;
3900 extended_mode = local_extend == 1;
3917 else if (!in_char_class && recurse) {
3935unescape_nonascii(
const char *p,
const char *end,
rb_encoding *enc,
3937 onig_errmsg_buffer err,
int options)
3939 return unescape_nonascii0(&p, end, enc, buf, encp, has_property,
3944rb_reg_preprocess(
const char *p,
const char *end,
rb_encoding *enc,
3945 rb_encoding **fixed_enc, onig_errmsg_buffer err,
int options)
3948 int has_property = 0;
3952 if (rb_enc_asciicompat(enc))
3956 rb_enc_associate(buf, enc);
3959 if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err, options) != 0)
3962 if (has_property && !*fixed_enc) {
3967 rb_enc_associate(buf, *fixed_enc);
3974rb_reg_check_preprocess(
VALUE str)
3977 onig_errmsg_buffer err =
"";
3983 p = RSTRING_PTR(str);
3984 end = p + RSTRING_LEN(str);
3985 enc = rb_enc_get(str);
3987 buf = rb_reg_preprocess(p, end, enc, &fixed_enc, err, 0);
3991 return rb_reg_error_desc(str, 0, err);
3997rb_reg_preprocess_dregexp(
VALUE ary,
int options)
4001 onig_errmsg_buffer err =
"";
4007 rb_raise(rb_eArgError,
"no arguments given");
4016 src_enc = rb_enc_get(str);
4017 if (options & ARG_ENCODING_NONE &&
4018 src_enc != ascii8bit) {
4020 rb_raise(
rb_eRegexpError,
"/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
4022 src_enc = ascii8bit;
4026 p = RSTRING_PTR(str);
4027 end = p + RSTRING_LEN(str);
4029 buf = rb_reg_preprocess(p, end, src_enc, &fixed_enc, err, options);
4032 rb_raise(rb_eArgError,
"%s", err);
4034 if (fixed_enc != 0) {
4035 if (regexp_enc != 0 && regexp_enc != fixed_enc) {
4036 rb_raise(
rb_eRegexpError,
"encoding mismatch in dynamic regexp : %s and %s",
4037 rb_enc_name(regexp_enc), rb_enc_name(fixed_enc));
4039 regexp_enc = fixed_enc;
4048 rb_enc_associate(result, regexp_enc);
4055rb_reg_initialize_check(
VALUE obj)
4057 rb_check_frozen(obj);
4065 int options, onig_errmsg_buffer err,
4066 const char *sourcefile,
int sourceline)
4073 rb_reg_initialize_check(obj);
4075 if (rb_enc_dummy_p(enc)) {
4076 errcpy(err,
"can't make regexp with dummy encoding");
4080 unescaped = rb_reg_preprocess(s, s+
len, enc, &fixed_enc, err, options);
4081 if (
NIL_P(unescaped))
4085 if ((fixed_enc != enc && (options & ARG_ENCODING_FIXED)) ||
4086 (fixed_enc != a_enc && (options & ARG_ENCODING_NONE))) {
4087 errcpy(err,
"incompatible character encoding");
4090 if (fixed_enc != a_enc) {
4091 options |= ARG_ENCODING_FIXED;
4095 else if (!(options & ARG_ENCODING_FIXED)) {
4096 enc = rb_usascii_encoding();
4099 rb_enc_associate((
VALUE)re, enc);
4100 if ((options & ARG_ENCODING_FIXED) || fixed_enc) {
4103 if (options & ARG_ENCODING_NONE) {
4107 bool success = make_regexp(
RREGEXP_PTR(obj), RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc,
4108 options & ARG_REG_OPTION_MASK, err,
4109 sourcefile, sourceline);
4110 if (!success)
return -1;
4125 if (regenc != enc) {
4127 str = rb_enc_associate(dup, enc = regenc);
4129 str = rb_fstring(str);
4134rb_reg_initialize_str(
VALUE obj,
VALUE str,
int options, onig_errmsg_buffer err,
4135 const char *sourcefile,
int sourceline)
4138 rb_encoding *str_enc = rb_enc_get(str), *enc = str_enc;
4139 if (options & ARG_ENCODING_NONE) {
4141 if (enc != ascii8bit) {
4143 errcpy(err,
"/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
4149 ret = rb_reg_initialize(obj, RSTRING_PTR(str), RSTRING_LEN(str), enc,
4150 options, err, sourcefile, sourceline);
4151 if (ret == 0) reg_set_source(obj, str, str_enc);
4156rb_reg_s_alloc(
VALUE klass)
4176 return rb_reg_init_str(rb_reg_alloc(), s, options);
4180rb_reg_init_str(
VALUE re,
VALUE s,
int options)
4182 onig_errmsg_buffer err =
"";
4184 if (rb_reg_initialize_str(re, s, options, err, NULL, 0) != 0) {
4185 rb_reg_raise_str(s, options, err);
4194 onig_errmsg_buffer err =
"";
4196 if (rb_reg_initialize(re, RSTRING_PTR(s), RSTRING_LEN(s),
4197 enc, options, err, NULL, 0) != 0) {
4198 rb_reg_raise_str(s, options, err);
4200 reg_set_source(re, s, enc);
4206rb_reg_new_from_values(
rb_len_t cnt,
const VALUE *elements,
int opt)
4208 const VALUE ary = rb_ary_tmp_new_from_values(0, cnt, elements);
4217 VALUE re = rb_reg_alloc();
4218 onig_errmsg_buffer err =
"";
4220 if (rb_reg_initialize(re, s,
len, enc, options, err, NULL, 0) != 0) {
4221 rb_enc_reg_raise(s,
len, enc, options, err);
4235rb_reg_compile(
VALUE str,
int options,
const char *sourcefile,
int sourceline)
4237 VALUE re = rb_reg_alloc();
4238 onig_errmsg_buffer err =
"";
4241 if (rb_reg_initialize_str(re, str, options, err, sourcefile, sourceline) != 0) {
4242 rb_set_errinfo(rb_reg_error_desc(str, options, err));
4248static VALUE reg_cache;
4253 if (rb_ractor_main_p()) {
4256 && memcmp(
RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
4266static st_index_t reg_hash(
VALUE re);
4278rb_reg_hash(
VALUE re)
4280 st_index_t hashval = reg_hash(re);
4313 if (re1 == re2)
return Qtrue;
4315 rb_reg_check(re1); rb_reg_check(re2);
4345match_hash(
VALUE match)
4351 hashval =
rb_hash_uint(hashval, reg_hash(match_regexp(match)));
4352 int num_regs = RMATCH_NREGS(match);
4387 if (match1 == match2)
return Qtrue;
4391 if (!rb_reg_equal(match_regexp(match1), match_regexp(match2)))
return Qfalse;
4392 int num_regs = RMATCH_NREGS(match1);
4393 if (num_regs != RMATCH_NREGS(match2))
return Qfalse;
4394 if (memcmp(RMATCH_BEG_PTR(match1), RMATCH_BEG_PTR(match2), num_regs *
sizeof(OnigPosition)))
return Qfalse;
4395 if (memcmp(RMATCH_END_PTR(match1), RMATCH_END_PTR(match2), num_regs *
sizeof(OnigPosition)))
return Qfalse;
4454match_integer_at(
int argc,
VALUE *argv,
VALUE match)
4466 else if ((nth = namev_to_backref_number(match, idx)) < 0) {
4467 name_to_backref_error(idx);
4470 if (argc > 1 && (base =
NUM2INT(argv[1])) < 0) {
4471 rb_raise(rb_eArgError,
"invalid radix %d", base);
4474 if (nth >= RMATCH_NREGS(match))
return Qnil;
4475 if (nth < 0 && (nth += RMATCH_NREGS(match)) <= 0)
return Qnil;
4477 rb_len_t start = RMATCH_BEG(match, nth), end = RMATCH_END(match, nth);
4478 if (start < 0)
return Qnil;
4479 RUBY_ASSERT(start <= end, "%"PRIdLEN" > %
"PRIdLEN, start, end);
4481 VALUE str = RMATCH(match)->str;
4482 RUBY_ASSERT(end <= RSTRING_LEN(str), "%
"PRIdLEN" > %
"PRIdLEN, end, RSTRING_LEN(str));
4485 return rb_int_parse_cstr(RSTRING_PTR(str) + start, end - start, &endp, NULL,
4486 base, RB_INT_PARSE_DEFAULT);
4490reg_operand(VALUE s, int check)
4493 return rb_sym2str(s);
4495 else if (RB_TYPE_P(s, T_STRING)) {
4499 return check ? rb_str_to_str(s) : rb_check_string_type(s);
4504reg_match_pos(VALUE re, VALUE *strp, rb_len_t pos, VALUE* set_match)
4509 rb_backref_set(Qnil);
4512 *strp = str = reg_operand(str, TRUE);
4515 VALUE l = rb_str_length(str);
4518 rb_backref_set(Qnil);
4522 pos = rb_str_offset(str, pos);
4524 return rb_reg_search_set_match(re, str, pos, 0, 1, set_match);
4529 * self =~ other -> integer or nil
4531 * Returns the integer index (in characters) of the first match
4532 * for +self+ and +other+, or +nil+ if none;
4533 * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables].
4535 * /at/ =~ 'input data' # => 7
4536 * $~ # => #<MatchData "at
">
4537 * /ax/ =~ 'input data' # => nil
4540 * Assigns named captures to local variables of the same names
4541 * if and only if +self+:
4543 * - Is a regexp literal;
4544 * see {Regexp Literals}[rdoc-ref:syntax/literals.rdoc@Regexp+Literals].
4545 * - Does not contain interpolations;
4546 * see {Regexp interpolation}[rdoc-ref:Regexp@Interpolation+Mode].
4547 * - Is at the left of the expression.
4551 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = y '
4555 * Assigns +nil+ if not matched:
4557 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ ' x = '
4561 * Does not make local variable assignments if +self+ is not a regexp literal:
4563 * r = /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
4565 * p foo # Undefined local variable
4566 * p bar # Undefined local variable
4568 * The assignment does not occur if the regexp is not at the left:
4570 * ' x = y ' =~ /(?<foo>\w+)\s*=\s*(?<foo>\w+)/
4571 * p foo, foo # Undefined local variables
4573 * A regexp interpolation, <tt>#{}</tt>, also disables
4577 * /(?<foo>\w+)\s*=\s*#{r}/ =~ 'x = y'
4578 * p foo # Undefined local variable
4583rb_reg_match(VALUE re, VALUE str)
4585 rb_len_t pos = reg_match_pos(re, &str, 0, NULL);
4586 if (pos < 0) return Qnil;
4587 pos = rb_str_sublen(str, pos);
4588 return LEN2NUM(pos);
4593 * self === other -> true or false
4595 * Returns whether +self+ finds a match in +other+:
4597 * /^[a-z]*$/ === 'HELLO' # => false
4598 * /^[A-Z]*$/ === 'HELLO' # => true
4600 * This method is called in case statements:
4604 * when /\A[a-z]*\z/; print "Lower
case\n
"
4605 * when /\A[A-Z]*\z/; print "Upper
case\n
"
4606 * else print "Mixed
case\n
"
4607 * end # => "Upper
case"
4612rb_reg_eqq(VALUE re, VALUE str)
4616 str = reg_operand(str, FALSE);
4618 rb_backref_set(Qnil);
4621 start = rb_reg_search(re, str, 0, 0);
4622 return RBOOL(start >= 0);
4628 * ~ rxp -> integer or nil
4630 * Equivalent to <tt><i>rxp</i> =~ $_</tt>:
4638rb_reg_match2(VALUE re)
4641 VALUE line = rb_lastline_get();
4643 if (!RB_TYPE_P(line, T_STRING)) {
4644 rb_backref_set(Qnil);
4648 start = rb_reg_search(re, line, 0, 0);
4652 start = rb_str_sublen(line, start);
4653 return LEN2NUM(start);
4659 * match(string, offset = 0) -> matchdata or nil
4660 * match(string, offset = 0) {|matchdata| ... } -> object
4662 * With no block given, returns the MatchData object
4663 * that describes the match, if any, or +nil+ if none;
4664 * the search begins at the given character +offset+ in +string+:
4666 * /abra/.match('abracadabra') # => #<MatchData "abra
">
4667 * /abra/.match('abracadabra', 4) # => #<MatchData "abra
">
4668 * /abra/.match('abracadabra', 8) # => nil
4669 * /abra/.match('abracadabra', 800) # => nil
4671 * string = "\u{5d0 5d1 5e8 5d0}cadabra
"
4672 * /abra/.match(string, 7) #=> #<MatchData "abra
">
4673 * /abra/.match(string, 8) #=> nil
4674 * /abra/.match(string.b, 8) #=> #<MatchData "abra
">
4676 * With a block given, calls the block if and only if a match is found;
4677 * returns the block's value:
4679 * /abra/.match('abracadabra') {|matchdata| p matchdata }
4680 * # => #<MatchData "abra
">
4681 * /abra/.match('abracadabra', 4) {|matchdata| p matchdata }
4682 * # => #<MatchData "abra
">
4683 * /abra/.match('abracadabra', 8) {|matchdata| p matchdata }
4685 * /abra/.match('abracadabra', 8) {|marchdata| fail 'Cannot happen' }
4688 * Output (from the first two blocks above):
4690 * #<MatchData "abra
">
4691 * #<MatchData "abra
">
4693 * /(.)(.)(.)/.match("abc
")[2] # => "b
"
4694 * /(.)(.)/.match("abc
", 1)[2] # => "c
"
4699rb_reg_match_m(int argc, VALUE *argv, VALUE re)
4701 VALUE result = Qnil, str, initpos;
4704 if (rb_scan_args(argc, argv, "11
", &str, &initpos) == 2) {
4705 pos = NUM2LEN(initpos);
4711 pos = reg_match_pos(re, &str, pos, &result);
4715 rb_match_busy(result);
4716 if (!NIL_P(result) && rb_block_given_p()) {
4717 return rb_yield(result);
4724 * match?(string) -> true or false
4725 * match?(string, offset = 0) -> true or false
4727 * Returns <code>true</code> or <code>false</code> to indicate whether the
4728 * regexp is matched or not without updating $~ and other related variables.
4729 * If the second parameter is present, it specifies the position in the string
4730 * to begin the search.
4732 * /R.../.match?("Ruby
") # => true
4733 * /R.../.match?("Ruby
", 1) # => false
4734 * /P.../.match?("Ruby
") # => false
4739rb_reg_match_m_p(int argc, VALUE *argv, VALUE re)
4741 rb_len_t pos = rb_check_arity(argc, 1, 2) > 1 ? NUM2LEN(argv[1]) : 0;
4742 return rb_reg_match_p(re, argv[0], pos);
4746rb_reg_match_p(VALUE re, VALUE str, rb_len_t pos)
4748 if (NIL_P(str)) return Qfalse;
4749 str = SYMBOL_P(str) ? rb_sym2str(str) : StringValue(str);
4752 pos += NUM2LEN(rb_str_length(str));
4753 if (pos < 0) return Qfalse;
4757 const char *beg = rb_str_subpos(str, pos, &len);
4758 if (!beg) return Qfalse;
4759 pos = beg - RSTRING_PTR(str);
4763 struct reg_onig_search_args args = {
4765 .range = RSTRING_LEN(str),
4768 return rb_reg_onig_match(re, str, reg_onig_search, &args, NULL) == ONIG_MISMATCH ? Qfalse : Qtrue;
4772 * Document-method: compile
4774 * Alias for Regexp.new
4778str_to_option(VALUE str)
4783 str = rb_check_string_type(str);
4784 if (NIL_P(str)) return -1;
4785 RSTRING_GETMEM(str, ptr, len);
4786 for (rb_len_t i = 0; i < len; ++i) {
4787 int f = char_to_option(ptr[i]);
4789 rb_raise(rb_eArgError, "unknown regexp option: %
"PRIsVALUE, str);
4797set_timeout(rb_hrtime_t *hrt, VALUE timeout)
4799 double timeout_d = NIL_P(timeout) ? 0.0 : NUM2DBL(timeout);
4800 if (!NIL_P(timeout) && !(timeout_d > 0)) {
4801 rb_raise(rb_eArgError, "invalid timeout: %
"PRIsVALUE, timeout);
4803 double2hrtime(hrt, timeout_d);
4807reg_copy(VALUE copy, VALUE orig)
4810 rb_reg_initialize_check(copy);
4811 if ((r = onig_reg_copy_body(RREGEXP_PTR(copy), RREGEXP_PTR(orig))) != 0) {
4812 /* ONIGERR_MEMORY only */
4813 rb_raise(rb_eRegexpError, "%s
", onig_error_code_to_format(r));
4815 FL_SET_RAW(copy, RREGEXP_INITIALIZED);
4817 RB_OBJ_WRITE(copy, &RREGEXP(copy)->src, RREGEXP(orig)->src);
4818 RREGEXP_PTR(copy)->timelimit = RREGEXP_PTR(orig)->timelimit;
4819 rb_enc_copy(copy, orig);
4820 FL_SET_RAW(copy, FL_TEST_RAW(orig, KCODE_FIXED|REG_ENCODING_NONE));
4821 if (RBASIC_CLASS(copy) == rb_cRegexp) {
4828struct reg_init_args {
4835static VALUE reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args);
4836static VALUE reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags);
4840 * Regexp.new(string, options = 0, timeout: nil) -> regexp
4841 * Regexp.new(regexp, timeout: nil) -> regexp
4843 * With argument +string+ given, returns a new regexp with the given string
4846 * r = Regexp.new('foo') # => /foo/
4847 * r.source # => "foo
"
4850 * Optional argument +options+ is one of the following:
4852 * - A String of options:
4854 * Regexp.new('foo', 'i') # => /foo/i
4855 * Regexp.new('foo', 'im') # => /foo/im
4857 * - The bit-wise OR of one or more of the constants
4858 * Regexp::EXTENDED, Regexp::IGNORECASE, Regexp::MULTILINE, and
4859 * Regexp::NOENCODING:
4861 * Regexp.new('foo', Regexp::IGNORECASE) # => /foo/i
4862 * Regexp.new('foo', Regexp::EXTENDED) # => /foo/x
4863 * Regexp.new('foo', Regexp::MULTILINE) # => /foo/m
4864 * Regexp.new('foo', Regexp::NOENCODING) # => /foo/n
4865 * flags = Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE
4866 * Regexp.new('foo', flags) # => /foo/mix
4868 * - +nil+ or +false+, which is ignored.
4869 * - Any other truthy value, in which case the regexp will be
4872 * If optional keyword argument +timeout+ is given,
4873 * its float value overrides the timeout interval for the class,
4875 * If +nil+ is passed as +timeout, it uses the timeout interval
4876 * for the class, Regexp.timeout.
4878 * With argument +regexp+ given, returns a new regexp. The source,
4879 * options, timeout are the same as +regexp+. +options+ and +n_flag+
4880 * arguments are ineffective. The timeout can be overridden by
4881 * +timeout+ keyword.
4883 * options = Regexp::MULTILINE
4884 * r = Regexp.new('foo', options, timeout: 1.1) # => /foo/m
4885 * r2 = Regexp.new(r) # => /foo/m
4886 * r2.timeout # => 1.1
4887 * r3 = Regexp.new(r, timeout: 3.14) # => /foo/m
4888 * r3.timeout # => 3.14
4893rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
4895 struct reg_init_args args;
4896 VALUE re = reg_extract_args(argc, argv, &args);
4899 reg_init_args(self, args.str, args.enc, args.flags);
4905 set_timeout(&RREGEXP_PTR(self)->timelimit, args.timeout);
4906 if (RBASIC_CLASS(self) == rb_cRegexp) {
4914reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args)
4917 rb_encoding *enc = 0;
4918 VALUE str, src, opts = Qundef, kwargs;
4921 rb_scan_args(argc, argv, "11:
", &src, &opts, &kwargs);
4923 args->timeout = Qnil;
4924 if (!NIL_P(kwargs)) {
4925 static ID keywords[1];
4927 keywords[0] = rb_intern_const("timeout
");
4929 rb_get_kwargs(kwargs, keywords, 0, 1, &args->timeout);
4932 if (RB_TYPE_P(src, T_REGEXP)) {
4936 rb_warn("flags ignored
");
4939 flags = rb_reg_options(re);
4940 str = RREGEXP_SRC(re);
4945 if (FIXNUM_P(opts)) flags = FIX2INT(opts);
4946 else if ((f = str_to_option(opts)) >= 0) flags = f;
4947 else if (rb_bool_expected(opts, "ignorecase
", FALSE))
4948 flags = ONIG_OPTION_IGNORECASE;
4950 str = StringValue(src);
4954 args->flags = flags;
4959reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags)
4961 if (enc && rb_enc_get(str) != enc)
4962 rb_reg_init_str_enc(self, str, enc, flags);
4964 rb_reg_init_str(self, str, flags);
4969rb_reg_quote(VALUE str)
4971 rb_encoding *enc = rb_enc_get(str);
4975 int ascii_only = rb_enc_str_asciionly_p(str);
4977 s = RSTRING_PTR(str);
4978 send = s + RSTRING_LEN(str);
4980 c = rb_enc_ascget(s, send, &clen, enc);
4982 s += mbclen(s, send, enc);
4986 case '[': case ']': case '{': case '}':
4987 case '(': case ')': case '|': case '-':
4988 case '*': case '.': case '\\':
4989 case '?': case '+': case '^': case '$':
4991 case '\t': case '\f': case '\v': case '\n': case '\r':
4996 tmp = rb_str_new3(str);
4998 rb_enc_associate(tmp, rb_usascii_encoding());
5003 tmp = rb_str_new(0, RSTRING_LEN(str)*2);
5005 rb_enc_associate(tmp, rb_usascii_encoding());
5008 rb_enc_copy(tmp, str);
5010 t = RSTRING_PTR(tmp);
5011 /* copy upto metacharacter */
5012 const char *p = RSTRING_PTR(str);
5013 memcpy(t, p, s - p);
5017 c = rb_enc_ascget(s, send, &clen, enc);
5019 int n = mbclen(s, send, enc);
5027 case '[': case ']': case '{': case '}':
5028 case '(': case ')': case '|': case '-':
5029 case '*': case '.': case '\\':
5030 case '?': case '+': case '^': case '$':
5032 t += rb_enc_mbcput('\\', t, enc);
5035 t += rb_enc_mbcput('\\', t, enc);
5036 t += rb_enc_mbcput(' ', t, enc);
5039 t += rb_enc_mbcput('\\', t, enc);
5040 t += rb_enc_mbcput('t', t, enc);
5043 t += rb_enc_mbcput('\\', t, enc);
5044 t += rb_enc_mbcput('n', t, enc);
5047 t += rb_enc_mbcput('\\', t, enc);
5048 t += rb_enc_mbcput('r', t, enc);
5051 t += rb_enc_mbcput('\\', t, enc);
5052 t += rb_enc_mbcput('f', t, enc);
5055 t += rb_enc_mbcput('\\', t, enc);
5056 t += rb_enc_mbcput('v', t, enc);
5059 t += rb_enc_mbcput(c, t, enc);
5061 rb_str_resize(tmp, t - RSTRING_PTR(tmp));
5068 * Regexp.escape(string) -> new_string
5070 * Returns a new string that escapes any characters
5071 * that have special meaning in a regular expression:
5073 * s = Regexp.escape('\*?{}.') # => "\\\\\\*\\?\\{\\}\\.
"
5075 * For any string +s+, this call returns a MatchData object:
5077 * r = Regexp.new(Regexp.escape(s)) # => /\\\\\\\*\\\?\\\{\\\}\\\./
5078 * r.match(s) # => #<MatchData "\\\\\\*\\?\\{\\}\\.
">
5083rb_reg_s_quote(VALUE c, VALUE str)
5085 return rb_reg_quote(reg_operand(str, TRUE));
5089rb_reg_options(VALUE re)
5094 options = RREGEXP_PTR(re)->options & ARG_REG_OPTION_MASK;
5095 if (RBASIC(re)->flags & KCODE_FIXED) options |= ARG_ENCODING_FIXED;
5096 if (RBASIC(re)->flags & REG_ENCODING_NONE) options |= ARG_ENCODING_NONE;
5101rb_check_regexp_type(VALUE re)
5103 return rb_check_convert_type(re, T_REGEXP, "Regexp
", "to_regexp
");
5108 * Regexp.try_convert(object) -> regexp or nil
5110 * Returns +object+ if it is a regexp:
5112 * Regexp.try_convert(/re/) # => /re/
5114 * Otherwise if +object+ responds to <tt>:to_regexp</tt>,
5115 * calls <tt>object.to_regexp</tt> and returns the result.
5117 * Returns +nil+ if +object+ does not respond to <tt>:to_regexp</tt>.
5119 * Regexp.try_convert('re') # => nil
5121 * Raises an exception unless <tt>object.to_regexp</tt> returns a regexp.
5125rb_reg_s_try_convert(VALUE dummy, VALUE re)
5127 return rb_check_regexp_type(re);
5131rb_reg_s_union(VALUE self, VALUE args0)
5133 rb_len_t argc = RARRAY_LEN(args0);
5137 args[0] = rb_str_new2("(?!)
");
5138 return rb_class_new_instance(1, args, rb_cRegexp);
5140 else if (argc == 1) {
5141 VALUE arg = rb_ary_entry(args0, 0);
5142 VALUE re = rb_check_regexp_type(arg);
5147 quoted = rb_reg_s_quote(Qnil, arg);
5148 return rb_reg_new_str(quoted, 0);
5153 VALUE source = rb_str_buf_new(0);
5154 rb_encoding *result_enc;
5156 int has_asciionly = 0;
5157 rb_encoding *has_ascii_compat_fixed = 0;
5158 rb_encoding *has_ascii_incompat = 0;
5160 for (i = 0; i < argc; i++) {
5162 VALUE e = rb_ary_entry(args0, i);
5165 rb_str_buf_cat_ascii(source, "|
");
5167 v = rb_check_regexp_type(e);
5169 rb_encoding *enc = rb_enc_get(v);
5170 if (!rb_enc_asciicompat(enc)) {
5171 if (!has_ascii_incompat)
5172 has_ascii_incompat = enc;
5173 else if (has_ascii_incompat != enc)
5174 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
5175 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
5177 else if (rb_reg_fixed_encoding_p(v)) {
5178 if (!has_ascii_compat_fixed)
5179 has_ascii_compat_fixed = enc;
5180 else if (has_ascii_compat_fixed != enc)
5181 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
5182 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
5187 v = rb_reg_str_with_term(v, -1);
5192 enc = rb_enc_get(e);
5193 if (!rb_enc_asciicompat(enc)) {
5194 if (!has_ascii_incompat)
5195 has_ascii_incompat = enc;
5196 else if (has_ascii_incompat != enc)
5197 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
5198 rb_enc_name(has_ascii_incompat), rb_enc_name(enc));
5200 else if (rb_enc_str_asciionly_p(e)) {
5204 if (!has_ascii_compat_fixed)
5205 has_ascii_compat_fixed = enc;
5206 else if (has_ascii_compat_fixed != enc)
5207 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
5208 rb_enc_name(has_ascii_compat_fixed), rb_enc_name(enc));
5210 v = rb_reg_s_quote(Qnil, e);
5212 if (has_ascii_incompat) {
5213 if (has_asciionly) {
5214 rb_raise(rb_eArgError, "ASCII incompatible encoding: %s
",
5215 rb_enc_name(has_ascii_incompat));
5217 if (has_ascii_compat_fixed) {
5218 rb_raise(rb_eArgError, "incompatible encodings: %s and %s
",
5219 rb_enc_name(has_ascii_incompat), rb_enc_name(has_ascii_compat_fixed));
5224 rb_enc_copy(source, v);
5226 rb_str_append(source, v);
5229 if (has_ascii_incompat) {
5230 result_enc = has_ascii_incompat;
5232 else if (has_ascii_compat_fixed) {
5233 result_enc = has_ascii_compat_fixed;
5236 result_enc = rb_ascii8bit_encoding();
5239 rb_enc_associate(source, result_enc);
5240 return rb_class_new_instance(1, &source, rb_cRegexp);
5246 * Regexp.union(*patterns) -> regexp
5247 * Regexp.union(array_of_patterns) -> regexp
5249 * Returns a regexp that is the union of the given patterns:
5251 * r = Regexp.union(%w[cat dog]) # => /cat|dog/
5252 * r.match('cat') # => #<MatchData "cat
">
5253 * r.match('dog') # => #<MatchData "dog
">
5254 * r.match('cog') # => nil
5256 * Each string pattern is escaped so that it is matched literally:
5258 * Regexp.union('penzance') # => /penzance/
5259 * Regexp.union('a+b*c') # => /a\+b\*c/
5260 * Regexp.union('skiing', 'sledding') # => /skiing|sledding/
5261 * Regexp.union(['skiing', 'sledding']) # => /skiing|sledding/
5263 * For each pattern that is a regexp, it is used as is,
5264 * including its flags:
5266 * Regexp.union(/foo/i, /bar/m, /baz/x)
5267 * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
5268 * Regexp.union([/foo/i, /bar/m, /baz/x])
5269 * # => /(?i-mx:foo)|(?m-ix:bar)|(?x-mi:baz)/
5271 * With no arguments, returns <tt>/(?!)/</tt>:
5273 * Regexp.union # => /(?!)/
5275 * If any regexp pattern contains captures, the behavior is unspecified.
5279rb_reg_s_union_m(VALUE self, VALUE args)
5282 if (RARRAY_LEN(args) == 1 &&
5283 !NIL_P(v = rb_check_array_type(rb_ary_entry(args, 0)))) {
5284 return rb_reg_s_union(self, v);
5286 return rb_reg_s_union(self, args);
5291 * Regexp.linear_time?(re)
5292 * Regexp.linear_time?(string, options = 0)
5294 * Returns +true+ if matching against <tt>re</tt> can be
5295 * done in linear time to the input string.
5297 * Regexp.linear_time?(/re/) # => true
5299 * Note that this is a property of the ruby interpreter, not of the argument
5300 * regular expression. Identical regexp can or cannot run in linear time
5301 * depending on your ruby binary. Neither forward nor backward compatibility
5302 * is guaranteed about the return value of this method. Our current algorithm
5303 * is (*1) but this is subject to change in the future. Alternative
5304 * implementations can also behave differently. They might always return
5305 * false for everything.
5307 * (*1): https://doi.org/10.1109/SP40001.2021.00032
5311rb_reg_s_linear_time_p(int argc, VALUE *argv, VALUE self)
5313 struct reg_init_args args;
5314 VALUE re = reg_extract_args(argc, argv, &args);
5317 re = reg_init_args(rb_reg_alloc(), args.str, args.enc, args.flags);
5320 return RBOOL(onig_check_linear_time(RREGEXP_PTR(re)));
5325rb_reg_init_copy(VALUE copy, VALUE re)
5327 if (!OBJ_INIT_COPY(copy, re)) return copy;
5329 return reg_copy(copy, re);
5333do_regsub(VALUE str, VALUE src, VALUE regexp, int num_regs, const OnigPosition *beg, const OnigPosition *end)
5338 rb_encoding *str_enc = rb_enc_get(str);
5339 rb_encoding *src_enc = rb_enc_get(src);
5340 int acompat = rb_enc_asciicompat(str_enc);
5342#define ASCGET(s,e,cl) (acompat ? (*(cl)=1,ISASCII((s)[0])?(s)[0]:-1) : rb_enc_ascget((s), (e), (cl), str_enc))
5344 RSTRING_GETMEM(str, s, n);
5349 int c = ASCGET(s, e, &clen);
5353 s += mbclen(s, e, str_enc);
5359 if (c != '\\' || s == e) continue;
5362 val = rb_str_buf_new(ss-p);
5364 rb_enc_str_buf_cat(val, p, ss-p, str_enc);
5366 c = ASCGET(s, e, &clen);
5368 s += mbclen(s, e, str_enc);
5369 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
5377 case '1': case '2': case '3': case '4':
5378 case '5': case '6': case '7': case '8': case '9':
5379 if (!NIL_P(regexp) && onig_noname_group_capture_is_active(RREGEXP_PTR(regexp))) {
5388 if (s < e && ASCGET(s, e, &clen) == '<') {
5389 char *name, *name_end;
5391 name_end = name = s + clen;
5392 while (name_end < e) {
5393 c = ASCGET(name_end, e, &clen);
5394 if (c == '>') break;
5395 name_end += c == -1 ? mbclen(name_end, e, str_enc) : clen;
5398 VALUE n = rb_str_subseq(str, (rb_len_t)(name - RSTRING_PTR(str)),
5399 (rb_len_t)(name_end - name));
5400 struct re_registers tmp = {
5401 .allocated = num_regs,
5402 .num_regs = num_regs,
5403 .beg = (OnigPosition *)beg,
5404 .end = (OnigPosition *)end,
5406 if ((no = NAME_TO_NUMBER(&tmp, regexp, n, name, name_end)) < 1) {
5407 name_to_backref_error(n);
5409 p = s = name_end + clen;
5413 rb_raise(rb_eRuntimeError, "invalid group name reference format
");
5417 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
5426 rb_enc_str_buf_cat(val, RSTRING_PTR(src), beg[0], src_enc);
5430 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+end[0], RSTRING_LEN(src)-end[0], src_enc);
5435 while (beg[no] == -1 && no > 0) no--;
5436 if (no == 0) continue;
5440 rb_enc_str_buf_cat(val, s-clen, clen, str_enc);
5444 rb_enc_str_buf_cat(val, ss, s-ss, str_enc);
5449 if (no >= num_regs) continue;
5450 if (beg[no] == -1) continue;
5451 rb_enc_str_buf_cat(val, RSTRING_PTR(src)+beg[no], end[no]-beg[no], src_enc);
5455 if (!val) return str;
5457 rb_enc_str_buf_cat(val, p, e-p, str_enc);
5465rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
5467 return do_regsub(str, src, regexp, regs->num_regs, regs->beg, regs->end);
5471rb_reg_regsub_match(VALUE str, VALUE src, VALUE match)
5473 return do_regsub(str, src, RMATCH(match)->regexp,
5474 RMATCH_NREGS(match), RMATCH_BEG_PTR(match), RMATCH_END_PTR(match));
5478ignorecase_getter(ID _x, VALUE *_y)
5480 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective
");
5485ignorecase_setter(VALUE val, ID id, VALUE *_)
5487 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective; ignored
");
5493 VALUE match = rb_backref_get();
5495 if (NIL_P(match)) return Qnil;
5496 rb_match_busy(match);
5501get_LAST_MATCH_INFO(ID _x, VALUE *_y)
5503 return match_getter();
5507match_setter(VALUE val, ID _x, VALUE *_y)
5510 Check_Type(val, T_MATCH);
5513 rb_backref_set(val);
5518 * Regexp.last_match -> matchdata or nil
5519 * Regexp.last_match(n) -> string or nil
5520 * Regexp.last_match(name) -> string or nil
5522 * With no argument, returns the value of <tt>$~</tt>,
5523 * which is the result of the most recent pattern match
5524 * (see {Regexp global variables}[rdoc-ref:Regexp@Global+Variables]):
5526 * /c(.)t/ =~ 'cat' # => 0
5527 * Regexp.last_match # => #<MatchData "cat
" 1:"a
">
5528 * /a/ =~ 'foo' # => nil
5529 * Regexp.last_match # => nil
5531 * With non-negative integer argument +n+, returns the _n_th field in the
5532 * matchdata, if any, or nil if none:
5534 * /c(.)t/ =~ 'cat' # => 0
5535 * Regexp.last_match(0) # => "cat
"
5536 * Regexp.last_match(1) # => "a
"
5537 * Regexp.last_match(2) # => nil
5539 * With negative integer argument +n+, counts backwards from the last field:
5541 * Regexp.last_match(-1) # => "a
"
5543 * With string or symbol argument +name+,
5544 * returns the string value for the named capture, if any:
5546 * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ 'var = val'
5547 * Regexp.last_match # => #<MatchData "var = val
" lhs:"var
"rhs:"val
">
5548 * Regexp.last_match(:lhs) # => "var
"
5549 * Regexp.last_match('rhs') # => "val
"
5550 * Regexp.last_match('foo') # Raises IndexError.
5555rb_reg_s_last_match(int argc, VALUE *argv, VALUE _)
5557 if (rb_check_arity(argc, 0, 1) == 1) {
5558 VALUE match = rb_backref_get();
5560 if (NIL_P(match)) return Qnil;
5561 n = match_backref_number(match, argv[0]);
5562 return rb_reg_nth_match(n, match);
5564 return match_getter();
5568re_warn(const char *s)
5573// This function is periodically called during regexp matching
5575rb_reg_timeout_p(regex_t *reg, void *end_time_)
5577 rb_hrtime_t *end_time = (rb_hrtime_t *)end_time_;
5579 if (*end_time == 0) {
5580 // This is the first time to check interrupts;
5581 // just measure the current time and determine the end time
5582 // if timeout is set.
5583 rb_hrtime_t timelimit = reg->timelimit;
5586 // no per-object timeout.
5587 timelimit = rb_reg_match_time_limit;
5591 *end_time = rb_hrtime_add(timelimit, rb_hrtime_now());
5594 // no timeout is set
5595 *end_time = RB_HRTIME_MAX;
5599 if (*end_time < rb_hrtime_now()) {
5600 // Timeout has exceeded
5610 * Regexp.timeout -> float or nil
5612 * It returns the current default timeout interval for Regexp matching in second.
5613 * +nil+ means no default timeout configuration.
5617rb_reg_s_timeout_get(VALUE dummy)
5619 double d = hrtime2double(rb_reg_match_time_limit);
5620 if (d == 0.0) return Qnil;
5626 * Regexp.timeout = float or nil
5628 * It sets the default timeout interval for Regexp matching in second.
5629 * +nil+ means no default timeout configuration.
5630 * This configuration is process-global. If you want to set timeout for
5631 * each Regexp, use +timeout+ keyword for <code>Regexp.new</code>.
5633 * Regexp.timeout = 1
5634 * /^a*b?a*$/ =~ "a
" * 100000 + "x
" #=> regexp match timeout (RuntimeError)
5638rb_reg_s_timeout_set(VALUE dummy, VALUE timeout)
5640 rb_ractor_ensure_main_ractor("can not access
Regexp.timeout from non-main Ractors
");
5642 set_timeout(&rb_reg_match_time_limit, timeout);
5649 * rxp.timeout -> float or nil
5651 * It returns the timeout interval for Regexp matching in second.
5652 * +nil+ means no default timeout configuration.
5654 * This configuration is per-object. The global configuration set by
5655 * Regexp.timeout= is ignored if per-object configuration is set.
5657 * re = Regexp.new("^a*b?a*$
", timeout: 1)
5658 * re.timeout #=> 1.0
5659 * re =~ "a
" * 100000 + "x
" #=> regexp match timeout (RuntimeError)
5663rb_reg_timeout_get(VALUE re)
5666 double d = hrtime2double(RREGEXP_PTR(re)->timelimit);
5667 if (d == 0.0) return Qnil;
5672 * Document-class: RegexpError
5674 * Raised when given an invalid regexp expression.
5678 * <em>raises the exception:</em>
5680 * RegexpError: target of repeat operator is not specified: /?/
5684 * Document-class: Regexp
5686 * :include: doc/_regexp.rdoc
5692 rb_eRegexpError = rb_define_class("RegexpError
", rb_eStandardError);
5694 onigenc_set_default_encoding(ONIG_ENCODING_ASCII);
5695 onig_set_warn_func(re_warn);
5696 onig_set_verb_warn_func(re_warn);
5698 rb_define_virtual_variable("$~
", get_LAST_MATCH_INFO, match_setter);
5699 rb_define_virtual_variable("$&
", last_match_getter, 0);
5700 rb_define_virtual_variable("$`
", prematch_getter, 0);
5701 rb_define_virtual_variable("$
'", postmatch_getter, 0);
5702 rb_define_virtual_variable("$+", last_paren_match_getter, 0);
5704 rb_gvar_ractor_local("$~");
5705 rb_gvar_ractor_local("$&");
5706 rb_gvar_ractor_local("$`");
5707 rb_gvar_ractor_local("$'");
5708 rb_gvar_ractor_local("$+
");
5709 rb_gvar_box_dynamic("$~
");
5710 rb_gvar_box_ready("$&
");
5711 rb_gvar_box_ready("$`
");
5712 rb_gvar_box_ready("$
'");
5713 rb_gvar_box_ready("$+");
5715 rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
5717 rb_cRegexp = rb_define_class("Regexp", rb_cObject);
5718 rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
5719 rb_define_singleton_method(rb_cRegexp, "compile", rb_class_new_instance_pass_kw, -1);
5720 rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
5721 rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, 1);
5722 rb_define_singleton_method(rb_cRegexp, "union", rb_reg_s_union_m, -2);
5723 rb_define_singleton_method(rb_cRegexp, "last_match", rb_reg_s_last_match, -1);
5724 rb_define_singleton_method(rb_cRegexp, "try_convert", rb_reg_s_try_convert, 1);
5725 rb_define_singleton_method(rb_cRegexp, "linear_time?", rb_reg_s_linear_time_p, -1);
5727 rb_define_method(rb_cRegexp, "initialize", rb_reg_initialize_m, -1);
5728 rb_define_method(rb_cRegexp, "initialize_copy", rb_reg_init_copy, 1);
5729 rb_define_method(rb_cRegexp, "hash", rb_reg_hash, 0);
5730 rb_define_method(rb_cRegexp, "eql?", rb_reg_equal, 1);
5731 rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
5732 rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
5733 rb_define_method(rb_cRegexp, "===", rb_reg_eqq, 1);
5734 rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
5735 rb_define_method(rb_cRegexp, "match", rb_reg_match_m, -1);
5736 rb_define_method(rb_cRegexp, "match?", rb_reg_match_m_p, -1);
5737 rb_define_method(rb_cRegexp, "to_s", rb_reg_to_s, 0);
5738 rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
5739 rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
5740 rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
5741 rb_define_method(rb_cRegexp, "options", rb_reg_options_m, 0);
5742 rb_define_method(rb_cRegexp, "encoding", rb_obj_encoding, 0); /* in encoding.c */
5743 rb_define_method(rb_cRegexp, "fixed_encoding?", rb_reg_fixed_encoding_p, 0);
5744 rb_define_method(rb_cRegexp, "names", rb_reg_names, 0);
5745 rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
5746 rb_define_method(rb_cRegexp, "timeout", rb_reg_timeout_get, 0);
5748 /* Raised when regexp matching timed out. */
5749 rb_eRegexpTimeoutError = rb_define_class_under(rb_cRegexp, "TimeoutError", rb_eRegexpError);
5750 rb_define_singleton_method(rb_cRegexp, "timeout", rb_reg_s_timeout_get, 0);
5751 rb_define_singleton_method(rb_cRegexp, "timeout=", rb_reg_s_timeout_set, 1);
5753 /* see Regexp.options and Regexp.new */
5754 rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(ONIG_OPTION_IGNORECASE));
5755 /* see Regexp.options and Regexp.new */
5756 rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(ONIG_OPTION_EXTEND));
5757 /* see Regexp.options and Regexp.new */
5758 rb_define_const(rb_cRegexp, "MULTILINE", INT2FIX(ONIG_OPTION_MULTILINE));
5759 /* see Regexp.options and Regexp.new */
5760 rb_define_const(rb_cRegexp, "FIXEDENCODING", INT2FIX(ARG_ENCODING_FIXED));
5761 /* see Regexp.options and Regexp.new */
5762 rb_define_const(rb_cRegexp, "NOENCODING", INT2FIX(ARG_ENCODING_NONE));
5764 rb_global_variable(®_cache);
5766 rb_cMatch = rb_define_class("MatchData", rb_cObject);
5767 rb_define_alloc_func(rb_cMatch, match_alloc);
5768 rb_undef_method(CLASS_OF(rb_cMatch), "new");
5769 rb_undef_method(CLASS_OF(rb_cMatch), "allocate");
5771 rb_define_method(rb_cMatch, "initialize_copy", rb_match_init_copy, 1);
5772 rb_define_method(rb_cMatch, "regexp", match_regexp, 0);
5773 rb_define_method(rb_cMatch, "names", match_names, 0);
5774 rb_define_method(rb_cMatch, "size", match_size, 0);
5775 rb_define_method(rb_cMatch, "length", match_size, 0);
5776 rb_define_method(rb_cMatch, "offset", match_offset, 1);
5777 rb_define_method(rb_cMatch, "byteoffset", match_byteoffset, 1);
5778 rb_define_method(rb_cMatch, "bytebegin", match_bytebegin, 1);
5779 rb_define_method(rb_cMatch, "byteend", match_byteend, 1);
5780 rb_define_method(rb_cMatch, "begin", match_begin, 1);
5781 rb_define_method(rb_cMatch, "end", match_end, 1);
5782 rb_define_method(rb_cMatch, "match", match_nth, 1);
5783 rb_define_method(rb_cMatch, "match_length", match_nth_length, 1);
5784 rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
5785 rb_define_method(rb_cMatch, "[]", match_aref, -1);
5786 rb_define_method(rb_cMatch, "captures", match_captures, 0);
5787 rb_define_alias(rb_cMatch, "deconstruct", "captures");
5788 rb_define_method(rb_cMatch, "named_captures", match_named_captures, -1);
5789 rb_define_method(rb_cMatch, "deconstruct_keys", match_deconstruct_keys, 1);
5790 rb_define_method(rb_cMatch, "values_at", match_values_at, -1);
5791 rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
5792 rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
5793 rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
5794 rb_define_method(rb_cMatch, "inspect", match_inspect, 0);
5795 rb_define_method(rb_cMatch, "string", match_string, 0);
5796 rb_define_method(rb_cMatch, "hash", match_hash, 0);
5797 rb_define_method(rb_cMatch, "eql?", match_equal, 1);
5798 rb_define_method(rb_cMatch, "==", match_equal, 1);
5799 rb_define_method(rb_cMatch, "integer_at", match_integer_at, -1);
#define RUBY_ATOMIC_PTR_LOAD(var)
Identical to RUBY_ATOMIC_LOAD, except it expects its arguments are void*.
#define RUBY_ATOMIC_PTR_CAS(var, oldval, newval)
Identical to RUBY_ATOMIC_CAS, except it expects its arguments are void*.
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 ALLOC
Old name of RB_ALLOC.
#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 LEN2NUM
Old name of RB_LEN2NUM.
#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 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 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 NUM2LEN
Old name of RB_NUM2LEN.
#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.
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
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, rb_len_t len, rb_encoding *enc, int opts)
Identical to rb_reg_new(), except it additionally takes an encoding.
rb_len_t 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.
rb_len_t rb_memsearch(const void *x, rb_len_t m, const void *y, rb_len_t n, rb_encoding *enc)
Looks for the passed string in the passed buffer.
rb_len_t 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(rb_len_t capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
void rb_ary_store(VALUE ary, rb_len_t key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
VALUE rb_ary_resize(VALUE ary, rb_len_t 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.
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, rb_len_t *begp, rb_len_t *lenp, rb_len_t 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, rb_len_t len, int opts)
Creates a new Regular expression.
VALUE rb_str_subseq(VALUE str, rb_len_t beg, rb_len_t len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
#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.
#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.
st_index_t rb_memhash(const void *ptr, rb_len_t len)
This is a universal hash function.
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(rb_len_t 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.
rb_len_t rb_reg_search(VALUE re, VALUE str, rb_len_t 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 ...
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.
rb_len_t rb_reg_adjust_startpos(VALUE re, VALUE str, rb_len_t pos, int dir)
Tell us if this is a wrong idea, but it seems this function has no usage at all.
unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret)
Interprets the passed string a hexadecimal unsigned integer.
unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed)
Interprets the passed string as an octal unsigned integer.
#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)
References an object in an array.
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 rb_len_t 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::@57 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 rb_regexp_variant * variants
Compiled variants for other encodings.
struct RBasic basic
Basic part, including flags and class.
const VALUE src
Source code of this expression.
Represents the region of a capture group.
rb_len_t end
End of a group.
rb_len_t beg
Beginning of a group.
long rb_len_t
A signed integer type for lengths and indices of objects such as String and Array.
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.