summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2018-04-30 10:46:01 -0600
committerKarl Williamson <khw@cpan.org>2018-06-25 07:33:26 -0600
commit6928bedc792ff80f0cb915460a7eacae25fa9bdd (patch)
treecb3daacc7529120825d1bbe72bd3a112cdf9f9f6 /numeric.c
parent808ea3ad2891b03a3f9c239b9b99d56b4765d765 (diff)
downloadperl-6928bedc792ff80f0cb915460a7eacae25fa9bdd.tar.gz
Create my_atof3()
This is like my_atof2(), but with an extra argument signifying the length of the input string to parse. If that length is 0, it uses strlen() to determine it. Then my_atof2() just calls my_atof3() with a zero final parameter. And this commit just uses the bulk of the current my_atof2() as the core of my_atof3(). Changes were needed however, because it relied on NUL-termination in a number of places. This allows one to convert a string that isn't necessarily NUL-terminated to an NV.
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/numeric.c b/numeric.c
index 8754a9f649..99531ef921 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1228,7 +1228,7 @@ Perl_my_atof(pTHX_ const char* s)
#ifdef USE_QUADMATH
- Perl_my_atof2(aTHX_ s, &x);
+ my_atof2(s, &x);
#elif ! defined(USE_LOCALE_NUMERIC)
@@ -1367,10 +1367,19 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
char*
Perl_my_atof2(pTHX_ const char* orig, NV* value)
{
+ PERL_ARGS_ASSERT_MY_ATOF2;
+ return my_atof3(orig, value, 0);
+}
+
+char*
+Perl_my_atof3(pTHX_ const char* orig, NV* value, STRLEN len)
+{
const char* s = orig;
NV result[3] = {0.0, 0.0, 0.0};
#if defined(USE_PERL_ATOF) || defined(USE_QUADMATH)
- const char* send = s + strlen(orig); /* one past the last */
+ const char* send = s + ((len != 0)
+ ? len
+ : strlen(orig)); /* one past the last */
bool negative = 0;
#endif
#if defined(USE_PERL_ATOF) && !defined(USE_QUADMATH)
@@ -1387,10 +1396,10 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
#endif
#if defined(USE_PERL_ATOF) || defined(USE_QUADMATH)
- PERL_ARGS_ASSERT_MY_ATOF2;
+ PERL_ARGS_ASSERT_MY_ATOF3;
/* leading whitespace */
- while (isSPACE(*s))
+ while (s < send && isSPACE(*s))
++s;
/* sign */
@@ -1408,6 +1417,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
char* endp;
if ((endp = S_my_atof_infnan(aTHX_ s, negative, send, value)))
return endp;
+ endp = send;
result[2] = strtoflt128(s, &endp);
if (s != endp) {
*value = negative ? -result[2] : result[2];
@@ -1457,7 +1467,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
/* we accumulate digits into an integer; when this becomes too
* large, we add the total to NV and start again */
- while (1) {
+ while (s < send) {
if (isDIGIT(*s)) {
seen_digit = 1;
old_digit = digit;
@@ -1485,7 +1495,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
exp_adjust[0]++;
}
/* skip remaining digits */
- while (isDIGIT(*s)) {
+ while (s < send && isDIGIT(*s)) {
++s;
if (! seen_dp) {
exp_adjust[0]++;
@@ -1509,7 +1519,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
else if (!seen_dp && GROK_NUMERIC_RADIX(&s, send)) {
seen_dp = 1;
if (sig_digits > MAX_SIG_DIGITS) {
- while (isDIGIT(*s)) {
+ while (s < send && isDIGIT(*s)) {
++s;
}
break;
@@ -1525,7 +1535,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
result[1] = S_mulexp10(result[1], exp_acc[1]) + (NV)accumulator[1];
}
- if (seen_digit && (isALPHA_FOLD_EQ(*s, 'e'))) {
+ if (s < send && seen_digit && (isALPHA_FOLD_EQ(*s, 'e'))) {
bool expnegative = 0;
++s;
@@ -1536,14 +1546,12 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
case '+':
++s;
}
- while (isDIGIT(*s))
+ while (s < send && isDIGIT(*s))
exponent = exponent * 10 + (*s++ - '0');
if (expnegative)
exponent = -exponent;
}
-
-
/* now apply the exponent */
if (seen_dp) {