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,
PyObject
*
PyFloat_FromString
(
PyObject
*
v
,
char
**
pend
)
{
const
char
*
s
,
*
last
,
*
end
,
*
sp
;
const
char
*
s
,
*
last
,
*
end
;
double
x
;
char
buffer
[
256
];
/* for errors */
#ifdef Py_USING_UNICODE
...
...
@@ -212,81 +212,42 @@ PyFloat_FromString(PyObject *v, char **pend)
"float() argument must be a string or a number"
);
return
NULL
;
}
last
=
s
+
len
;
while
(
*
s
&&
isspace
(
Py_CHARMASK
(
*
s
)))
s
++
;
if
(
*
s
==
'\0'
)
{
PyErr_SetString
(
PyExc_ValueError
,
"empty string for float()"
);
return
NULL
;
}
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.
*/
/* We don't care about overflow or underflow. If the platform
* supports them, infinities and signed zeroes (on underflow) are
* fine. */
errno
=
0
;
PyFPE_START_PROTECT
(
"strtod"
,
return
NULL
)
x
=
PyOS_ascii_strtod
(
s
,
(
char
**
)
&
end
);
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
)
{
char
*
p
=
(
char
*
)
sp
;
int
sign
=
1
;
if
(
*
p
==
'-'
)
{
sign
=
-
1
;
p
++
;
}
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
;
if
(
errno
==
ENOMEM
)
PyErr_NoMemory
();
else
{
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
}
#endif
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
return
NULL
;
}
/* Since end != s, the platform made *some* kind of sense out
of the input. Trust it. */
while
(
*
end
&&
isspace
(
Py_CHARMASK
(
*
end
)))
end
++
;
if
(
*
end
!=
'\0'
)
{
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
return
NULL
;
}
else
if
(
end
!=
last
)
{
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for float()"
);
if
(
end
!=
last
)
{
if
(
*
end
==
'\0'
)
PyErr_SetString
(
PyExc_ValueError
,
"null byte in argument for float()"
);
else
{
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"invalid literal for float(): %.200s"
,
s
);
PyErr_SetString
(
PyExc_ValueError
,
buffer
);
}
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
);
}
...
...
Python/pystrtod.c
View file @
6d6b2202
...
...
@@ -71,6 +71,10 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
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,
then pass the remainder to the system strtod. This ensures that
the result of an underflow has the correct sign. (bug #1725) */
...
...
@@ -84,27 +88,53 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
if
(
*
p
==
'-'
)
{
negate
=
1
;
p
++
;
}
else
if
(
*
p
==
'+'
)
{
}
else
if
(
*
p
==
'+'
)
{
p
++
;
}
/* What's left should begin with a digit, a decimal point, or one of
the letters i, I, n, N. It should not begin with 0x or 0X */
if
((
!
ISDIGIT
(
*
p
)
&&
*
p
!=
'.'
&&
*
p
!=
'i'
&&
*
p
!=
'I'
&&
*
p
!=
'n'
&&
*
p
!=
'N'
)
||
(
*
p
==
'0'
&&
(
p
[
1
]
==
'x'
||
p
[
1
]
==
'X'
)))
{
if
(
endptr
)
*
endptr
=
(
char
*
)
nptr
;
errno
=
EINVAL
;
return
val
;
/* Parse infinities and nans */
if
(
*
p
==
'i'
||
*
p
==
'I'
)
{
if
(
PyOS_strnicmp
(
p
,
"inf"
,
3
)
==
0
)
{
val
=
Py_HUGE_VAL
;
if
(
PyOS_strnicmp
(
p
+
3
,
"inity"
,
5
)
==
0
)
fail_pos
=
(
char
*
)
p
+
8
;
else
fail_pos
=
(
char
*
)
p
+
3
;
goto
got_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
)
{
/* 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
))
p
++
;
...
...
@@ -112,6 +142,7 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
{
decimal_point_pos
=
p
++
;
/* locate end of number */
while
(
ISDIGIT
(
*
p
))
p
++
;
...
...
@@ -124,27 +155,16 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
end
=
p
;
}
else
if
(
strncmp
(
p
,
decimal_point
,
decimal_point_len
)
==
0
)
{
/* Python bug #1417699 */
if
(
endptr
)
*
endptr
=
(
char
*
)
nptr
;
errno
=
EINVAL
;
return
val
;
}
goto
invalid_string
;
/* For the other cases, we need not convert the decimal
point */
}
/* Set errno to zero, so that we can distinguish zero results
and underflows */
errno
=
0
;
if
(
decimal_point_pos
)
{
if
(
decimal_point_pos
)
{
char
*
copy
,
*
c
;
/* We need to convert the '.' to the locale specific decimal
point */
/* Create a copy of the input, with the '.' converted to the
locale-specific decimal point */
copy
=
(
char
*
)
PyMem_MALLOC
(
end
-
digits_pos
+
1
+
decimal_point_len
);
if
(
copy
==
NULL
)
{
...
...
@@ -185,8 +205,9 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
}
if
(
fail_pos
==
digits_pos
)
fail_pos
=
(
char
*
)
nptr
;
goto
invalid_string
;
got_val:
if
(
negate
&&
fail_pos
!=
nptr
)
val
=
-
val
;
...
...
@@ -194,6 +215,12 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
*
endptr
=
fail_pos
;
return
val
;
invalid_string:
if
(
endptr
)
*
endptr
=
(
char
*
)
nptr
;
errno
=
EINVAL
;
return
-
1
.
0
;
}
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