* 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:
nobu 2017-03-16 03:21:12 +00:00
Родитель a441e89c78
Коммит 92e2a7048e
2 изменённых файлов: 39 добавлений и 8 удалений

Просмотреть файл

@ -4011,22 +4011,28 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
* 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, ssize_t len, char **endp, int base)
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, ssize_t len, char **endp, int base)
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, ssize_t len, char **endp, int base)
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, ssize_t len, char **endp, int base)
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, ssize_t len, char **endp, int base)
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)) {
@ -4201,6 +4217,13 @@ rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
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
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_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);