2003-03-24 20:11:08 -05:00
|
|
|
/*
|
2005-09-24 08:20:14 -04:00
|
|
|
$Id$
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2006-07-26 05:41:08 -04:00
|
|
|
Copyright (c) 1999-2006 Minero Aoki
|
2002-03-22 01:38:27 -05:00
|
|
|
|
|
|
|
This program is free software.
|
2020-12-17 08:40:26 -05:00
|
|
|
You can redistribute this program under the terms of the Ruby's or 2-clause
|
|
|
|
BSD License. For details, see the COPYING and LICENSE.txt files.
|
2002-03-22 01:38:27 -05:00
|
|
|
*/
|
|
|
|
|
2007-06-09 23:06:15 -04:00
|
|
|
#include "ruby/ruby.h"
|
|
|
|
#include "ruby/re.h"
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-24 23:29:39 -04:00
|
|
|
#include "ruby/encoding.h"
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
#ifdef RUBY_EXTCONF_H
|
|
|
|
# include RUBY_EXTCONF_H
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_ONIG_REGION_MEMSIZE
|
|
|
|
extern size_t onig_region_memsize(const struct re_registers *regs);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
2020-12-17 04:32:08 -05:00
|
|
|
#define STRSCAN_VERSION "3.0.0"
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
/* =======================================================================
|
|
|
|
Data Type Definitions
|
|
|
|
======================================================================= */
|
|
|
|
|
|
|
|
static VALUE StringScanner;
|
|
|
|
static VALUE ScanError;
|
2012-11-27 19:17:33 -05:00
|
|
|
static ID id_byteslice;
|
2002-08-01 20:10:19 -04:00
|
|
|
|
2002-03-22 01:38:27 -05:00
|
|
|
struct strscanner
|
|
|
|
{
|
2002-03-28 03:53:24 -05:00
|
|
|
/* multi-purpose flags */
|
2002-03-22 01:38:27 -05:00
|
|
|
unsigned long flags;
|
2002-08-01 20:10:19 -04:00
|
|
|
#define FLAG_MATCHED (1 << 0)
|
2002-03-28 03:53:24 -05:00
|
|
|
|
|
|
|
/* the string to scan */
|
2002-03-22 01:38:27 -05:00
|
|
|
VALUE str;
|
2010-04-22 04:04:13 -04:00
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
/* scan pointers */
|
|
|
|
long prev; /* legal only when MATCHED_P(s) */
|
|
|
|
long curr; /* always legal */
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
/* the regexp register; legal only when MATCHED_P(s) */
|
2002-03-22 01:38:27 -05:00
|
|
|
struct re_registers regs;
|
2013-05-21 09:48:57 -04:00
|
|
|
|
|
|
|
/* regexp used for last scan */
|
|
|
|
VALUE regex;
|
2019-10-13 23:40:50 -04:00
|
|
|
|
|
|
|
/* anchor mode */
|
|
|
|
bool fixed_anchor_p;
|
2002-03-22 01:38:27 -05:00
|
|
|
};
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
#define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
|
|
|
|
#define MATCHED(s) (s)->flags |= FLAG_MATCHED
|
|
|
|
#define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2006-08-31 06:30:33 -04:00
|
|
|
#define S_PBEG(s) (RSTRING_PTR((s)->str))
|
|
|
|
#define S_LEN(s) (RSTRING_LEN((s)->str))
|
2003-12-16 10:18:11 -05:00
|
|
|
#define S_PEND(s) (S_PBEG(s) + S_LEN(s))
|
|
|
|
#define CURPTR(s) (S_PBEG(s) + (s)->curr)
|
2002-08-01 20:10:19 -04:00
|
|
|
#define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
|
|
|
|
|
2006-08-31 06:30:33 -04:00
|
|
|
#define EOS_P(s) ((s)->curr >= RSTRING_LEN(p->str))
|
2002-08-01 20:10:19 -04:00
|
|
|
|
|
|
|
#define GET_SCANNER(obj,var) do {\
|
2011-12-15 00:48:39 -05:00
|
|
|
(var) = check_strscan(obj);\
|
2011-03-31 07:42:23 -04:00
|
|
|
if (NIL_P((var)->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
|
2002-08-01 20:10:19 -04:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/* =======================================================================
|
|
|
|
Function Prototypes
|
|
|
|
======================================================================= */
|
|
|
|
|
2016-09-28 01:11:22 -04:00
|
|
|
static inline long minl _((const long n, const long x));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
|
|
|
|
static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
|
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
static struct strscanner *check_strscan _((VALUE obj));
|
|
|
|
static void strscan_mark _((void *p));
|
|
|
|
static void strscan_free _((void *p));
|
|
|
|
static size_t strscan_memsize _((const void *p));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_s_allocate _((VALUE klass));
|
|
|
|
static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
|
2004-03-05 06:20:12 -05:00
|
|
|
static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
|
2002-08-01 20:10:19 -04:00
|
|
|
|
|
|
|
static VALUE strscan_s_mustc _((VALUE self));
|
|
|
|
static VALUE strscan_terminate _((VALUE self));
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE strscan_clear _((VALUE self));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_get_string _((VALUE self));
|
|
|
|
static VALUE strscan_set_string _((VALUE self, VALUE str));
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE strscan_concat _((VALUE self, VALUE str));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_get_pos _((VALUE self));
|
|
|
|
static VALUE strscan_set_pos _((VALUE self, VALUE pos));
|
|
|
|
static VALUE strscan_do_scan _((VALUE self, VALUE regex,
|
|
|
|
int succptr, int getstr, int headonly));
|
|
|
|
static VALUE strscan_scan _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_match_p _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_skip _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_check _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_scan_full _((VALUE self, VALUE re,
|
|
|
|
VALUE succp, VALUE getp));
|
|
|
|
static VALUE strscan_scan_until _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_skip_until _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_check_until _((VALUE self, VALUE re));
|
|
|
|
static VALUE strscan_search_full _((VALUE self, VALUE re,
|
|
|
|
VALUE succp, VALUE getp));
|
|
|
|
static void adjust_registers_to_matched _((struct strscanner *p));
|
|
|
|
static VALUE strscan_getch _((VALUE self));
|
|
|
|
static VALUE strscan_get_byte _((VALUE self));
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE strscan_getbyte _((VALUE self));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_peek _((VALUE self, VALUE len));
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE strscan_peep _((VALUE self, VALUE len));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_unscan _((VALUE self));
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE strscan_bol_p _((VALUE self));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_eos_p _((VALUE self));
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE strscan_empty_p _((VALUE self));
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE strscan_rest_p _((VALUE self));
|
|
|
|
static VALUE strscan_matched_p _((VALUE self));
|
|
|
|
static VALUE strscan_matched _((VALUE self));
|
|
|
|
static VALUE strscan_matched_size _((VALUE self));
|
|
|
|
static VALUE strscan_aref _((VALUE self, VALUE idx));
|
|
|
|
static VALUE strscan_pre_match _((VALUE self));
|
|
|
|
static VALUE strscan_post_match _((VALUE self));
|
|
|
|
static VALUE strscan_rest _((VALUE self));
|
|
|
|
static VALUE strscan_rest_size _((VALUE self));
|
|
|
|
|
|
|
|
static VALUE strscan_inspect _((VALUE self));
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE inspect1 _((struct strscanner *p));
|
|
|
|
static VALUE inspect2 _((struct strscanner *p));
|
2002-08-01 20:10:19 -04:00
|
|
|
|
|
|
|
/* =======================================================================
|
|
|
|
Utils
|
|
|
|
======================================================================= */
|
2002-03-28 03:53:24 -05:00
|
|
|
|
2007-12-28 09:55:43 -05:00
|
|
|
static VALUE
|
|
|
|
str_new(struct strscanner *p, const char *ptr, long len)
|
|
|
|
{
|
|
|
|
VALUE str = rb_str_new(ptr, len);
|
|
|
|
rb_enc_copy(str, p->str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2016-09-28 01:11:22 -04:00
|
|
|
static inline long
|
|
|
|
minl(const long x, const long y)
|
|
|
|
{
|
|
|
|
return (x < y) ? x : y;
|
|
|
|
}
|
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
extract_range(struct strscanner *p, long beg_i, long end_i)
|
2002-03-28 03:53:24 -05:00
|
|
|
{
|
2003-12-16 10:18:11 -05:00
|
|
|
if (beg_i > S_LEN(p)) return Qnil;
|
2016-09-28 01:11:22 -04:00
|
|
|
end_i = minl(end_i, S_LEN(p));
|
2019-11-14 19:56:02 -05:00
|
|
|
return str_new(p, S_PBEG(p) + beg_i, end_i - beg_i);
|
2002-03-28 03:53:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
extract_beg_len(struct strscanner *p, long beg_i, long len)
|
2002-03-28 03:53:24 -05:00
|
|
|
{
|
2003-12-16 10:18:11 -05:00
|
|
|
if (beg_i > S_LEN(p)) return Qnil;
|
2016-09-28 01:11:22 -04:00
|
|
|
len = minl(len, S_LEN(p) - beg_i);
|
2019-11-14 19:56:02 -05:00
|
|
|
return str_new(p, S_PBEG(p) + beg_i, len);
|
2002-03-28 03:53:24 -05:00
|
|
|
}
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
/* =======================================================================
|
|
|
|
Constructor
|
|
|
|
======================================================================= */
|
2002-03-22 01:38:27 -05:00
|
|
|
|
|
|
|
static void
|
2011-12-15 00:48:39 -05:00
|
|
|
strscan_mark(void *ptr)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
2011-12-15 00:48:39 -05:00
|
|
|
struct strscanner *p = ptr;
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_gc_mark(p->str);
|
2020-10-02 13:54:31 -04:00
|
|
|
rb_gc_mark(p->regex);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-12-15 00:48:39 -05:00
|
|
|
strscan_free(void *ptr)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
2011-12-15 00:48:39 -05:00
|
|
|
struct strscanner *p = ptr;
|
2005-02-17 09:43:38 -05:00
|
|
|
onig_region_free(&(p->regs), 0);
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 06:01:40 -04:00
|
|
|
ruby_xfree(p);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
static size_t
|
|
|
|
strscan_memsize(const void *ptr)
|
|
|
|
{
|
|
|
|
const struct strscanner *p = ptr;
|
2019-10-13 23:40:50 -04:00
|
|
|
size_t size = sizeof(*p) - sizeof(p->regs);
|
|
|
|
#ifdef HAVE_ONIG_REGION_MEMSIZE
|
|
|
|
size += onig_region_memsize(&p->regs);
|
|
|
|
#endif
|
|
|
|
return size;
|
2011-12-15 00:48:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static const rb_data_type_t strscanner_type = {
|
|
|
|
"StringScanner",
|
2013-10-29 07:16:54 -04:00
|
|
|
{strscan_mark, strscan_free, strscan_memsize},
|
2014-12-01 01:38:04 -05:00
|
|
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
2011-12-15 00:48:39 -05:00
|
|
|
};
|
|
|
|
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_s_allocate(VALUE klass)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
2015-05-16 08:56:48 -04:00
|
|
|
VALUE obj = TypedData_Make_Struct(klass, struct strscanner, &strscanner_type, p);
|
2010-04-22 04:04:13 -04:00
|
|
|
|
2002-03-22 01:38:27 -05:00
|
|
|
CLEAR_MATCH_STATUS(p);
|
2005-02-28 08:04:28 -05:00
|
|
|
onig_region_init(&(p->regs));
|
2002-08-01 20:10:19 -04:00
|
|
|
p->str = Qnil;
|
2020-10-02 13:54:31 -04:00
|
|
|
p->regex = Qnil;
|
2015-05-16 08:56:48 -04:00
|
|
|
return obj;
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2019-10-13 23:40:50 -04:00
|
|
|
* call-seq:
|
|
|
|
* StringScanner.new(string, fixed_anchor: false)
|
|
|
|
* StringScanner.new(string, dup = false)
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* Creates a new StringScanner object to scan over the given +string+.
|
2019-10-13 23:40:50 -04:00
|
|
|
*
|
|
|
|
* If +fixed_anchor+ is +true+, +\A+ always matches the beginning of
|
|
|
|
* the string. Otherwise, +\A+ always matches the current position.
|
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* +dup+ argument is obsolete and not used now.
|
|
|
|
*/
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_initialize(int argc, VALUE *argv, VALUE self)
|
2002-08-01 20:10:19 -04:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
2019-10-13 23:40:50 -04:00
|
|
|
VALUE str, options;
|
2002-08-01 20:10:19 -04:00
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
p = check_strscan(self);
|
2019-10-13 23:40:50 -04:00
|
|
|
rb_scan_args(argc, argv, "11", &str, &options);
|
|
|
|
options = rb_check_hash_type(options);
|
|
|
|
if (!NIL_P(options)) {
|
|
|
|
VALUE fixed_anchor;
|
|
|
|
ID keyword_ids[1];
|
|
|
|
keyword_ids[0] = rb_intern("fixed_anchor");
|
|
|
|
rb_get_kwargs(options, keyword_ids, 0, 1, &fixed_anchor);
|
|
|
|
if (fixed_anchor == Qundef) {
|
|
|
|
p->fixed_anchor_p = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
p->fixed_anchor_p = RTEST(fixed_anchor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
p->fixed_anchor_p = false;
|
|
|
|
}
|
2002-08-01 20:10:19 -04:00
|
|
|
StringValue(str);
|
2003-12-16 10:18:11 -05:00
|
|
|
p->str = str;
|
2002-08-01 20:10:19 -04:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
static struct strscanner *
|
2006-06-20 14:02:17 -04:00
|
|
|
check_strscan(VALUE obj)
|
2004-03-05 06:20:12 -05:00
|
|
|
{
|
2011-12-15 00:48:39 -05:00
|
|
|
return rb_check_typeddata(obj, &strscanner_type);
|
2004-03-05 06:20:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* dup
|
|
|
|
* clone
|
|
|
|
*
|
|
|
|
* Duplicates a StringScanner object.
|
|
|
|
*/
|
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_init_copy(VALUE vself, VALUE vorig)
|
2004-03-05 06:20:12 -05:00
|
|
|
{
|
|
|
|
struct strscanner *self, *orig;
|
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
self = check_strscan(vself);
|
|
|
|
orig = check_strscan(vorig);
|
2004-03-06 01:15:11 -05:00
|
|
|
if (self != orig) {
|
|
|
|
self->flags = orig->flags;
|
|
|
|
self->str = orig->str;
|
|
|
|
self->prev = orig->prev;
|
|
|
|
self->curr = orig->curr;
|
2014-12-01 16:30:58 -05:00
|
|
|
if (rb_reg_region_copy(&self->regs, &orig->regs))
|
|
|
|
rb_memerror();
|
|
|
|
RB_GC_GUARD(vorig);
|
2004-03-06 01:15:11 -05:00
|
|
|
}
|
2004-03-05 06:20:12 -05:00
|
|
|
|
|
|
|
return vself;
|
|
|
|
}
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
/* =======================================================================
|
|
|
|
Instance Methods
|
|
|
|
======================================================================= */
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: StringScanner.must_C_version
|
|
|
|
*
|
|
|
|
* This method is defined for backward compatibility.
|
|
|
|
*/
|
2002-08-01 20:10:19 -04:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_s_mustc(VALUE self)
|
2002-08-01 20:10:19 -04:00
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Reset the scan pointer (index 0) and clear matching data.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
strscan_reset(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-03-28 03:53:24 -05:00
|
|
|
p->curr = 0;
|
2002-03-22 01:38:27 -05:00
|
|
|
CLEAR_MATCH_STATUS(p);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* terminate
|
|
|
|
* clear
|
|
|
|
*
|
2019-10-13 23:40:50 -04:00
|
|
|
* Sets the scan pointer to the end of the string and clear matching data.
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_terminate(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-03-28 03:53:24 -05:00
|
|
|
p->curr = S_LEN(p);
|
2002-03-22 01:38:27 -05:00
|
|
|
CLEAR_MATCH_STATUS(p);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2005-03-04 05:40:09 -05:00
|
|
|
* Equivalent to #terminate.
|
|
|
|
* This method is obsolete; use #terminate instead.
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_clear(VALUE self)
|
2004-02-17 04:02:41 -05:00
|
|
|
{
|
|
|
|
rb_warning("StringScanner#clear is obsolete; use #terminate instead");
|
|
|
|
return strscan_terminate(self);
|
|
|
|
}
|
|
|
|
|
2005-03-04 05:40:09 -05:00
|
|
|
/*
|
|
|
|
* Returns the string being scanned.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_get_string(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
return p->str;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: string=(str)
|
|
|
|
*
|
|
|
|
* Changes the string being scanned to +str+ and resets the scanner.
|
|
|
|
* Returns +str+.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_set_string(VALUE self, VALUE str)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
2011-12-15 00:48:39 -05:00
|
|
|
struct strscanner *p = check_strscan(self);
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
StringValue(str);
|
2009-08-26 19:16:40 -04:00
|
|
|
p->str = str;
|
2002-03-28 03:53:24 -05:00
|
|
|
p->curr = 0;
|
2002-03-22 01:38:27 -05:00
|
|
|
CLEAR_MATCH_STATUS(p);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* concat(str)
|
|
|
|
* <<(str)
|
|
|
|
*
|
|
|
|
* Appends +str+ to the string being scanned.
|
|
|
|
* This method does not affect scan pointer.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan(/Fri /)
|
|
|
|
* s << " +1000 GMT"
|
|
|
|
* s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
|
|
|
|
* s.scan(/Dec/) # -> "Dec"
|
|
|
|
*/
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_concat(VALUE self, VALUE str)
|
2003-12-16 10:18:11 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
StringValue(str);
|
|
|
|
rb_str_append(p->str, str);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2010-01-26 02:56:36 -05:00
|
|
|
* Returns the byte position of the scan pointer. In the 'reset' position, this
|
2004-02-18 12:38:33 -05:00
|
|
|
* value is zero. In the 'terminated' position (i.e. the string is exhausted),
|
2010-01-26 02:56:36 -05:00
|
|
|
* this value is the bytesize of the string.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
2012-11-27 19:17:33 -05:00
|
|
|
* In short, it's a 0-based index into bytes of the string.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.pos # -> 0
|
|
|
|
* s.scan_until /str/ # -> "test str"
|
|
|
|
* s.pos # -> 8
|
|
|
|
* s.terminate # -> #<StringScanner fin>
|
|
|
|
* s.pos # -> 11
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_get_pos(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-03-28 03:53:24 -05:00
|
|
|
return INT2FIX(p->curr);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2012-11-27 19:17:33 -05:00
|
|
|
/*
|
|
|
|
* Returns the character position of the scan pointer. In the 'reset' position, this
|
|
|
|
* value is zero. In the 'terminated' position (i.e. the string is exhausted),
|
|
|
|
* this value is the size of the string.
|
|
|
|
*
|
|
|
|
* In short, it's a 0-based index into the string.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("abcädeföghi")
|
|
|
|
* s.charpos # -> 0
|
|
|
|
* s.scan_until(/ä/) # -> "abcä"
|
|
|
|
* s.pos # -> 5
|
|
|
|
* s.charpos # -> 4
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
strscan_get_charpos(VALUE self)
|
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
VALUE substr;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
|
2020-04-08 03:06:30 -04:00
|
|
|
substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), LONG2NUM(p->curr));
|
2012-11-27 19:17:33 -05:00
|
|
|
|
|
|
|
return rb_str_length(substr);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: pos=(n)
|
|
|
|
*
|
2019-10-13 23:40:50 -04:00
|
|
|
* Sets the byte position of the scan pointer.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.pos = 7 # -> 7
|
|
|
|
* s.rest # -> "ring"
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_set_pos(VALUE self, VALUE v)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
long i;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
i = NUM2INT(v);
|
|
|
|
if (i < 0) i += S_LEN(p);
|
|
|
|
if (i < 0) rb_raise(rb_eRangeError, "index out of range");
|
|
|
|
if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
|
2002-03-28 03:53:24 -05:00
|
|
|
p->curr = i;
|
2020-04-08 03:06:30 -04:00
|
|
|
return LONG2NUM(i);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
static inline UChar *
|
|
|
|
match_target(struct strscanner *p)
|
|
|
|
{
|
|
|
|
if (p->fixed_anchor_p) {
|
|
|
|
return (UChar *)S_PBEG(p);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return (UChar *)CURPTR(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
set_registers(struct strscanner *p, size_t length)
|
|
|
|
{
|
2019-10-14 02:10:33 -04:00
|
|
|
const int at = 0;
|
|
|
|
OnigRegion *regs = &(p->regs);
|
|
|
|
onig_region_clear(regs);
|
|
|
|
if (onig_region_set(regs, at, 0, 0)) return;
|
2019-10-13 23:40:50 -04:00
|
|
|
if (p->fixed_anchor_p) {
|
2019-10-14 02:10:33 -04:00
|
|
|
regs->beg[at] = p->curr;
|
|
|
|
regs->end[at] = p->curr + length;
|
2019-10-13 23:40:50 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-14 02:10:33 -04:00
|
|
|
regs->end[at] = length;
|
2019-10-13 23:40:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
succ(struct strscanner *p)
|
|
|
|
{
|
|
|
|
if (p->fixed_anchor_p) {
|
|
|
|
p->curr = p->regs.end[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p->curr += p->regs.end[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline long
|
|
|
|
last_match_length(struct strscanner *p)
|
|
|
|
{
|
|
|
|
if (p->fixed_anchor_p) {
|
|
|
|
return p->regs.end[0] - p->prev;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return p->regs.end[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline long
|
|
|
|
adjust_register_position(struct strscanner *p, long position)
|
|
|
|
{
|
|
|
|
if (p->fixed_anchor_p) {
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return p->prev + position;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2019-10-13 23:40:50 -04:00
|
|
|
strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
if (headonly) {
|
|
|
|
if (!RB_TYPE_P(pattern, T_REGEXP)) {
|
|
|
|
StringValue(pattern);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Check_Type(pattern, T_REGEXP);
|
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
GET_SCANNER(self, p);
|
|
|
|
|
|
|
|
CLEAR_MATCH_STATUS(p);
|
2006-07-26 05:41:08 -04:00
|
|
|
if (S_RESTLEN(p) < 0) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
2013-05-21 09:48:57 -04:00
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
if (RB_TYPE_P(pattern, T_REGEXP)) {
|
|
|
|
regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
|
|
|
|
regex_t *re;
|
|
|
|
long ret;
|
|
|
|
int tmpreg;
|
|
|
|
|
|
|
|
p->regex = pattern;
|
|
|
|
re = rb_reg_prepare_re(pattern, p->str);
|
|
|
|
tmpreg = re != RREGEXP_PTR(pattern);
|
|
|
|
if (!tmpreg) RREGEXP(pattern)->usecnt++;
|
|
|
|
|
|
|
|
if (headonly) {
|
|
|
|
ret = onig_match(re,
|
|
|
|
match_target(p),
|
|
|
|
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
|
|
|
(UChar* )CURPTR(p),
|
|
|
|
&(p->regs),
|
|
|
|
ONIG_OPTION_NONE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ret = onig_search(re,
|
|
|
|
match_target(p),
|
|
|
|
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
|
|
|
(UChar* )CURPTR(p),
|
|
|
|
(UChar* )(CURPTR(p) + S_RESTLEN(p)),
|
|
|
|
&(p->regs),
|
|
|
|
ONIG_OPTION_NONE);
|
|
|
|
}
|
|
|
|
if (!tmpreg) RREGEXP(pattern)->usecnt--;
|
|
|
|
if (tmpreg) {
|
|
|
|
if (RREGEXP(pattern)->usecnt) {
|
|
|
|
onig_free(re);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
onig_free(RREGEXP_PTR(pattern));
|
|
|
|
RREGEXP_PTR(pattern) = re;
|
|
|
|
}
|
|
|
|
}
|
2008-08-30 02:54:25 -04:00
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
|
|
|
|
if (ret < 0) {
|
|
|
|
/* not matched */
|
|
|
|
return Qnil;
|
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
else {
|
2019-10-13 23:40:50 -04:00
|
|
|
rb_enc_check(p->str, pattern);
|
|
|
|
if (S_RESTLEN(p) < RSTRING_LEN(pattern)) {
|
|
|
|
return Qnil;
|
2008-08-30 02:54:25 -04:00
|
|
|
}
|
2019-10-13 23:40:50 -04:00
|
|
|
if (memcmp(CURPTR(p), RSTRING_PTR(pattern), RSTRING_LEN(pattern)) != 0) {
|
|
|
|
return Qnil;
|
2008-08-30 02:54:25 -04:00
|
|
|
}
|
2019-10-13 23:40:50 -04:00
|
|
|
set_registers(p, RSTRING_LEN(pattern));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
2002-03-28 03:53:24 -05:00
|
|
|
|
|
|
|
MATCHED(p);
|
|
|
|
p->prev = p->curr;
|
2019-10-13 23:40:50 -04:00
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
if (succptr) {
|
2019-10-13 23:40:50 -04:00
|
|
|
succ(p);
|
2002-03-28 03:53:24 -05:00
|
|
|
}
|
2019-10-13 23:40:50 -04:00
|
|
|
{
|
|
|
|
const long length = last_match_length(p);
|
|
|
|
if (getstr) {
|
|
|
|
return extract_beg_len(p, p->prev, length);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return INT2FIX(length);
|
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2005-09-24 08:20:14 -04:00
|
|
|
* call-seq: scan(pattern) => String
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* Tries to match with +pattern+ at the current position. If there's a match,
|
|
|
|
* the scanner advances the "scan pointer" and returns the matched string.
|
|
|
|
* Otherwise, the scanner returns +nil+.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* p s.scan(/\w+/) # -> "test"
|
|
|
|
* p s.scan(/\w+/) # -> nil
|
|
|
|
* p s.scan(/\s+/) # -> " "
|
2019-10-13 23:40:50 -04:00
|
|
|
* p s.scan("str") # -> "str"
|
|
|
|
* p s.scan(/\w+/) # -> "ing"
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.scan(/./) # -> nil
|
|
|
|
*
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_scan(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 1, 1, 1);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: match?(pattern)
|
|
|
|
*
|
|
|
|
* Tests whether the given +pattern+ is matched from the current scan pointer.
|
|
|
|
* Returns the length of the match, or +nil+. The scan pointer is not advanced.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* p s.match?(/\w+/) # -> 4
|
|
|
|
* p s.match?(/\w+/) # -> 4
|
2019-10-13 23:40:50 -04:00
|
|
|
* p s.match?("test") # -> 4
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.match?(/\s+/) # -> nil
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_match_p(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 0, 0, 1);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: skip(pattern)
|
|
|
|
*
|
|
|
|
* Attempts to skip over the given +pattern+ beginning with the scan pointer.
|
|
|
|
* If it matches, the scan pointer is advanced to the end of the match, and the
|
|
|
|
* length of the match is returned. Otherwise, +nil+ is returned.
|
|
|
|
*
|
|
|
|
* It's similar to #scan, but without returning the matched string.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* p s.skip(/\w+/) # -> 4
|
|
|
|
* p s.skip(/\w+/) # -> nil
|
|
|
|
* p s.skip(/\s+/) # -> 1
|
2019-10-13 23:40:50 -04:00
|
|
|
* p s.skip("st") # -> 2
|
|
|
|
* p s.skip(/\w+/) # -> 4
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.skip(/./) # -> nil
|
|
|
|
*
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_skip(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 1, 0, 1);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: check(pattern)
|
|
|
|
*
|
|
|
|
* This returns the value that #scan would return, without advancing the scan
|
|
|
|
* pointer. The match register is affected, though.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.check /Fri/ # -> "Fri"
|
|
|
|
* s.pos # -> 0
|
|
|
|
* s.matched # -> "Fri"
|
|
|
|
* s.check /12/ # -> nil
|
|
|
|
* s.matched # -> nil
|
|
|
|
*
|
|
|
|
* Mnemonic: it "checks" to see whether a #scan will return a value.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_check(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 0, 1, 1);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2008-06-03 10:07:50 -04:00
|
|
|
* call-seq: scan_full(pattern, advance_pointer_p, return_string_p)
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* Tests whether the given +pattern+ is matched from the current scan pointer.
|
|
|
|
* Advances the scan pointer if +advance_pointer_p+ is true.
|
2008-06-03 10:07:50 -04:00
|
|
|
* Returns the matched string if +return_string_p+ is true.
|
2004-02-18 12:38:33 -05:00
|
|
|
* The match register is affected.
|
|
|
|
*
|
|
|
|
* "full" means "#scan with full parameters".
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: scan_until(pattern)
|
|
|
|
*
|
|
|
|
* Scans the string _until_ the +pattern+ is matched. Returns the substring up
|
|
|
|
* to and including the end of the match, advancing the scan pointer to that
|
|
|
|
* location. If there is no match, +nil+ is returned.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan_until(/1/) # -> "Fri Dec 1"
|
|
|
|
* s.pre_match # -> "Fri Dec "
|
|
|
|
* s.scan_until(/XYZ/) # -> nil
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_scan_until(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 1, 1, 0);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: exist?(pattern)
|
|
|
|
*
|
|
|
|
* Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
|
|
|
|
* without advancing the scan pointer. This predicates whether a #scan_until
|
|
|
|
* will return a value.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.exist? /s/ # -> 3
|
|
|
|
* s.scan /test/ # -> "test"
|
2008-06-03 09:37:59 -04:00
|
|
|
* s.exist? /s/ # -> 2
|
2004-02-18 12:38:33 -05:00
|
|
|
* s.exist? /e/ # -> nil
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
strscan_exist_p(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: skip_until(pattern)
|
|
|
|
*
|
|
|
|
* Advances the scan pointer until +pattern+ is matched and consumed. Returns
|
|
|
|
* the number of bytes advanced, or +nil+ if no match was found.
|
|
|
|
*
|
|
|
|
* Look ahead to match +pattern+, and advance the scan pointer to the _end_
|
|
|
|
* of the match. Return the number of characters advanced, or +nil+ if the
|
|
|
|
* match was unsuccessful.
|
|
|
|
*
|
|
|
|
* It's similar to #scan_until, but without returning the intervening string.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.skip_until /12/ # -> 10
|
2010-04-22 04:04:13 -04:00
|
|
|
* s #
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_skip_until(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 1, 0, 0);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: check_until(pattern)
|
|
|
|
*
|
|
|
|
* This returns the value that #scan_until would return, without advancing the
|
|
|
|
* scan pointer. The match register is affected, though.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.check_until /12/ # -> "Fri Dec 12"
|
|
|
|
* s.pos # -> 0
|
|
|
|
* s.matched # -> 12
|
|
|
|
*
|
|
|
|
* Mnemonic: it "checks" to see whether a #scan_until will return a value.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_check_until(VALUE self, VALUE re)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, 0, 1, 0);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2008-06-03 10:07:50 -04:00
|
|
|
* call-seq: search_full(pattern, advance_pointer_p, return_string_p)
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* Scans the string _until_ the +pattern+ is matched.
|
2008-06-03 10:07:50 -04:00
|
|
|
* Advances the scan pointer if +advance_pointer_p+, otherwise not.
|
2004-02-18 12:38:33 -05:00
|
|
|
* Returns the matched string if +return_string_p+ is true, otherwise
|
|
|
|
* returns the number of bytes advanced.
|
|
|
|
* This method does affect the match register.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
|
|
|
|
}
|
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
static void
|
2006-06-20 14:02:17 -04:00
|
|
|
adjust_registers_to_matched(struct strscanner *p)
|
2002-03-28 03:53:24 -05:00
|
|
|
{
|
2005-02-28 08:04:28 -05:00
|
|
|
onig_region_clear(&(p->regs));
|
2019-10-13 23:40:50 -04:00
|
|
|
if (p->fixed_anchor_p) {
|
|
|
|
onig_region_set(&(p->regs), 0, (int)p->prev, (int)p->curr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
onig_region_set(&(p->regs), 0, 0, (int)(p->curr - p->prev));
|
|
|
|
}
|
2002-03-28 03:53:24 -05:00
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Scans one character and returns it.
|
2005-09-24 08:20:14 -04:00
|
|
|
* This method is multibyte character sensitive.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
2005-09-24 08:20:14 -04:00
|
|
|
* s = StringScanner.new("ab")
|
2004-02-18 12:38:33 -05:00
|
|
|
* s.getch # => "a"
|
|
|
|
* s.getch # => "b"
|
|
|
|
* s.getch # => nil
|
2005-09-24 08:20:14 -04:00
|
|
|
*
|
2020-08-31 08:47:25 -04:00
|
|
|
* s = StringScanner.new("\244\242".force_encoding("euc-jp"))
|
|
|
|
* s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP
|
2005-09-24 08:20:14 -04:00
|
|
|
* s.getch # => nil
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_getch(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
long len;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
CLEAR_MATCH_STATUS(p);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (EOS_P(p))
|
2002-03-22 01:38:27 -05:00
|
|
|
return Qnil;
|
|
|
|
|
2007-09-24 04:56:24 -04:00
|
|
|
len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
|
2016-09-28 01:11:22 -04:00
|
|
|
len = minl(len, S_RESTLEN(p));
|
2002-03-28 03:53:24 -05:00
|
|
|
p->prev = p->curr;
|
|
|
|
p->curr += len;
|
|
|
|
MATCHED(p);
|
|
|
|
adjust_registers_to_matched(p);
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.beg[0]),
|
|
|
|
adjust_register_position(p, p->regs.end[0]));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2005-09-24 08:20:14 -04:00
|
|
|
* Scans one byte and returns it.
|
|
|
|
* This method is not multibyte character sensitive.
|
|
|
|
* See also: #getch.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
2005-09-24 08:20:14 -04:00
|
|
|
* s = StringScanner.new('ab')
|
|
|
|
* s.get_byte # => "a"
|
|
|
|
* s.get_byte # => "b"
|
|
|
|
* s.get_byte # => nil
|
|
|
|
*
|
2020-08-31 08:47:25 -04:00
|
|
|
* s = StringScanner.new("\244\242".force_encoding("euc-jp"))
|
|
|
|
* s.get_byte # => "\xA4"
|
|
|
|
* s.get_byte # => "\xA2"
|
2005-09-24 08:20:14 -04:00
|
|
|
* s.get_byte # => nil
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_get_byte(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
CLEAR_MATCH_STATUS(p);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (EOS_P(p))
|
2002-03-22 01:38:27 -05:00
|
|
|
return Qnil;
|
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
p->prev = p->curr;
|
|
|
|
p->curr++;
|
|
|
|
MATCHED(p);
|
|
|
|
adjust_registers_to_matched(p);
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.beg[0]),
|
|
|
|
adjust_register_position(p, p->regs.end[0]));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2005-03-04 05:40:09 -05:00
|
|
|
/*
|
|
|
|
* Equivalent to #get_byte.
|
|
|
|
* This method is obsolete; use #get_byte instead.
|
|
|
|
*/
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_getbyte(VALUE self)
|
2004-02-17 04:02:41 -05:00
|
|
|
{
|
|
|
|
rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
|
|
|
|
return strscan_get_byte(self);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: peek(len)
|
|
|
|
*
|
|
|
|
* Extracts a string corresponding to <tt>string[pos,len]</tt>, without
|
|
|
|
* advancing the scan pointer.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.peek(7) # => "test st"
|
|
|
|
* s.peek(7) # => "test st"
|
|
|
|
*
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_peek(VALUE self, VALUE vlen)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
long len;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
|
|
|
|
len = NUM2LONG(vlen);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (EOS_P(p))
|
2019-11-14 19:56:02 -05:00
|
|
|
return str_new(p, "", 0);
|
2002-03-28 03:53:24 -05:00
|
|
|
|
2016-09-28 01:11:22 -04:00
|
|
|
len = minl(len, S_RESTLEN(p));
|
2002-03-28 03:53:24 -05:00
|
|
|
return extract_beg_len(p, p->curr, len);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2005-03-04 05:40:09 -05:00
|
|
|
/*
|
|
|
|
* Equivalent to #peek.
|
|
|
|
* This method is obsolete; use #peek instead.
|
|
|
|
*/
|
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_peep(VALUE self, VALUE vlen)
|
2005-03-04 05:40:09 -05:00
|
|
|
{
|
|
|
|
rb_warning("StringScanner#peep is obsolete; use #peek instead");
|
|
|
|
return strscan_peek(self, vlen);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2019-10-13 23:40:50 -04:00
|
|
|
* Sets the scan pointer to the previous position. Only one previous position is
|
2004-02-18 12:38:33 -05:00
|
|
|
* remembered, and it changes with each scanning operation.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.scan(/\w+/) # => "test"
|
|
|
|
* s.unscan
|
|
|
|
* s.scan(/../) # => "te"
|
|
|
|
* s.scan(/\d/) # => nil
|
2005-09-24 08:20:14 -04:00
|
|
|
* s.unscan # ScanError: unscan failed: previous match record not exist
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_unscan(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-03-28 03:53:24 -05:00
|
|
|
if (! MATCHED_P(p))
|
2005-09-24 08:20:14 -04:00
|
|
|
rb_raise(ScanError, "unscan failed: previous match record not exist");
|
2002-03-28 03:53:24 -05:00
|
|
|
p->curr = p->prev;
|
|
|
|
CLEAR_MATCH_STATUS(p);
|
|
|
|
return self;
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns +true+ iff the scan pointer is at the beginning of the line.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("test\ntest\n")
|
|
|
|
* s.bol? # => true
|
|
|
|
* s.scan(/te/)
|
|
|
|
* s.bol? # => false
|
|
|
|
* s.scan(/st\n/)
|
|
|
|
* s.bol? # => true
|
|
|
|
* s.terminate
|
|
|
|
* s.bol? # => true
|
|
|
|
*/
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_bol_p(VALUE self)
|
2003-12-16 10:18:11 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (CURPTR(p) > S_PEND(p)) return Qnil;
|
|
|
|
if (p->curr == 0) return Qtrue;
|
|
|
|
return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
|
|
|
|
}
|
2002-03-28 03:53:24 -05:00
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns +true+ if the scan pointer is at the end of the string.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* p s.eos? # => false
|
|
|
|
* s.scan(/test/)
|
|
|
|
* p s.eos? # => false
|
|
|
|
* s.terminate
|
|
|
|
* p s.eos? # => true
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_eos_p(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2005-09-24 08:20:14 -04:00
|
|
|
return EOS_P(p) ? Qtrue : Qfalse;
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Equivalent to #eos?.
|
|
|
|
* This method is obsolete, use #eos? instead.
|
|
|
|
*/
|
2004-02-17 04:02:41 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_empty_p(VALUE self)
|
2004-02-17 04:02:41 -05:00
|
|
|
{
|
2004-02-18 12:38:33 -05:00
|
|
|
rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
|
2004-02-17 04:02:41 -05:00
|
|
|
return strscan_eos_p(self);
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns true iff there is more data in the string. See #eos?.
|
|
|
|
* This method is obsolete; use #eos? instead.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.eos? # These two
|
|
|
|
* s.rest? # are opposites.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_rest_p(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2005-09-24 08:20:14 -04:00
|
|
|
return EOS_P(p) ? Qfalse : Qtrue;
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns +true+ iff the last match was successful.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.match?(/\w+/) # => 4
|
|
|
|
* s.matched? # => true
|
|
|
|
* s.match?(/\d+/) # => nil
|
|
|
|
* s.matched? # => false
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_matched_p(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2005-09-24 08:20:14 -04:00
|
|
|
return MATCHED_P(p) ? Qtrue : Qfalse;
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns the last matched string.
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.match?(/\w+/) # -> 4
|
|
|
|
* s.matched # -> "test"
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_matched(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.beg[0]),
|
|
|
|
adjust_register_position(p, p->regs.end[0]));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2020-09-02 13:40:17 -04:00
|
|
|
* Returns the size of the most recent match in bytes, or +nil+ if there
|
|
|
|
* was no recent match. This is different than <tt>matched.size</tt>,
|
|
|
|
* which will return the size in characters.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.check /\w+/ # -> "test"
|
|
|
|
* s.matched_size # -> 4
|
|
|
|
* s.check /\d+/ # -> nil
|
|
|
|
* s.matched_size # -> nil
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_matched_size(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
2020-04-08 03:06:30 -04:00
|
|
|
return LONG2NUM(p->regs.end[0] - p->regs.beg[0]);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2013-05-24 03:32:45 -04:00
|
|
|
static int
|
2014-08-02 21:56:31 -04:00
|
|
|
name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end, rb_encoding *enc)
|
2013-05-24 03:32:45 -04:00
|
|
|
{
|
|
|
|
int num;
|
|
|
|
|
2016-02-01 23:39:44 -05:00
|
|
|
num = onig_name_to_backref_number(RREGEXP_PTR(regexp),
|
2013-05-24 03:32:45 -04:00
|
|
|
(const unsigned char* )name, (const unsigned char* )name_end, regs);
|
|
|
|
if (num >= 1) {
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
else {
|
2014-08-02 21:56:31 -04:00
|
|
|
rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s",
|
|
|
|
rb_long2int(name_end - name), name);
|
2013-05-24 03:32:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* call-seq: [](n)
|
|
|
|
*
|
2017-12-08 17:42:19 -05:00
|
|
|
* Returns the n-th subgroup in the most recent match.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
|
|
|
|
* s[0] # -> "Fri Dec 12 "
|
|
|
|
* s[1] # -> "Fri"
|
|
|
|
* s[2] # -> "Dec"
|
|
|
|
* s[3] # -> "12"
|
|
|
|
* s.post_match # -> "1975 14:39"
|
|
|
|
* s.pre_match # -> ""
|
2013-05-21 09:48:57 -04:00
|
|
|
*
|
|
|
|
* s.reset
|
|
|
|
* s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 "
|
|
|
|
* s[0] # -> "Fri Dec 12 "
|
|
|
|
* s[1] # -> "Fri"
|
|
|
|
* s[2] # -> "Dec"
|
|
|
|
* s[3] # -> "12"
|
|
|
|
* s[:wday] # -> "Fri"
|
|
|
|
* s[:month] # -> "Dec"
|
|
|
|
* s[:day] # -> "12"
|
|
|
|
* s.post_match # -> "1975 14:39"
|
|
|
|
* s.pre_match # -> ""
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_aref(VALUE self, VALUE idx)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
2013-05-25 07:37:35 -04:00
|
|
|
const char *name;
|
2002-03-22 01:38:27 -05:00
|
|
|
struct strscanner *p;
|
2002-03-28 03:53:24 -05:00
|
|
|
long i;
|
2002-03-22 01:38:27 -05:00
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-03-28 03:53:24 -05:00
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
2010-04-22 04:04:13 -04:00
|
|
|
|
2013-05-21 09:48:57 -04:00
|
|
|
switch (TYPE(idx)) {
|
|
|
|
case T_SYMBOL:
|
2014-08-02 21:56:16 -04:00
|
|
|
idx = rb_sym2str(idx);
|
2014-08-02 21:56:31 -04:00
|
|
|
/* fall through */
|
2013-05-21 09:48:57 -04:00
|
|
|
case T_STRING:
|
2020-10-02 13:54:31 -04:00
|
|
|
if (!RTEST(p->regex)) return Qnil;
|
2014-08-02 21:56:31 -04:00
|
|
|
RSTRING_GETMEM(idx, name, i);
|
|
|
|
i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx));
|
2013-05-21 09:48:57 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
i = NUM2LONG(idx);
|
|
|
|
}
|
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
if (i < 0)
|
|
|
|
i += p->regs.num_regs;
|
|
|
|
if (i < 0) return Qnil;
|
|
|
|
if (i >= p->regs.num_regs) return Qnil;
|
|
|
|
if (p->regs.beg[i] == -1) return Qnil;
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.beg[i]),
|
|
|
|
adjust_register_position(p, p->regs.end[i]));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2017-11-29 02:57:48 -05:00
|
|
|
/*
|
|
|
|
* call-seq: size
|
|
|
|
*
|
2017-12-08 17:42:19 -05:00
|
|
|
* Returns the amount of subgroups in the most recent match.
|
2017-11-29 02:57:48 -05:00
|
|
|
* The full match counts as a subgroup.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
|
|
|
|
* s.size # -> 4
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
strscan_size(VALUE self)
|
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
|
|
|
return INT2FIX(p->regs.num_regs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq: captures
|
|
|
|
*
|
|
|
|
* Returns the subgroups in the most recent match (not including the full match).
|
|
|
|
* If nothing was priorly matched, it returns nil.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
|
|
|
|
* s.captures # -> ["Fri", "Dec", "12"]
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> nil
|
|
|
|
* s.captures # -> nil
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
strscan_captures(VALUE self)
|
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
int i, num_regs;
|
|
|
|
VALUE new_ary;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
|
|
|
|
|
|
|
num_regs = p->regs.num_regs;
|
|
|
|
new_ary = rb_ary_new2(num_regs);
|
|
|
|
|
|
|
|
for (i = 1; i < num_regs; i++) {
|
2019-10-13 23:40:50 -04:00
|
|
|
VALUE str = extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.beg[i]),
|
|
|
|
adjust_register_position(p, p->regs.end[i]));
|
2017-11-29 02:57:48 -05:00
|
|
|
rb_ary_push(new_ary, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* scanner.values_at( i1, i2, ... iN ) -> an_array
|
|
|
|
*
|
|
|
|
* Returns the subgroups in the most recent match at the given indices.
|
|
|
|
* If nothing was priorly matched, it returns nil.
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
|
|
|
|
* s.values_at 0, -1, 5, 2 # -> ["Fri Dec 12 ", "12", nil, "Dec"]
|
|
|
|
* s.scan(/(\w+) (\w+) (\d+) /) # -> nil
|
|
|
|
* s.values_at 0, -1, 5, 2 # -> nil
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
strscan_values_at(int argc, VALUE *argv, VALUE self)
|
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
long i;
|
|
|
|
VALUE new_ary;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
|
|
|
|
|
|
|
new_ary = rb_ary_new2(argc);
|
|
|
|
for (i = 0; i<argc; i++) {
|
|
|
|
rb_ary_push(new_ary, strscan_aref(self, argv[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_ary;
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2017-12-08 17:42:19 -05:00
|
|
|
* Returns the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.scan(/\w+/) # -> "test"
|
|
|
|
* s.scan(/\s+/) # -> " "
|
|
|
|
* s.pre_match # -> "test"
|
|
|
|
* s.post_match # -> "string"
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_pre_match(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
0,
|
|
|
|
adjust_register_position(p, p->regs.beg[0]));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2017-12-08 17:42:19 -05:00
|
|
|
* Returns the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* s = StringScanner.new('test string')
|
|
|
|
* s.scan(/\w+/) # -> "test"
|
|
|
|
* s.scan(/\s+/) # -> " "
|
|
|
|
* s.pre_match # -> "test"
|
|
|
|
* s.post_match # -> "string"
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_post_match(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
|
|
|
if (! MATCHED_P(p)) return Qnil;
|
2019-10-13 23:40:50 -04:00
|
|
|
return extract_range(p,
|
|
|
|
adjust_register_position(p, p->regs.end[0]),
|
|
|
|
S_LEN(p));
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns the "rest" of the string (i.e. everything after the scan pointer).
|
2004-02-18 13:06:14 -05:00
|
|
|
* If there is no more data (eos? = true), it returns <tt>""</tt>.
|
2004-02-18 12:38:33 -05:00
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_rest(VALUE self)
|
2002-03-28 03:53:24 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (EOS_P(p)) {
|
2019-11-14 19:56:02 -05:00
|
|
|
return str_new(p, "", 0);
|
2002-03-28 03:53:24 -05:00
|
|
|
}
|
|
|
|
return extract_range(p, p->curr, S_LEN(p));
|
|
|
|
}
|
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
|
|
|
|
*/
|
2002-03-28 03:53:24 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_rest_size(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
long i;
|
|
|
|
|
|
|
|
GET_SCANNER(self, p);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (EOS_P(p)) {
|
2002-03-28 03:53:24 -05:00
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
2016-09-28 01:11:20 -04:00
|
|
|
i = S_RESTLEN(p);
|
2002-03-28 03:53:24 -05:00
|
|
|
return INT2FIX(i);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2004-02-18 13:06:14 -05:00
|
|
|
/*
|
|
|
|
* <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
|
|
|
|
* This method is obsolete; use #rest_size instead.
|
|
|
|
*/
|
|
|
|
static VALUE
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
strscan_restsize(VALUE self)
|
2004-02-18 13:06:14 -05:00
|
|
|
{
|
|
|
|
rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
|
|
|
|
return strscan_rest_size(self);
|
|
|
|
}
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
#define INSPECT_LENGTH 5
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
|
|
|
* Returns a string that represents the StringScanner object, showing:
|
|
|
|
* - the current position
|
|
|
|
* - the size of the string
|
|
|
|
* - the characters surrounding the scan pointer
|
|
|
|
*
|
|
|
|
* s = StringScanner.new("Fri Dec 12 1975 14:39")
|
|
|
|
* s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
|
|
|
|
* s.scan_until /12/ # -> "Fri Dec 12"
|
|
|
|
* s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
strscan_inspect(VALUE self)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
|
|
|
struct strscanner *p;
|
2003-12-16 10:18:11 -05:00
|
|
|
VALUE a, b;
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2011-12-15 00:48:39 -05:00
|
|
|
p = check_strscan(self);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (NIL_P(p->str)) {
|
2014-01-12 19:57:36 -05:00
|
|
|
a = rb_sprintf("#<%"PRIsVALUE" (uninitialized)>", rb_obj_class(self));
|
2019-11-14 19:56:02 -05:00
|
|
|
return a;
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
|
|
|
if (EOS_P(p)) {
|
2014-01-12 19:57:36 -05:00
|
|
|
a = rb_sprintf("#<%"PRIsVALUE" fin>", rb_obj_class(self));
|
2019-11-14 19:56:02 -05:00
|
|
|
return a;
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
2003-12-16 10:18:11 -05:00
|
|
|
if (p->curr == 0) {
|
2014-01-12 03:11:36 -05:00
|
|
|
b = inspect2(p);
|
|
|
|
a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld @ %"PRIsVALUE">",
|
2014-01-12 19:57:36 -05:00
|
|
|
rb_obj_class(self),
|
2014-01-12 03:11:36 -05:00
|
|
|
p->curr, S_LEN(p),
|
|
|
|
b);
|
2019-11-14 19:56:02 -05:00
|
|
|
return a;
|
2003-12-16 10:18:11 -05:00
|
|
|
}
|
|
|
|
a = inspect1(p);
|
|
|
|
b = inspect2(p);
|
2014-01-12 03:11:36 -05:00
|
|
|
a = rb_sprintf("#<%"PRIsVALUE" %ld/%ld %"PRIsVALUE" @ %"PRIsVALUE">",
|
2014-01-12 19:57:36 -05:00
|
|
|
rb_obj_class(self),
|
2014-01-12 03:11:36 -05:00
|
|
|
p->curr, S_LEN(p),
|
|
|
|
a, b);
|
2019-11-14 19:56:02 -05:00
|
|
|
return a;
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
|
|
|
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
inspect1(struct strscanner *p)
|
2002-08-01 20:10:19 -04:00
|
|
|
{
|
2014-01-13 21:48:07 -05:00
|
|
|
VALUE str;
|
2002-08-01 20:10:19 -04:00
|
|
|
long len;
|
|
|
|
|
2003-12-16 10:18:11 -05:00
|
|
|
if (p->curr == 0) return rb_str_new2("");
|
2002-08-01 20:10:19 -04:00
|
|
|
if (p->curr > INSPECT_LENGTH) {
|
2014-01-13 21:48:07 -05:00
|
|
|
str = rb_str_new_cstr("...");
|
|
|
|
len = INSPECT_LENGTH;
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
|
|
|
else {
|
2014-01-13 21:48:07 -05:00
|
|
|
str = rb_str_new(0, 0);
|
|
|
|
len = p->curr;
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
2014-01-13 22:23:20 -05:00
|
|
|
rb_str_cat(str, CURPTR(p) - len, len);
|
2014-01-13 21:48:07 -05:00
|
|
|
return rb_str_dump(str);
|
2002-08-01 20:10:19 -04:00
|
|
|
}
|
|
|
|
|
2003-12-16 10:18:11 -05:00
|
|
|
static VALUE
|
2006-06-20 14:02:17 -04:00
|
|
|
inspect2(struct strscanner *p)
|
2002-08-01 20:10:19 -04:00
|
|
|
{
|
2014-01-12 03:11:36 -05:00
|
|
|
VALUE str;
|
2002-08-01 20:10:19 -04:00
|
|
|
long len;
|
|
|
|
|
2003-12-16 10:18:11 -05:00
|
|
|
if (EOS_P(p)) return rb_str_new2("");
|
2016-09-28 01:11:20 -04:00
|
|
|
len = S_RESTLEN(p);
|
2002-08-01 20:10:19 -04:00
|
|
|
if (len > INSPECT_LENGTH) {
|
2014-01-12 03:11:36 -05:00
|
|
|
str = rb_str_new(CURPTR(p), INSPECT_LENGTH);
|
|
|
|
rb_str_cat2(str, "...");
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
else {
|
2014-01-12 03:11:36 -05:00
|
|
|
str = rb_str_new(CURPTR(p), len);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
2014-01-12 03:11:36 -05:00
|
|
|
return rb_str_dump(str);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|
|
|
|
|
2019-10-13 23:40:50 -04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* scanner.fixed_anchor? -> true or false
|
|
|
|
*
|
|
|
|
* Whether +scanner+ uses fixed anchor mode or not.
|
|
|
|
*
|
|
|
|
* If fixed anchor mode is used, +\A+ always matches the beginning of
|
|
|
|
* the string. Otherwise, +\A+ always matches the current position.
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
strscan_fixed_anchor_p(VALUE self)
|
|
|
|
{
|
|
|
|
struct strscanner *p;
|
|
|
|
p = check_strscan(self);
|
|
|
|
return p->fixed_anchor_p ? Qtrue : Qfalse;
|
|
|
|
}
|
|
|
|
|
2002-08-01 20:10:19 -04:00
|
|
|
/* =======================================================================
|
|
|
|
Ruby Interface
|
|
|
|
======================================================================= */
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2004-02-18 12:38:33 -05:00
|
|
|
/*
|
2004-02-19 07:32:09 -05:00
|
|
|
* Document-class: StringScanner
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* StringScanner provides for lexical scanning operations on a String. Here is
|
|
|
|
* an example of its usage:
|
|
|
|
*
|
|
|
|
* s = StringScanner.new('This is an example string')
|
|
|
|
* s.eos? # -> false
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.scan(/\w+/) # -> "This"
|
|
|
|
* p s.scan(/\w+/) # -> nil
|
|
|
|
* p s.scan(/\s+/) # -> " "
|
|
|
|
* p s.scan(/\s+/) # -> nil
|
|
|
|
* p s.scan(/\w+/) # -> "is"
|
|
|
|
* s.eos? # -> false
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.scan(/\s+/) # -> " "
|
|
|
|
* p s.scan(/\w+/) # -> "an"
|
|
|
|
* p s.scan(/\s+/) # -> " "
|
|
|
|
* p s.scan(/\w+/) # -> "example"
|
|
|
|
* p s.scan(/\s+/) # -> " "
|
|
|
|
* p s.scan(/\w+/) # -> "string"
|
|
|
|
* s.eos? # -> true
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* p s.scan(/\s+/) # -> nil
|
|
|
|
* p s.scan(/\w+/) # -> nil
|
|
|
|
*
|
|
|
|
* Scanning a string means remembering the position of a <i>scan pointer</i>,
|
2004-02-19 07:32:09 -05:00
|
|
|
* which is just an index. The point of scanning is to move forward a bit at
|
|
|
|
* a time, so matches are sought after the scan pointer; usually immediately
|
|
|
|
* after it.
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* Given the string "test string", here are the pertinent scan pointer
|
|
|
|
* positions:
|
|
|
|
*
|
|
|
|
* t e s t s t r i n g
|
|
|
|
* 0 1 2 ... 1
|
|
|
|
* 0
|
|
|
|
*
|
|
|
|
* When you #scan for a pattern (a regular expression), the match must occur
|
|
|
|
* at the character after the scan pointer. If you use #scan_until, then the
|
|
|
|
* match can occur anywhere after the scan pointer. In both cases, the scan
|
|
|
|
* pointer moves <i>just beyond</i> the last character of the match, ready to
|
|
|
|
* scan again from the next character onwards. This is demonstrated by the
|
|
|
|
* example above.
|
|
|
|
*
|
|
|
|
* == Method Categories
|
|
|
|
*
|
|
|
|
* There are other methods besides the plain scanners. You can look ahead in
|
|
|
|
* the string without actually scanning. You can access the most recent match.
|
|
|
|
* You can modify the string being scanned, reset or terminate the scanner,
|
|
|
|
* find out or change the position of the scan pointer, skip ahead, and so on.
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* === Advancing the Scan Pointer
|
|
|
|
*
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #getch
|
2005-09-24 08:20:14 -04:00
|
|
|
* - #get_byte
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #scan
|
|
|
|
* - #scan_until
|
|
|
|
* - #skip
|
|
|
|
* - #skip_until
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* === Looking Ahead
|
|
|
|
*
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #check
|
|
|
|
* - #check_until
|
|
|
|
* - #exist?
|
|
|
|
* - #match?
|
|
|
|
* - #peek
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* === Finding Where we Are
|
|
|
|
*
|
2005-09-24 08:20:14 -04:00
|
|
|
* - #beginning_of_line? (#bol?)
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #eos?
|
|
|
|
* - #rest?
|
|
|
|
* - #rest_size
|
|
|
|
* - #pos
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* === Setting Where we Are
|
|
|
|
*
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #reset
|
|
|
|
* - #terminate
|
|
|
|
* - #pos=
|
2010-04-22 04:04:13 -04:00
|
|
|
*
|
2004-02-18 12:38:33 -05:00
|
|
|
* === Match Data
|
|
|
|
*
|
2004-02-19 07:32:09 -05:00
|
|
|
* - #matched
|
|
|
|
* - #matched?
|
|
|
|
* - #matched_size
|
|
|
|
* - []
|
|
|
|
* - #pre_match
|
|
|
|
* - #post_match
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* === Miscellaneous
|
|
|
|
*
|
2004-02-19 07:32:09 -05:00
|
|
|
* - <<
|
|
|
|
* - #concat
|
|
|
|
* - #string
|
|
|
|
* - #string=
|
|
|
|
* - #unscan
|
2004-02-18 12:38:33 -05:00
|
|
|
*
|
|
|
|
* There are aliases to several of the methods.
|
|
|
|
*/
|
2002-03-22 01:38:27 -05:00
|
|
|
void
|
2014-09-30 01:25:32 -04:00
|
|
|
Init_strscan(void)
|
2002-03-22 01:38:27 -05:00
|
|
|
{
|
2020-12-17 04:29:21 -05:00
|
|
|
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
|
|
rb_ext_ractor_safe(true);
|
|
|
|
#endif
|
|
|
|
|
2018-02-16 03:39:48 -05:00
|
|
|
#undef rb_intern
|
2004-02-18 12:42:54 -05:00
|
|
|
ID id_scanerr = rb_intern("ScanError");
|
|
|
|
VALUE tmp;
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2012-11-27 19:17:33 -05:00
|
|
|
id_byteslice = rb_intern("byteslice");
|
|
|
|
|
2002-03-22 01:38:27 -05:00
|
|
|
StringScanner = rb_define_class("StringScanner", rb_cObject);
|
2004-02-18 12:42:54 -05:00
|
|
|
ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
|
|
|
|
if (!rb_const_defined(rb_cObject, id_scanerr)) {
|
|
|
|
rb_const_set(rb_cObject, id_scanerr, ScanError);
|
|
|
|
}
|
2002-03-22 01:38:27 -05:00
|
|
|
tmp = rb_str_new2(STRSCAN_VERSION);
|
|
|
|
rb_obj_freeze(tmp);
|
|
|
|
rb_const_set(StringScanner, rb_intern("Version"), tmp);
|
|
|
|
tmp = rb_str_new2("$Id$");
|
|
|
|
rb_obj_freeze(tmp);
|
|
|
|
rb_const_set(StringScanner, rb_intern("Id"), tmp);
|
2010-04-22 04:04:13 -04:00
|
|
|
|
* ext/curses/curses.c, ext/digest/digest.c, ext/dl/handle.c,
ext/dl/ptr.c, ext/dl/sym.c, ext/gdbm/gdbm.c, ext/iconv/iconv.c,
ext/stringio/stringio.c, ext/strscan/strscan.c,
ext/tcltklib/tcltklib.c, ext/win32ole/win32ole.c:
use rb_define_alloc_func().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3193 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-20 06:23:40 -05:00
|
|
|
rb_define_alloc_func(StringScanner, strscan_s_allocate);
|
2003-03-24 20:11:08 -05:00
|
|
|
rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
|
2004-03-05 06:20:12 -05:00
|
|
|
rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
|
2003-03-24 20:11:08 -05:00
|
|
|
rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "reset", strscan_reset, 0);
|
|
|
|
rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
|
2004-02-17 04:02:41 -05:00
|
|
|
rb_define_method(StringScanner, "clear", strscan_clear, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "string", strscan_get_string, 0);
|
|
|
|
rb_define_method(StringScanner, "string=", strscan_set_string, 1);
|
2003-12-16 10:18:11 -05:00
|
|
|
rb_define_method(StringScanner, "concat", strscan_concat, 1);
|
|
|
|
rb_define_method(StringScanner, "<<", strscan_concat, 1);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
|
|
|
|
rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
|
2012-11-27 19:17:33 -05:00
|
|
|
rb_define_method(StringScanner, "charpos", strscan_get_charpos, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
|
|
|
|
rb_define_method(StringScanner, "pointer=", strscan_set_pos, 1);
|
|
|
|
|
|
|
|
rb_define_method(StringScanner, "scan", strscan_scan, 1);
|
|
|
|
rb_define_method(StringScanner, "skip", strscan_skip, 1);
|
|
|
|
rb_define_method(StringScanner, "match?", strscan_match_p, 1);
|
|
|
|
rb_define_method(StringScanner, "check", strscan_check, 1);
|
|
|
|
rb_define_method(StringScanner, "scan_full", strscan_scan_full, 3);
|
|
|
|
|
|
|
|
rb_define_method(StringScanner, "scan_until", strscan_scan_until, 1);
|
|
|
|
rb_define_method(StringScanner, "skip_until", strscan_skip_until, 1);
|
|
|
|
rb_define_method(StringScanner, "exist?", strscan_exist_p, 1);
|
|
|
|
rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
|
|
|
|
rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
|
|
|
|
|
|
|
|
rb_define_method(StringScanner, "getch", strscan_getch, 0);
|
|
|
|
rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
|
2004-02-17 04:02:41 -05:00
|
|
|
rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "peek", strscan_peek, 1);
|
2004-02-17 04:02:41 -05:00
|
|
|
rb_define_method(StringScanner, "peep", strscan_peep, 1);
|
2002-03-22 01:38:27 -05:00
|
|
|
|
2002-03-28 03:53:24 -05:00
|
|
|
rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
|
|
|
|
|
2003-12-16 10:18:11 -05:00
|
|
|
rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
|
2005-09-24 08:20:14 -04:00
|
|
|
rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
|
2004-02-17 04:02:41 -05:00
|
|
|
rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
|
|
|
|
|
|
|
|
rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
|
|
|
|
rb_define_method(StringScanner, "matched", strscan_matched, 0);
|
|
|
|
rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
|
2002-03-28 03:53:24 -05:00
|
|
|
rb_define_method(StringScanner, "[]", strscan_aref, 1);
|
2002-03-22 01:38:27 -05:00
|
|
|
rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
|
|
|
|
rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
|
2017-11-29 02:57:48 -05:00
|
|
|
rb_define_method(StringScanner, "size", strscan_size, 0);
|
|
|
|
rb_define_method(StringScanner, "captures", strscan_captures, 0);
|
|
|
|
rb_define_method(StringScanner, "values_at", strscan_values_at, -1);
|
2002-03-28 03:53:24 -05:00
|
|
|
|
|
|
|
rb_define_method(StringScanner, "rest", strscan_rest, 0);
|
|
|
|
rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
|
2004-02-18 13:06:14 -05:00
|
|
|
rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
|
|
|
|
rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
|
2019-10-13 23:40:50 -04:00
|
|
|
|
|
|
|
rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0);
|
2002-03-22 01:38:27 -05:00
|
|
|
}
|