bignum.c: rb_int_parse_cstr
* bignum.c (rb_int_parse_cstr): extend rb_cstr_parse_inum with flags. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57988 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a441e89c78
commit
92e2a7048e
39
bignum.c
39
bignum.c
@ -4011,22 +4011,28 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
|
|||||||
* be NUL-terminated.
|
* be NUL-terminated.
|
||||||
* endp: if non-NULL, the address after parsed part is stored. if
|
* endp: if non-NULL, the address after parsed part is stored. if
|
||||||
* NULL, Qnil is returned when +str+ is not valid as an Integer.
|
* 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+
|
* 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
|
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;
|
const char *const s = str;
|
||||||
char sign = 1;
|
char sign = 1;
|
||||||
int c;
|
int c;
|
||||||
VALUE z;
|
VALUE z = Qnil;
|
||||||
|
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int ov;
|
int ov;
|
||||||
|
|
||||||
const char *digits_start, *digits_end;
|
const char *digits_start, *digits_end;
|
||||||
size_t num_digits;
|
size_t num_digits = 0;
|
||||||
size_t num_bdigits;
|
size_t num_bdigits;
|
||||||
const ssize_t len0 = len;
|
const ssize_t len0 = len;
|
||||||
const int badcheck = !endp;
|
const int badcheck = !endp;
|
||||||
@ -4044,9 +4050,10 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
if (!str) {
|
if (!str) {
|
||||||
bad:
|
bad:
|
||||||
if (endp) *endp = (char *)str;
|
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);
|
while (ISSPACE(*str)) ADV(1);
|
||||||
|
|
||||||
if (str[0] == '+') {
|
if (str[0] == '+') {
|
||||||
@ -4088,7 +4095,7 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
base = 10;
|
base = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (len == 1) {
|
else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
|
||||||
/* no prefix */
|
/* no prefix */
|
||||||
}
|
}
|
||||||
else if (base == 2) {
|
else if (base == 2) {
|
||||||
@ -4115,15 +4122,19 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
invalid_radix(base);
|
invalid_radix(base);
|
||||||
}
|
}
|
||||||
if (!len) goto bad;
|
if (!len) goto bad;
|
||||||
|
num_digits = str - s;
|
||||||
if (*str == '0' && len != 1) { /* squeeze preceding 0s */
|
if (*str == '0' && len != 1) { /* squeeze preceding 0s */
|
||||||
int us = 0;
|
int us = 0;
|
||||||
const char *end = len < 0 ? NULL : str + len;
|
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 (c == '_') {
|
||||||
if (++us >= 2)
|
if (++us >= 2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
++num_digits;
|
||||||
us = 0;
|
us = 0;
|
||||||
}
|
}
|
||||||
if (str == end) break;
|
if (str == end) break;
|
||||||
@ -4135,14 +4146,18 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
c = *str;
|
c = *str;
|
||||||
c = conv_digit(c);
|
c = conv_digit(c);
|
||||||
if (c < 0 || c >= base) {
|
if (c < 0 || c >= base) {
|
||||||
|
if (!badcheck && num_digits) z = INT2FIX(0);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ndigits) *ndigits = num_digits;
|
||||||
val = ruby_scan_digits(str, len, base, &num_digits, &ov);
|
val = ruby_scan_digits(str, len, base, &num_digits, &ov);
|
||||||
if (!ov) {
|
if (!ov) {
|
||||||
const char *end = &str[num_digits];
|
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 (endp) *endp = (char *)end;
|
||||||
|
if (ndigits) *ndigits += num_digits;
|
||||||
if (badcheck) {
|
if (badcheck) {
|
||||||
if (num_digits == 0) return Qnil; /* no number */
|
if (num_digits == 0) return Qnil; /* no number */
|
||||||
while (len < 0 ? *end : end < str + len) {
|
while (len < 0 ? *end : end < str + len) {
|
||||||
@ -4170,6 +4185,7 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
|
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (endp) *endp = (char *)(str + len);
|
if (endp) *endp = (char *)(str + len);
|
||||||
|
if (ndigits) *ndigits += num_digits;
|
||||||
digits_end = digits_start + len;
|
digits_end = digits_start + len;
|
||||||
|
|
||||||
if (POW2_P(base)) {
|
if (POW2_P(base)) {
|
||||||
@ -4201,6 +4217,13 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
|
|||||||
return bignorm(z);
|
return bignorm(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
VALUE
|
||||||
rb_str_to_inum(VALUE str, int base, int badcheck)
|
rb_str_to_inum(VALUE str, int base, int badcheck)
|
||||||
{
|
{
|
||||||
|
@ -1746,6 +1746,14 @@ VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
|
|||||||
VALUE rb_big2str_gmp(VALUE x, int base);
|
VALUE rb_big2str_gmp(VALUE x, int base);
|
||||||
VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
|
VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
|
||||||
#endif
|
#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) */
|
/* error.c (export) */
|
||||||
int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
|
int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user