[前][次][番号順一覧][スレッド一覧]

ruby-changes:45915

From: nobu <ko1@a...>
Date: Thu, 16 Mar 2017 12:21:17 +0900 (JST)
Subject: [ruby-changes:45915] nobu:r57988 (trunk): bignum.c: rb_int_parse_cstr

nobu	2017-03-16 12:21:12 +0900 (Thu, 16 Mar 2017)

  New Revision: 57988

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57988

  Log:
    bignum.c: rb_int_parse_cstr
    
    * bignum.c (rb_int_parse_cstr): extend rb_cstr_parse_inum with
      flags.

  Modified files:
    trunk/bignum.c
    trunk/internal.h
Index: bignum.c
===================================================================
--- bignum.c	(revision 57987)
+++ bignum.c	(revision 57988)
@@ -4011,22 +4011,28 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L4011
  *       be NUL-terminated.
  * endp: if non-NULL, the address after parsed part is stored.  if
  *       NULL, Qnil is returned when +str+ is not valid as an Integer.
+ * ndigits: if non-NULL, the number of parsed digits is stored.
  * base: see +rb_cstr_to_inum+
+ * flags: bit-ORed flags of belows:
+ *       RB_INT_PARSE_SIGN: allow preceeding spaces and +/- sign
+ *       RB_INT_PARSE_UNDERSCORE: allow an underscore between digits
+ *       RB_INT_PARSE_PREFIX: allow preceeding prefix
  */
 
 VALUE
-rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
+rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
+		  int base, int flags)
 {
     const char *const s = str;
     char sign = 1;
     int c;
-    VALUE z;
+    VALUE z = Qnil;
 
     unsigned long val;
     int ov;
 
     const char *digits_start, *digits_end;
-    size_t num_digits;
+    size_t num_digits = 0;
     size_t num_bdigits;
     const ssize_t len0 = len;
     const int badcheck = !endp;
@@ -4044,9 +4050,10 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4050
     if (!str) {
       bad:
 	if (endp) *endp = (char *)str;
-	return Qnil;
+	if (ndigits) *ndigits = num_digits;
+	return z;
     }
-    if (len) {
+    if (len && (flags & RB_INT_PARSE_SIGN)) {
 	while (ISSPACE(*str)) ADV(1);
 
 	if (str[0] == '+') {
@@ -4088,7 +4095,7 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4095
 	    base = 10;
 	}
     }
-    else if (len == 1) {
+    else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
 	/* no prefix */
     }
     else if (base == 2) {
@@ -4115,15 +4122,19 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4122
         invalid_radix(base);
     }
     if (!len) goto bad;
+    num_digits = str - s;
     if (*str == '0' && len != 1) { /* squeeze preceding 0s */
 	int us = 0;
 	const char *end = len < 0 ? NULL : str + len;
-	while ((c = *++str) == '0' || c == '_') {
+	++num_digits;
+	while ((c = *++str) == '0' ||
+	       ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
 	    if (c == '_') {
 		if (++us >= 2)
 		    break;
 	    }
 	    else {
+		++num_digits;
 		us = 0;
 	    }
 	    if (str == end) break;
@@ -4135,14 +4146,18 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4146
     c = *str;
     c = conv_digit(c);
     if (c < 0 || c >= base) {
+	if (!badcheck && num_digits) z = INT2FIX(0);
 	goto bad;
     }
 
+    if (ndigits) *ndigits = num_digits;
     val = ruby_scan_digits(str, len, base, &num_digits, &ov);
     if (!ov) {
 	const char *end = &str[num_digits];
-	if (num_digits > 0 && *end == '_') goto bigparse;
+	if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
+	    goto bigparse;
 	if (endp) *endp = (char *)end;
+	if (ndigits) *ndigits += num_digits;
 	if (badcheck) {
 	    if (num_digits == 0) return Qnil; /* no number */
 	    while (len < 0 ? *end : end < str + len) {
@@ -4170,6 +4185,7 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4185
     if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
 	goto bad;
     if (endp) *endp = (char *)(str + len);
+    if (ndigits) *ndigits += num_digits;
     digits_end = digits_start + len;
 
     if (POW2_P(base)) {
@@ -4202,6 +4218,13 @@ rb_cstr_parse_inum(const char *str, ssiz https://github.com/ruby/ruby/blob/trunk/bignum.c#L4218
 }
 
 VALUE
+rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
+{
+    return rb_int_parse_cstr(str, len, endp, NULL, base,
+			     RB_INT_PARSE_DEFAULT);
+}
+
+VALUE
 rb_str_to_inum(VALUE str, int base, int badcheck)
 {
     VALUE ret;
Index: internal.h
===================================================================
--- internal.h	(revision 57987)
+++ internal.h	(revision 57988)
@@ -1746,6 +1746,14 @@ VALUE rb_big_divrem_gmp(VALUE x, VALUE y https://github.com/ruby/ruby/blob/trunk/internal.h#L1746
 VALUE rb_big2str_gmp(VALUE x, int base);
 VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
 #endif
+enum rb_int_parse_flags {
+    RB_INT_PARSE_SIGN       = 0x01,
+    RB_INT_PARSE_UNDERSCORE = 0x02,
+    RB_INT_PARSE_PREFIX     = 0x04,
+    RB_INT_PARSE_ALL        = 0x07,
+    RB_INT_PARSE_DEFAULT    = 0x07
+};
+VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
 
 /* error.c (export) */
 int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]