Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
6d6b2202
Commit
6d6b2202
authored
Apr 26, 2009
by
Mark Dickinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backport r71967 changes from py3k to trunk.
(Internal plumbing changes for float parsing.)
parent
944c6aed
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
90 deletions
+78
-90
Objects/floatobject.c
Objects/floatobject.c
+21
-60
Python/pystrtod.c
Python/pystrtod.c
+57
-30
No files found.
Objects/floatobject.c
View file @
6d6b2202
...
@@ -177,7 +177,7 @@ still supported but now *officially* useless: if pend is not NULL,
...
@@ -177,7 +177,7 @@ still supported but now *officially* useless: if pend is not NULL,
PyObject
*
PyObject
*
PyFloat_FromString
(
PyObject
*
v
,
char
**
pend
)
PyFloat_FromString
(
PyObject
*
v
,
char
**
pend
)
{
{
const
char
*
s
,
*
last
,
*
end
,
*
sp
;
const
char
*
s
,
*
last
,
*
end
;
double
x
;
double
x
;
char
buffer
[
256
];
/* for errors */
char
buffer
[
256
];
/* for errors */
#ifdef Py_USING_UNICODE
#ifdef Py_USING_UNICODE
...
@@ -212,81 +212,42 @@ PyFloat_FromString(PyObject *v, char **pend)
...
@@ -212,81 +212,42 @@ PyFloat_FromString(PyObject *v, char **pend)
"float() argument must be a string or a number"
);
"float() argument must be a string or a number"
);
return
NULL
;
return
NULL
;
}
}
last
=
s
+
len
;
last
=
s
+
len
;
while
(
*
s
&&
isspace
(
Py_CHARMASK
(
*
s
)))
while
(
*
s
&&
isspace
(
Py_CHARMASK
(
*
s
)))
s
++
;
s
++
;
if
(
*
s
==
'\0'
)
{
/* We don't care about overflow or underflow. If the platform
PyErr_SetString
(
PyExc_ValueError
,
"empty string for float()"
);
* supports them, infinities and signed zeroes (on underflow) are
return
NULL
;
* fine. */
}
errno
=
0
;
sp
=
s
;
/* We don't care about overflow or underflow. If the platform supports
* them, infinities and signed zeroes (on underflow) are fine.
* However, strtod can return 0 for denormalized numbers, where atof
* does not. So (alas!) we special-case a zero result. Note that
* whether strtod sets errno on underflow is not defined, so we can't
* key off errno.
*/
PyFPE_START_PROTECT
(
"strtod"
,
return
NULL
)
PyFPE_START_PROTECT
(
"strtod"
,
return
NULL
)
x
=
PyOS_ascii_strtod
(
s
,
(
char
**
)
&
end
);
x
=
PyOS_ascii_strtod
(
s
,
(
char
**
)
&
end
);
PyFPE_END_PROTECT
(
x
)
PyFPE_END_PROTECT
(
x
)
errno
=
0
;
/* Believe it or not, Solaris 2.6 can move end *beyond* the null
byte at the end of the string, when the input is inf(inity). */
if
(
end
>
last
)
end
=
last
;
/* Check for inf and nan. This is done late because it rarely happens. */
if
(
end
==
s
)
{
if
(
end
==
s
)
{
char
*
p
=
(
char
*
)
sp
;
if
(
errno
==
ENOMEM
)
int
sign
=
1
;
PyErr_NoMemory
();
else
{
if
(
*
p
==
'-'
)
{
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
sign
=
-
1
;
"invalid literal for float(): %.200s"
,
s
);
p
++
;
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
}
if
(
*
p
==
'+'
)
{
p
++
;
}
if
(
PyOS_strnicmp
(
p
,
"inf"
,
4
)
==
0
)
{
Py_RETURN_INF
(
sign
);
}
if
(
PyOS_strnicmp
(
p
,
"infinity"
,
9
)
==
0
)
{
Py_RETURN_INF
(
sign
);
}
#ifdef Py_NAN
if
(
PyOS_strnicmp
(
p
,
"nan"
,
4
)
==
0
)
{
Py_RETURN_NAN
;
}
}
#endif
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
return
NULL
;
return
NULL
;
}
}
/* Since end != s, the platform made *some* kind of sense out
/* Since end != s, the platform made *some* kind of sense out
of the input. Trust it. */
of the input. Trust it. */
while
(
*
end
&&
isspace
(
Py_CHARMASK
(
*
end
)))
while
(
*
end
&&
isspace
(
Py_CHARMASK
(
*
end
)))
end
++
;
end
++
;
if
(
*
end
!=
'\0'
)
{
if
(
end
!=
last
)
{
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
if
(
*
end
==
'\0'
)
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
"null byte in argument for float()"
);
return
NULL
;
else
{
}
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
else
if
(
end
!=
last
)
{
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
"null byte in argument for float()"
);
}
return
NULL
;
return
NULL
;
}
}
if
(
x
==
0
.
0
)
{
/* See above -- may have been strtod being anal
about denorms. */
PyFPE_START_PROTECT
(
"atof"
,
return
NULL
)
x
=
PyOS_ascii_atof
(
s
);
PyFPE_END_PROTECT
(
x
)
errno
=
0
;
/* whether atof ever set errno is undefined */
}
return
PyFloat_FromDouble
(
x
);
return
PyFloat_FromDouble
(
x
);
}
}
...
...
Python/pystrtod.c
View file @
6d6b2202
...
@@ -71,6 +71,10 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -71,6 +71,10 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
decimal_point_pos
=
NULL
;
decimal_point_pos
=
NULL
;
/* Set errno to zero, so that we can distinguish zero results
and underflows */
errno
=
0
;
/* We process any leading whitespace and the optional sign manually,
/* We process any leading whitespace and the optional sign manually,
then pass the remainder to the system strtod. This ensures that
then pass the remainder to the system strtod. This ensures that
the result of an underflow has the correct sign. (bug #1725) */
the result of an underflow has the correct sign. (bug #1725) */
...
@@ -84,27 +88,53 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -84,27 +88,53 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
if
(
*
p
==
'-'
)
{
if
(
*
p
==
'-'
)
{
negate
=
1
;
negate
=
1
;
p
++
;
p
++
;
}
else
if
(
*
p
==
'+'
)
{
}
else
if
(
*
p
==
'+'
)
{
p
++
;
p
++
;
}
}
/* What's left should begin with a digit, a decimal point, or one of
/* Parse infinities and nans */
the letters i, I, n, N. It should not begin with 0x or 0X */
if
(
*
p
==
'i'
||
*
p
==
'I'
)
{
if
((
!
ISDIGIT
(
*
p
)
&&
if
(
PyOS_strnicmp
(
p
,
"inf"
,
3
)
==
0
)
{
*
p
!=
'.'
&&
*
p
!=
'i'
&&
*
p
!=
'I'
&&
*
p
!=
'n'
&&
*
p
!=
'N'
)
val
=
Py_HUGE_VAL
;
||
if
(
PyOS_strnicmp
(
p
+
3
,
"inity"
,
5
)
==
0
)
(
*
p
==
'0'
&&
(
p
[
1
]
==
'x'
||
p
[
1
]
==
'X'
)))
fail_pos
=
(
char
*
)
p
+
8
;
{
else
if
(
endptr
)
fail_pos
=
(
char
*
)
p
+
3
;
*
endptr
=
(
char
*
)
nptr
;
goto
got_val
;
errno
=
EINVAL
;
}
return
val
;
else
goto
invalid_string
;
}
}
digits_pos
=
p
;
#ifdef Py_NAN
if
(
*
p
==
'n'
||
*
p
==
'N'
)
{
if
(
PyOS_strnicmp
(
p
,
"nan"
,
3
)
==
0
)
{
val
=
Py_NAN
;
fail_pos
=
(
char
*
)
p
+
3
;
goto
got_val
;
}
else
goto
invalid_string
;
}
#endif
/* Some platform strtods accept hex floats; Python shouldn't (at the
moment), so we check explicitly for strings starting with '0x'. */
if
(
*
p
==
'0'
&&
(
*
(
p
+
1
)
==
'x'
||
*
(
p
+
1
)
==
'X'
))
goto
invalid_string
;
/* Check that what's left begins with a digit or decimal point */
if
(
!
ISDIGIT
(
*
p
)
&&
*
p
!=
'.'
)
goto
invalid_string
;
if
(
decimal_point
[
0
]
!=
'.'
||
digits_pos
=
p
;
if
(
decimal_point
[
0
]
!=
'.'
||
decimal_point
[
1
]
!=
0
)
decimal_point
[
1
]
!=
0
)
{
{
/* Look for a '.' in the input; if present, it'll need to be
swapped for the current locale's decimal point before we
call strtod. On the other hand, if we find the current
locale's decimal point then the input is invalid. */
while
(
ISDIGIT
(
*
p
))
while
(
ISDIGIT
(
*
p
))
p
++
;
p
++
;
...
@@ -112,6 +142,7 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -112,6 +142,7 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
{
{
decimal_point_pos
=
p
++
;
decimal_point_pos
=
p
++
;
/* locate end of number */
while
(
ISDIGIT
(
*
p
))
while
(
ISDIGIT
(
*
p
))
p
++
;
p
++
;
...
@@ -124,27 +155,16 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -124,27 +155,16 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
end
=
p
;
end
=
p
;
}
}
else
if
(
strncmp
(
p
,
decimal_point
,
decimal_point_len
)
==
0
)
else
if
(
strncmp
(
p
,
decimal_point
,
decimal_point_len
)
==
0
)
{
/* Python bug #1417699 */
/* Python bug #1417699 */
if
(
endptr
)
goto
invalid_string
;
*
endptr
=
(
char
*
)
nptr
;
errno
=
EINVAL
;
return
val
;
}
/* For the other cases, we need not convert the decimal
/* For the other cases, we need not convert the decimal
point */
point */
}
}
/* Set errno to zero, so that we can distinguish zero results
if
(
decimal_point_pos
)
{
and underflows */
errno
=
0
;
if
(
decimal_point_pos
)
{
char
*
copy
,
*
c
;
char
*
copy
,
*
c
;
/* Create a copy of the input, with the '.' converted to the
/* We need to convert the '.' to the locale specific decimal
locale-specific decimal point */
point */
copy
=
(
char
*
)
PyMem_MALLOC
(
end
-
digits_pos
+
copy
=
(
char
*
)
PyMem_MALLOC
(
end
-
digits_pos
+
1
+
decimal_point_len
);
1
+
decimal_point_len
);
if
(
copy
==
NULL
)
{
if
(
copy
==
NULL
)
{
...
@@ -185,8 +205,9 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -185,8 +205,9 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
}
}
if
(
fail_pos
==
digits_pos
)
if
(
fail_pos
==
digits_pos
)
fail_pos
=
(
char
*
)
nptr
;
goto
invalid_string
;
got_val:
if
(
negate
&&
fail_pos
!=
nptr
)
if
(
negate
&&
fail_pos
!=
nptr
)
val
=
-
val
;
val
=
-
val
;
...
@@ -194,6 +215,12 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
...
@@ -194,6 +215,12 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
*
endptr
=
fail_pos
;
*
endptr
=
fail_pos
;
return
val
;
return
val
;
invalid_string:
if
(
endptr
)
*
endptr
=
(
char
*
)
nptr
;
errno
=
EINVAL
;
return
-
1
.
0
;
}
}
double
double
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment