Skip to content

Commit 6928bed

Browse files
committed
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.
1 parent 808ea3a commit 6928bed

File tree

6 files changed

+28
-15
lines changed

6 files changed

+28
-15
lines changed

embed.fnc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2909,7 +2909,8 @@ Apd |char* |sv_pvn_force_flags|NN SV *const sv|NULLOK STRLEN *const lp|const I32
29092909
Apmb |void |sv_copypv |NN SV *const dsv|NN SV *const ssv
29102910
Apmd |void |sv_copypv_nomg |NN SV *const dsv|NN SV *const ssv
29112911
Apd |void |sv_copypv_flags |NN SV *const dsv|NN SV *const ssv|const I32 flags
2912-
Ap |char* |my_atof2 |NN const char *orig|NN NV* value
2912+
Apo |char* |my_atof2 |NN const char *orig|NN NV* value
2913+
Ap |char* |my_atof3 |NN const char *orig|NN NV* value|const STRLEN len
29132914
Apn |int |my_socketpair |int family|int type|int protocol|int fd[2]
29142915
Apn |int |my_dirfd |NULLOK DIR* dir
29152916
#ifdef PERL_ANY_COW

embed.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@
476476
#define mro_get_linear_isa(a) Perl_mro_get_linear_isa(aTHX_ a)
477477
#define mro_method_changed_in(a) Perl_mro_method_changed_in(aTHX_ a)
478478
#define my_atof(a) Perl_my_atof(aTHX_ a)
479-
#define my_atof2(a,b) Perl_my_atof2(aTHX_ a,b)
479+
#define my_atof3(a,b,c) Perl_my_atof3(aTHX_ a,b,c)
480480
#define my_dirfd Perl_my_dirfd
481481
#define my_exit(a) Perl_my_exit(aTHX_ a)
482482
#define my_failure_exit() Perl_my_failure_exit(aTHX)

numeric.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ Perl_my_atof(pTHX_ const char* s)
12281228

12291229
#ifdef USE_QUADMATH
12301230

1231-
Perl_my_atof2(aTHX_ s, &x);
1231+
my_atof2(s, &x);
12321232

12331233
#elif ! defined(USE_LOCALE_NUMERIC)
12341234

@@ -1366,11 +1366,20 @@ S_my_atof_infnan(pTHX_ const char* s, bool negative, const char* send, NV* value
13661366

13671367
char*
13681368
Perl_my_atof2(pTHX_ const char* orig, NV* value)
1369+
{
1370+
PERL_ARGS_ASSERT_MY_ATOF2;
1371+
return my_atof3(orig, value, 0);
1372+
}
1373+
1374+
char*
1375+
Perl_my_atof3(pTHX_ const char* orig, NV* value, STRLEN len)
13691376
{
13701377
const char* s = orig;
13711378
NV result[3] = {0.0, 0.0, 0.0};
13721379
#if defined(USE_PERL_ATOF) || defined(USE_QUADMATH)
1373-
const char* send = s + strlen(orig); /* one past the last */
1380+
const char* send = s + ((len != 0)
1381+
? len
1382+
: strlen(orig)); /* one past the last */
13741383
bool negative = 0;
13751384
#endif
13761385
#if defined(USE_PERL_ATOF) && !defined(USE_QUADMATH)
@@ -1387,10 +1396,10 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
13871396
#endif
13881397

13891398
#if defined(USE_PERL_ATOF) || defined(USE_QUADMATH)
1390-
PERL_ARGS_ASSERT_MY_ATOF2;
1399+
PERL_ARGS_ASSERT_MY_ATOF3;
13911400

13921401
/* leading whitespace */
1393-
while (isSPACE(*s))
1402+
while (s < send && isSPACE(*s))
13941403
++s;
13951404

13961405
/* sign */
@@ -1408,6 +1417,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
14081417
char* endp;
14091418
if ((endp = S_my_atof_infnan(aTHX_ s, negative, send, value)))
14101419
return endp;
1420+
endp = send;
14111421
result[2] = strtoflt128(s, &endp);
14121422
if (s != endp) {
14131423
*value = negative ? -result[2] : result[2];
@@ -1457,7 +1467,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
14571467
/* we accumulate digits into an integer; when this becomes too
14581468
* large, we add the total to NV and start again */
14591469

1460-
while (1) {
1470+
while (s < send) {
14611471
if (isDIGIT(*s)) {
14621472
seen_digit = 1;
14631473
old_digit = digit;
@@ -1485,7 +1495,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
14851495
exp_adjust[0]++;
14861496
}
14871497
/* skip remaining digits */
1488-
while (isDIGIT(*s)) {
1498+
while (s < send && isDIGIT(*s)) {
14891499
++s;
14901500
if (! seen_dp) {
14911501
exp_adjust[0]++;
@@ -1509,7 +1519,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
15091519
else if (!seen_dp && GROK_NUMERIC_RADIX(&s, send)) {
15101520
seen_dp = 1;
15111521
if (sig_digits > MAX_SIG_DIGITS) {
1512-
while (isDIGIT(*s)) {
1522+
while (s < send && isDIGIT(*s)) {
15131523
++s;
15141524
}
15151525
break;
@@ -1525,7 +1535,7 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
15251535
result[1] = S_mulexp10(result[1], exp_acc[1]) + (NV)accumulator[1];
15261536
}
15271537

1528-
if (seen_digit && (isALPHA_FOLD_EQ(*s, 'e'))) {
1538+
if (s < send && seen_digit && (isALPHA_FOLD_EQ(*s, 'e'))) {
15291539
bool expnegative = 0;
15301540

15311541
++s;
@@ -1536,14 +1546,12 @@ Perl_my_atof2(pTHX_ const char* orig, NV* value)
15361546
case '+':
15371547
++s;
15381548
}
1539-
while (isDIGIT(*s))
1549+
while (s < send && isDIGIT(*s))
15401550
exponent = exponent * 10 + (*s++ - '0');
15411551
if (expnegative)
15421552
exponent = -exponent;
15431553
}
15441554

1545-
1546-
15471555
/* now apply the exponent */
15481556

15491557
if (seen_dp) {

perl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2328,11 +2328,12 @@ int isnan(double d);
23282328

23292329
#ifdef USE_PERL_ATOF
23302330
# define Perl_atof(s) Perl_my_atof(s)
2331-
# define Perl_atof2(s, n) Perl_my_atof2(aTHX_ (s), &(n))
2331+
# define Perl_atof2(s, n) Perl_my_atof3(aTHX_ (s), &(n), 0)
23322332
#else
23332333
# define Perl_atof(s) (NV)atof(s)
23342334
# define Perl_atof2(s, n) ((n) = atof(s))
23352335
#endif
2336+
#define my_atof2(a,b) my_atof3(a,b,0)
23362337

23372338
/*
23382339
* CHAR_MIN and CHAR_MAX are not included here, as the (char) type may be

pod/perlclib.pod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ C<toUPPER_uni>, as described in L<perlapi/Character case changing>.)
205205
atof(s) Atof(s)
206206
atoi(s) grok_atoUV(s, &uv, &e)
207207
atol(s) grok_atoUV(s, &uv, &e)
208-
strtod(s, &p) Nothing. Just don't use it.
208+
strtod(s, &p) my_atof3(s, &nv, &p) is the closest we have
209209
strtol(s, &p, n) grok_atoUV(s, &uv, &e)
210210
strtoul(s, &p, n) grok_atoUV(s, &uv, &e)
211211

proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,9 @@ PERL_CALLCONV NV Perl_my_atof(pTHX_ const char *s);
22202220
PERL_CALLCONV char* Perl_my_atof2(pTHX_ const char *orig, NV* value);
22212221
#define PERL_ARGS_ASSERT_MY_ATOF2 \
22222222
assert(orig); assert(value)
2223+
PERL_CALLCONV char* Perl_my_atof3(pTHX_ const char *orig, NV* value, const STRLEN len);
2224+
#define PERL_ARGS_ASSERT_MY_ATOF3 \
2225+
assert(orig); assert(value)
22232226
PERL_CALLCONV OP * Perl_my_attrs(pTHX_ OP *o, OP *attrs);
22242227
#define PERL_ARGS_ASSERT_MY_ATTRS \
22252228
assert(o)

0 commit comments

Comments
 (0)