Christian Heimes added the comment:
Update:
I've added a platform independent implementation of stricmp and strnicmp
(case insensitive compare). It could be useful for other parts of the
code as well.
Added file: http://bugs.python.org/file8962/trunk_float_inf_nan2.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1635>
__________________________________
Index: Python/pystrcmp.c
===================================================================
--- Python/pystrcmp.c (Revision 0)
+++ Python/pystrcmp.c (Revision 0)
@@ -0,0 +1,26 @@
+/* Cross platform case insenstive string compare functions
+ */
+
+#include "Python.h"
+
+int
+PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size)
+{
+ if (size == 0)
+ return 0;
+ while ((--size > 0) && (tolower(*s1) == tolower(*s2))) {
+ if (!*s1++ || !*s2++)
+ break;
+ }
+ return tolower(*s1) - tolower(*s2);
+}
+
+int
+PyOS_mystricmp(const char *s1, const char *s2)
+{
+ while (*s1 && (tolower(*s1++) == tolower(*s2++))) {
+ ;
+ }
+ return (tolower(*s1) - tolower(*s2));
+}
+
Eigenschaftsänderungen: Python/pystrcmp.c
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Index: PCbuild/pythoncore.vcproj
===================================================================
--- PCbuild/pythoncore.vcproj (Revision 59511)
+++ PCbuild/pythoncore.vcproj (Arbeitskopie)
@@ -701,6 +701,10 @@
RelativePath="..\Python\pystate.c">
</File>
<File
+ RelativePath="..\Python\pystrcmp.c"
+ >
+ </File>
+ <File
RelativePath="..\Python\pystrtod.c">
</File>
<File
Index: Include/pyport.h
===================================================================
--- Include/pyport.h (Revision 59511)
+++ Include/pyport.h (Arbeitskopie)
@@ -393,6 +393,15 @@
#define Py_HUGE_VAL HUGE_VAL
#endif
+/* Py_NAN
+ * Some value that evaluates to a NaN. On IEEE 754 platforms INF*0 or
+ * INF/INF works. Define Py_NO_NAN in pyconfig.h if your platform
+ * doesn't support NaNs.
+ */
+#if !defined(Py_NAN) && !defined(Py_NO_NAN)
+#define Py_NAN Py_HUGE_VAL * 0
+#endif
+
/* Py_OVERFLOWED(X)
* Return 1 iff a libm function overflowed. Set errno to 0 before calling
* a libm function, and invoke this macro after, passing the function
Index: Include/pystrcmp.h
===================================================================
--- Include/pystrcmp.h (Revision 0)
+++ Include/pystrcmp.h (Revision 0)
@@ -0,0 +1,23 @@
+#ifndef Py_STRCMP_H
+#define Py_STRCMP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(int) PyOS_mystrnicmp(const char *, const char *, Py_ssize_t);
+PyAPI_FUNC(int) PyOS_mystricmp(const char *, const char *);
+
+#ifdef MS_WINDOWS
+#define PyOS_strnicmp strnicmp
+#define PyOS_stricmp stricmp
+#else
+#define PyOS_strnicmp PyOS_mystrnicmp
+#define PyOS_stricmp PyOS_mystricmp
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !Py_STRCMP_H */
Eigenschaftsänderungen: Include/pystrcmp.h
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Index: Include/Python.h
===================================================================
--- Include/Python.h (Revision 59511)
+++ Include/Python.h (Arbeitskopie)
@@ -129,6 +129,7 @@
#include "eval.h"
#include "pystrtod.h"
+#include "pystrcmp.h"
/* _Py_Mangle is defined in compile.c */
PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
Index: Objects/floatobject.c
===================================================================
--- Objects/floatobject.c (Revision 59511)
+++ Objects/floatobject.c (Arbeitskopie)
@@ -128,7 +128,7 @@
PyObject *
PyFloat_FromString(PyObject *v, char **pend)
{
- const char *s, *last, *end;
+ const char *s, *last, *end, *sp;
double x;
char buffer[256]; /* for errors */
#ifdef Py_USING_UNICODE
@@ -171,6 +171,7 @@
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
@@ -186,7 +187,26 @@
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 = sp;
+ int sign = 1;
+
+ if (*p == '-') {
+ sign = -1;
+ p++;
+ }
+ if (*p == '+') {
+ p++;
+ }
+ if (PyOS_strnicmp(p, "inf", 4) == 0) {
+ return PyFloat_FromDouble(sign * HUGE_VAL);
+ }
+#ifdef Py_NAN
+ if(PyOS_strnicmp(p, "nan", 4) == 0) {
+ return PyFloat_FromDouble(Py_NAN);
+ }
+#endif
PyOS_snprintf(buffer, sizeof(buffer),
"invalid literal for float(): %.200s", s);
PyErr_SetString(PyExc_ValueError, buffer);
@@ -271,6 +291,8 @@
{
register char *cp;
char format[32];
+ int i;
+
/* Subroutine for float_repr and float_print.
We want float numbers to be recognizable as such,
i.e., they should contain a decimal point or an exponent.
@@ -293,7 +315,39 @@
*cp++ = '.';
*cp++ = '0';
*cp++ = '\0';
+ return;
}
+ /* checking the next three items should be more than enough to
+ * detect inf or nan, even on Windows. We check for inf or nan
+ * at last because they are rare cases.
+ */
+ for (i=0; *cp != '\0' && i<3; cp++, i++) {
+ if (isdigit(Py_CHARMASK(*cp)) || *cp == '.')
+ continue;
+ /* found something that is neither a digit nor point
+ * it might be a NaN or INF
+ */
+#ifdef Py_NAN
+ if (Py_IS_NAN(v->ob_fval)) {
+ cp = buf;
+ *cp++ = 'n';
+ *cp++ = 'a';
+ *cp++ = 'n';
+ *cp++ = '\0';
+ }
+#endif
+ if (Py_IS_INFINITY(v->ob_fval)) {
+ cp = buf;
+ if (*cp == '-')
+ cp++;
+ *cp++ = 'i';
+ *cp++ = 'n';
+ *cp++ = 'f';
+ *cp++ = '\0';
+ }
+ break;
+ }
+
}
/* XXX PyFloat_AsStringEx should not be a public API function (for one
Index: Lib/test/test_float.py
===================================================================
--- Lib/test/test_float.py (Revision 59511)
+++ Lib/test/test_float.py (Arbeitskopie)
@@ -3,6 +3,12 @@
import os
from test import test_support
+def isinf(x):
+ return x * 0.5 == x
+
+def isnan(x):
+ return x != x
+
class FormatFunctionsTestCase(unittest.TestCase):
def setUp(self):
@@ -128,13 +134,78 @@
self.assertEqual(v, eval(repr(v)))
floats_file.close()
+# Beginning with Python 2.6 float has cross platform compatible
+# ways to create and representate inf and nan
+class InfNanTest(unittest.TestCase):
+ def test_inf_from_str(self):
+ self.assert_(isinf(float("inf")))
+ self.assert_(isinf(float("+inf")))
+ self.assert_(isinf(float("-inf")))
+ self.assertEqual(repr(float("inf")), "inf")
+ self.assertEqual(repr(float("+inf")), "inf")
+ self.assertEqual(repr(float("-inf")), "-inf")
+
+ self.assertEqual(repr(float("INF")), "inf")
+ self.assertEqual(repr(float("+Inf")), "inf")
+ self.assertEqual(repr(float("-iNF")), "-inf")
+
+ self.assertEqual(str(float("inf")), "inf")
+ self.assertEqual(str(float("+inf")), "inf")
+ self.assertEqual(str(float("-inf")), "-inf")
+
+ self.assertRaises(ValueError, float, "info")
+ self.assertRaises(ValueError, float, "+info")
+ self.assertRaises(ValueError, float, "-info")
+ self.assertRaises(ValueError, float, "in")
+ self.assertRaises(ValueError, float, "+in")
+ self.assertRaises(ValueError, float, "-in")
+
+ def test_inf_as_str(self):
+ self.assertEqual(repr(1e300 * 1e300), "inf")
+ self.assertEqual(repr(-1e300 * 1e300), "-inf")
+
+ self.assertEqual(str(1e300 * 1e300), "inf")
+ self.assertEqual(str(-1e300 * 1e300), "-inf")
+
+ def test_nan_from_str(self):
+ self.assert_(isnan(float("nan")))
+ self.assert_(isnan(float("+nan")))
+ self.assert_(isnan(float("-nan")))
+
+ self.assertEqual(repr(float("nan")), "nan")
+ self.assertEqual(repr(float("+nan")), "nan")
+ self.assertEqual(repr(float("-nan")), "nan")
+
+ self.assertEqual(repr(float("NAN")), "nan")
+ self.assertEqual(repr(float("+NAn")), "nan")
+ self.assertEqual(repr(float("-NaN")), "nan")
+
+ self.assertEqual(str(float("nan")), "nan")
+ self.assertEqual(str(float("+nan")), "nan")
+ self.assertEqual(str(float("-nan")), "nan")
+
+ self.assertRaises(ValueError, float, "nana")
+ self.assertRaises(ValueError, float, "+nana")
+ self.assertRaises(ValueError, float, "-nana")
+ self.assertRaises(ValueError, float, "na")
+ self.assertRaises(ValueError, float, "+na")
+ self.assertRaises(ValueError, float, "-na")
+
+ def test_nan_as_str(self):
+ self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
+ self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
+
+ self.assertEqual(str(1e300 * 1e300 * 0), "nan")
+ self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
+
def test_main():
test_support.run_unittest(
FormatFunctionsTestCase,
UnknownFormatTestCase,
IEEEFormatTestCase,
- #ReprTestCase
+ ReprTestCase,
+ InfNanTest,
)
if __name__ == '__main__':
Index: Makefile.pre.in
===================================================================
--- Makefile.pre.in (Revision 59511)
+++ Makefile.pre.in (Arbeitskopie)
@@ -275,6 +275,7 @@
Python/sysmodule.o \
Python/traceback.o \
Python/getopt.o \
+ Python/pystrcmp.o \
Python/pystrtod.o \
Python/$(DYNLOADFILE) \
$(LIBOBJS) \
@@ -554,6 +555,8 @@
Include/pymem.h \
Include/pyport.h \
Include/pystate.h \
+ Include/pystrtod.h \
+ Include/pystrcmp.h \
Include/pythonrun.h \
Include/rangeobject.h \
Include/setobject.h \
Index: PCbuild8/pythoncore/pythoncore.vcproj
===================================================================
--- PCbuild8/pythoncore/pythoncore.vcproj (Revision 59511)
+++ PCbuild8/pythoncore/pythoncore.vcproj (Arbeitskopie)
@@ -736,6 +736,10 @@
>
</File>
<File
+ RelativePath="..\..\Python\pystrcmp.c"
+ >
+ </File>
+ <File
RelativePath="..\..\Python\pystrtod.c"
>
</File>
@@ -1194,6 +1198,10 @@
>
</File>
<File
+ RelativePath="..\..\Include\pystrcmp.h"
+ >
+ </File>
+ <File
RelativePath="..\..\Include\pystrtod.h"
>
</File>
Index: PCbuild9/pythoncore.vcproj
===================================================================
--- PCbuild9/pythoncore.vcproj (Revision 59511)
+++ PCbuild9/pythoncore.vcproj (Arbeitskopie)
@@ -875,6 +875,10 @@
>
</File>
<File
+ RelativePath="..\Include\pystrcmp.h"
+ >
+ </File>
+ <File
RelativePath="..\Include\pystrtod.h"
>
</File>
@@ -1715,6 +1719,10 @@
>
</File>
<File
+ RelativePath="..\Python\pystrcmp.c"
+ >
+ </File>
+ <File
RelativePath="..\Python\pystrtod.c"
>
</File>
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com