[Python-checkins] r46284 - in python/branches/blais-bytebuf: Doc/api/abstract.tex Doc/api/newtypes.tex Doc/lib/libstdtypes.tex Include/longobject.h Include/pyport.h Include/unicodeobject.h Lib/idlelib/configHelpSourceEdit.py Lib/popen2.py Lib/test/string_tests.py Lib/test/test_grp.py Misc/NEWS Misc/developers.txt Modules/_ctypes/libffi/configure Modules/_ctypes/libffi/configure.ac Modules/_ctypes/libffi/fficonfig.h.in Modules/_ctypes/libffi/fficonfig.py.in Modules/_ctypes/libffi/src/darwin Modules/_ctypes/libffi/src/powerpc/darwin.S Modules/_ctypes/libffi/src/powerpc/darwin_closure.S Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c Modules/_ctypes/libffi/src/prep_cif.c Modules/_ctypes/libffi/src/x86/darwin.S Modules/_ctypes/libffi/src/x86/ffi_darwin.c Modules/_ctypes/libffi/src/x86/ffitarget.h Modules/_struct.c Modules/cPickle.c Modules/gcmodule.c Modules/grpmodule.c Modules/parsermodule.c Modules/timemodule.c Objects/classobject.c Objects/floatobject.c Objects/longobject.c Objects/stringobject.c Objects/typeobject.c Objects/unicodeobject.c Objects/weakrefobject.c PC/pyconfig.h Python/ceval.c Python/import.c Python/mystrtoul.c Python/pystrtod.c
martin.blais
python-checkins at python.org
Fri May 26 13:03:58 CEST 2006
Author: martin.blais
Date: Fri May 26 13:03:30 2006
New Revision: 46284
Added:
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/darwin/
- copied from r46282, python/trunk/Modules/_ctypes/libffi/src/darwin/
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/darwin.S
- copied unchanged from r46282, python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
- copied unchanged from r46282, python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
Modified:
python/branches/blais-bytebuf/Doc/api/abstract.tex
python/branches/blais-bytebuf/Doc/api/newtypes.tex
python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex
python/branches/blais-bytebuf/Include/longobject.h
python/branches/blais-bytebuf/Include/pyport.h
python/branches/blais-bytebuf/Include/unicodeobject.h
python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py
python/branches/blais-bytebuf/Lib/popen2.py
python/branches/blais-bytebuf/Lib/test/string_tests.py
python/branches/blais-bytebuf/Lib/test/test_grp.py
python/branches/blais-bytebuf/Misc/NEWS
python/branches/blais-bytebuf/Misc/developers.txt
python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure
python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac
python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in
python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c
python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h
python/branches/blais-bytebuf/Modules/_struct.c
python/branches/blais-bytebuf/Modules/cPickle.c
python/branches/blais-bytebuf/Modules/gcmodule.c
python/branches/blais-bytebuf/Modules/grpmodule.c
python/branches/blais-bytebuf/Modules/parsermodule.c
python/branches/blais-bytebuf/Modules/timemodule.c
python/branches/blais-bytebuf/Objects/classobject.c
python/branches/blais-bytebuf/Objects/floatobject.c
python/branches/blais-bytebuf/Objects/longobject.c
python/branches/blais-bytebuf/Objects/stringobject.c
python/branches/blais-bytebuf/Objects/typeobject.c
python/branches/blais-bytebuf/Objects/unicodeobject.c
python/branches/blais-bytebuf/Objects/weakrefobject.c
python/branches/blais-bytebuf/PC/pyconfig.h
python/branches/blais-bytebuf/Python/ceval.c
python/branches/blais-bytebuf/Python/import.c
python/branches/blais-bytebuf/Python/mystrtoul.c
python/branches/blais-bytebuf/Python/pystrtod.c
Log:
Updated branch bytebuf to 46281
Modified: python/branches/blais-bytebuf/Doc/api/abstract.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/api/abstract.tex (original)
+++ python/branches/blais-bytebuf/Doc/api/abstract.tex Fri May 26 13:03:30 2006
@@ -260,6 +260,8 @@
result of the call on success, or \NULL{} on failure. This is the
equivalent of the Python expression \samp{apply(\var{callable},
\var{args})} or \samp{\var{callable}(*\var{args})}.
+ Note that if you only pass \ctype{PyObject *} args,
+ \cfunction{PyObject_CallFunctionObjArgs} is a faster alternative.
\bifuncindex{apply}
\end{cfuncdesc}
@@ -274,6 +276,8 @@
indicating that no arguments are provided. Returns the result of the
call on success, or \NULL{} on failure. This is the equivalent of
the Python expression \samp{\var{o}.\var{method}(\var{args})}.
+ Note that if you only pass \ctype{PyObject *} args,
+ \cfunction{PyObject_CallMethodObjArgs} is a faster alternative.
\end{cfuncdesc}
Modified: python/branches/blais-bytebuf/Doc/api/newtypes.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/api/newtypes.tex (original)
+++ python/branches/blais-bytebuf/Doc/api/newtypes.tex Fri May 26 13:03:30 2006
@@ -990,10 +990,10 @@
An optional pointer to the rich comparison function.
The signature is the same as for \cfunction{PyObject_RichCompare()}.
- The function should return \code{1} if the requested comparison
- returns true, \code{0} if it returns false. It should return
- \code{-1} and set an exception condition when an error occurred
- during the comparison.
+ The function should return the result of the comparison (usually
+ \code{Py_True} or \code{Py_False}). If the comparison is undefined,
+ it must return \code{Py_NotImplemented}, if another error occurred
+ it must return \code{NULL} and set an exception condition.
This field is inherited by subtypes together with
\member{tp_compare} and \member{tp_hash}: a subtype inherits all
Modified: python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex
==============================================================================
--- python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex (original)
+++ python/branches/blais-bytebuf/Doc/lib/libstdtypes.tex Fri May 26 13:03:30 2006
@@ -727,6 +727,15 @@
\versionchanged[Support for the \var{chars} argument]{2.2.2}
\end{methoddesc}
+\begin{methoddesc}[string]{partition}{sep}
+Splits the string at the first occurence of \var{sep}, and return
+a 3-tuple containing the part before the separator, the separator
+itself, and the part after the separator. If the separator is not
+found, return a 3-tuple containing the string itself, followed by
+two empty strings.
+\versionadded{2.5}
+\end{methoddesc}
+
\begin{methoddesc}[string]{replace}{old, new\optional{, count}}
Return a copy of the string with all occurrences of substring
\var{old} replaced by \var{new}. If the optional argument
Modified: python/branches/blais-bytebuf/Include/longobject.h
==============================================================================
--- python/branches/blais-bytebuf/Include/longobject.h (original)
+++ python/branches/blais-bytebuf/Include/longobject.h Fri May 26 13:03:30 2006
@@ -25,6 +25,7 @@
PyAPI_FUNC(Py_ssize_t) _PyLong_AsSsize_t(PyObject *);
PyAPI_FUNC(PyObject *) _PyLong_FromSize_t(size_t);
PyAPI_FUNC(PyObject *) _PyLong_FromSsize_t(Py_ssize_t);
+PyAPI_DATA(int) _PyLong_DigitValue[256];
/* _PyLong_AsScaledDouble returns a double x and an exponent e such that
the true value is approximately equal to x * 2**(SHIFT*e). e is >= 0.
Modified: python/branches/blais-bytebuf/Include/pyport.h
==============================================================================
--- python/branches/blais-bytebuf/Include/pyport.h (original)
+++ python/branches/blais-bytebuf/Include/pyport.h Fri May 26 13:03:30 2006
@@ -295,6 +295,15 @@
#define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X))
#endif
+/* Py_IS_FINITE(X)
+ * Return 1 if float or double arg is neither infinite nor NAN, else 0.
+ * Some compilers (e.g. VisualStudio) have intrisics for this, so a special
+ * macro for this particular test is useful
+ */
+#ifndef Py_IS_FINITE
+#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
+#endif
+
/* HUGE_VAL is supposed to expand to a positive double infinity. Python
* uses Py_HUGE_VAL instead because some platforms are broken in this
* respect. We used to embed code in pyport.h to try to worm around that,
Modified: python/branches/blais-bytebuf/Include/unicodeobject.h
==============================================================================
--- python/branches/blais-bytebuf/Include/unicodeobject.h (original)
+++ python/branches/blais-bytebuf/Include/unicodeobject.h Fri May 26 13:03:30 2006
@@ -184,6 +184,7 @@
# define PyUnicode_GetMax PyUnicodeUCS2_GetMax
# define PyUnicode_GetSize PyUnicodeUCS2_GetSize
# define PyUnicode_Join PyUnicodeUCS2_Join
+# define PyUnicode_Partition PyUnicodeUCS2_Partition
# define PyUnicode_Replace PyUnicodeUCS2_Replace
# define PyUnicode_Resize PyUnicodeUCS2_Resize
# define PyUnicode_SetDefaultEncoding PyUnicodeUCS2_SetDefaultEncoding
@@ -259,6 +260,7 @@
# define PyUnicode_GetMax PyUnicodeUCS4_GetMax
# define PyUnicode_GetSize PyUnicodeUCS4_GetSize
# define PyUnicode_Join PyUnicodeUCS4_Join
+# define PyUnicode_Partition PyUnicodeUCS4_Partition
# define PyUnicode_Replace PyUnicodeUCS4_Replace
# define PyUnicode_Resize PyUnicodeUCS4_Resize
# define PyUnicode_SetDefaultEncoding PyUnicodeUCS4_SetDefaultEncoding
@@ -1018,6 +1020,13 @@
int keepends /* If true, line end markers are included */
);
+/* Partition a string using a given separator. */
+
+PyAPI_FUNC(PyObject*) PyUnicode_Partition(
+ PyObject *s, /* String to partition */
+ PyObject *sep /* String separator */
+ );
+
/* Split a string giving a list of Unicode strings.
If sep is NULL, splitting will be done at all whitespace
Modified: python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py (original)
+++ python/branches/blais-bytebuf/Lib/idlelib/configHelpSourceEdit.py Fri May 26 13:03:30 2006
@@ -151,6 +151,7 @@
pass
else:
# Mac Safari insists on using the URI form for local files
+ self.result = list(self.result)
self.result[1] = "file://" + path
self.destroy()
Modified: python/branches/blais-bytebuf/Lib/popen2.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/popen2.py (original)
+++ python/branches/blais-bytebuf/Lib/popen2.py Fri May 26 13:03:30 2006
@@ -72,8 +72,9 @@
# In case the child hasn't been waited on, check if it's done.
self.poll(_deadstate=sys.maxint)
if self.sts < 0:
- # Child is still running, keep us alive until we can wait on it.
- _active.append(self)
+ if _active:
+ # Child is still running, keep us alive until we can wait on it.
+ _active.append(self)
def _run_child(self, cmd):
if isinstance(cmd, basestring):
Modified: python/branches/blais-bytebuf/Lib/test/string_tests.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/string_tests.py (original)
+++ python/branches/blais-bytebuf/Lib/test/string_tests.py Fri May 26 13:03:30 2006
@@ -555,15 +555,14 @@
self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
-### Commented out until the underlying libraries are fixed
-## def test_replace_overflow(self):
-## # Check for overflow checking on 32 bit machines
-## if sys.maxint != 2147483647:
-## return
-## A2_16 = "A" * (2**16)
-## self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
-## self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
-## self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
+ def test_replace_overflow(self):
+ # Check for overflow checking on 32 bit machines
+ if sys.maxint != 2147483647:
+ return
+ A2_16 = "A" * (2**16)
+ self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
+ self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
+ self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
def test_zfill(self):
self.checkequal('123', '123', 'zfill', 2)
@@ -882,6 +881,40 @@
else:
self.checkcall(format, "__mod__", value)
+ def test_inplace_rewrites(self):
+ # Check that strings don't copy and modify cached single-character strings
+ self.checkequal('a', 'A', 'lower')
+ self.checkequal(True, 'A', 'isupper')
+ self.checkequal('A', 'a', 'upper')
+ self.checkequal(True, 'a', 'islower')
+
+ self.checkequal('a', 'A', 'replace', 'A', 'a')
+ self.checkequal(True, 'A', 'isupper')
+
+ self.checkequal('A', 'a', 'capitalize')
+ self.checkequal(True, 'a', 'islower')
+
+ self.checkequal('A', 'a', 'swapcase')
+ self.checkequal(True, 'a', 'islower')
+
+ self.checkequal('A', 'a', 'title')
+ self.checkequal(True, 'a', 'islower')
+
+ def test_partition(self):
+
+ self.checkequal(('this', ' is ', 'the partition method'),
+ 'this is the partition method', 'partition', ' is ')
+
+ # from raymond's original specification
+ S = 'http://www.python.org'
+ self.checkequal(('http', '://', 'www.python.org'), S, 'partition', '://')
+ self.checkequal(('http://www.python.org', '', ''), S, 'partition', '?')
+ self.checkequal(('', 'http://', 'www.python.org'), S, 'partition', 'http://')
+ self.checkequal(('http://www.python.', 'org', ''), S, 'partition', 'org')
+
+ self.checkraises(ValueError, S, 'partition', '')
+ self.checkraises(TypeError, S, 'partition', None)
+
class MixinStrStringUserStringTest:
# Additional tests for 8bit strings, i.e. str, UserString and
Modified: python/branches/blais-bytebuf/Lib/test/test_grp.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/test_grp.py (original)
+++ python/branches/blais-bytebuf/Lib/test/test_grp.py Fri May 26 13:03:30 2006
@@ -31,7 +31,10 @@
self.assertEqual(e2.gr_gid, e.gr_gid)
e2 = grp.getgrnam(e.gr_name)
self.check_value(e2)
- self.assertEqual(e2.gr_name, e.gr_name)
+ # There are instances where getgrall() returns group names in
+ # lowercase while getgrgid() returns proper casing.
+ # Discovered on Ubuntu 5.04 (custom).
+ self.assertEqual(e2.gr_name.lower(), e.gr_name.lower())
def test_errors(self):
self.assertRaises(TypeError, grp.getgrgid)
Modified: python/branches/blais-bytebuf/Misc/NEWS
==============================================================================
--- python/branches/blais-bytebuf/Misc/NEWS (original)
+++ python/branches/blais-bytebuf/Misc/NEWS Fri May 26 13:03:30 2006
@@ -64,6 +64,10 @@
- Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
As a result, these functions now raise WindowsError instead of OSError.
+- ``time.clock()`` on Win64 should use the high-performance Windows
+ ``QueryPerformanceCounter()`` now (as was already the case on 32-bit
+ Windows platforms).
+
- Calling Tk_Init twice is refused if the first call failed as that
may deadlock.
Modified: python/branches/blais-bytebuf/Misc/developers.txt
==============================================================================
--- python/branches/blais-bytebuf/Misc/developers.txt (original)
+++ python/branches/blais-bytebuf/Misc/developers.txt Fri May 26 13:03:30 2006
@@ -18,10 +18,11 @@
-------------------
- 2006 Summer of Code entries: Matt Fleming was added on 25 May 2006
- by AMK; he'll be working on enhancing the Python debugger. SoC
- developers are expected to work primarily in nondist/sandbox or on a
- branch of their own, and will have their work reviewed before
- changes are accepted into the trunk.
+ by AMK; he'll be working on enhancing the Python debugger. Jackilyn
+ Hoxworth was added on 25 May 2005 by AMK; she'll be adding logging
+ to the standard library. SoC developers are expected to work
+ primarily in nondist/sandbox or on a branch of their own, and will
+ have their work reviewed before changes are accepted into the trunk.
- Steven Bethard was given SVN access on 27 Apr 2006 by DJG, for PEP
update access.
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure Fri May 26 13:03:30 2006
@@ -3483,6 +3483,7 @@
TARGETDIR="unknown"
case "$host" in
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
i*86-*-solaris2.1[0-9]*) TARGET=X86_64; TARGETDIR=x86;;
@@ -5243,6 +5244,9 @@
esac
+
+
+
if test x$TARGET = xSPARC; then
echo "$as_me:$LINENO: checking assembler and linker support unaligned pc related relocs" >&5
echo $ECHO_N "checking assembler and linker support unaligned pc related relocs... $ECHO_C" >&6
@@ -5470,7 +5474,15 @@
ac_config_commands="$ac_config_commands src"
- ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
+TARGETINCDIR=$TARGETDIR
+case $host in
+*-*-darwin*)
+ TARGETINCDIR="darwin"
+ ;;
+esac
+
+
+ ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h"
ac_config_links="$ac_config_links include/ffi_common.h:include/ffi_common.h"
@@ -6017,7 +6029,7 @@
# Handling of arguments.
"include/ffi.h" ) CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
"fficonfig.py" ) CONFIG_FILES="$CONFIG_FILES fficonfig.py" ;;
- "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;;
+ "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h" ;;
"include/ffi_common.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffi_common.h:include/ffi_common.h" ;;
"include" ) CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
"src" ) CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;;
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/configure.ac Fri May 26 13:03:30 2006
@@ -21,6 +21,7 @@
TARGETDIR="unknown"
case "$host" in
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;;
@@ -99,6 +100,24 @@
AC_SUBST(HAVE_LONG_DOUBLE)
AC_C_BIGENDIAN
+AH_VERBATIM([WORDS_BIGENDIAN],
+[
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX).
+
+ The block below does compile-time checking for endianness on platforms
+ that use GCC and therefore allows compiling fat binaries on OSX by using
+ '-arch ppc -arch i386' as the compile flags. The phrasing was choosen
+ such that the configure-result is used on systems that don't use GCC.
+*/
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN 1
+#else
+#ifndef __LITTLE_ENDIAN__
+#undef WORDS_BIGENDIAN
+#endif
+#endif])
+
if test x$TARGET = xSPARC; then
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
@@ -201,7 +220,15 @@
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
], [TARGETDIR="$TARGETDIR"])
-AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
+TARGETINCDIR=$TARGETDIR
+case $host in
+*-*-darwin*)
+ TARGETINCDIR="darwin"
+ ;;
+esac
+
+
+AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h)
AC_CONFIG_LINKS(include/ffi_common.h:include/ffi_common.h)
AC_CONFIG_FILES(include/ffi.h fficonfig.py)
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.h.in Fri May 26 13:03:30 2006
@@ -114,9 +114,22 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+
/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
+ first (like Motorola and SPARC, unlike Intel and VAX).
+
+ The block below does compile-time checking for endianness on platforms
+ that use GCC and therefore allows compiling fat binaries on OSX by using
+ '-arch ppc -arch i386' as the compile flags. The phrasing was choosen
+ such that the configure-result is used on systems that don't use GCC.
+*/
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN 1
+#else
+#ifndef __LITTLE_ENDIAN__
#undef WORDS_BIGENDIAN
+#endif
+#endif
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/fficonfig.py.in Fri May 26 13:03:30 2006
@@ -6,6 +6,7 @@
'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'],
'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'],
'X86': ['src/x86/ffi.c', 'src/x86/sysv.S'],
+ 'X86_DARWIN': ['src/x86/ffi_darwin.c', 'src/x86/darwin.S'],
'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'],
'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'],
'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'],
@@ -26,6 +27,17 @@
'PA': ['src/pa/linux.S', 'src/pa/ffi.c'],
}
+# Build all darwin related files on all supported darwin architectures, this
+# makes it easier to build universal binaries.
+if 0:
+ all_darwin = ('X86_DARWIN', 'POWERPC_DARWIN')
+ all_darwin_files = []
+ for pn in all_darwin:
+ all_darwin_files.extend(ffi_platforms[pn])
+ for pn in all_darwin:
+ ffi_platforms[pn] = all_darwin_files
+ del all_darwin, all_darwin_files, pn
+
ffi_srcdir = '@srcdir@'
ffi_sources += ffi_platforms['@MKTARGET@']
ffi_sources = [os.path.join('@srcdir@', f) for f in ffi_sources]
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin.S Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
/* -----------------------------------------------------------------------
darwin.S - Copyright (c) 2000 John Hornkvist
Copyright (c) 2004 Free Software Foundation, Inc.
@@ -243,3 +244,4 @@
.align LOG2_GPR_BYTES
LLFB0$non_lazy_ptr:
.g_long LFB0
+#endif
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
/* -----------------------------------------------------------------------
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
Inc. based on ppc_closure.S
@@ -315,3 +316,4 @@
.align LOG2_GPR_BYTES
LLFB1$non_lazy_ptr:
.g_long LFB1
+#endif
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c Fri May 26 13:03:30 2006
@@ -1,3 +1,4 @@
+#ifdef __ppc__
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Geoffrey Keating
@@ -767,3 +768,4 @@
/* Tell ffi_closure_ASM to perform return type promotions. */
return cif->rtype->type;
}
+#endif
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/prep_cif.c Fri May 26 13:03:30 2006
@@ -55,11 +55,29 @@
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
+#ifdef POWERPC_DARWIN
+ {
+ int curalign;
+
+ curalign = (*ptr)->alignment;
+ if (ptr != &(arg->elements[0])) {
+ if (curalign > 4 && curalign != 16) {
+ curalign = 4;
+ }
+ }
+ arg->size = ALIGN(arg->size, curalign);
+ arg->size += (*ptr)->size;
+
+ arg->alignment = (arg->alignment > curalign) ?
+ arg->alignment : curalign;
+ }
+#else
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
+#endif
ptr++;
}
@@ -89,6 +107,19 @@
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
+#ifdef X86_DARWIN
+static inline int struct_on_stack(int size)
+{
+ if (size > 8) return 1;
+ /* This is not what the ABI says, but is what is really implemented */
+ switch (size) {
+ case 1: case 2: case 4: case 8: return 0;
+ }
+ return 1;
+}
+#endif
+
+
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_abi abi, unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
@@ -124,6 +155,10 @@
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
+#ifdef X86_DARWIN
+
+ && (struct_on_stack(cif->rtype->size))
+#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
@@ -139,7 +174,16 @@
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
-#if !defined __x86_64__ && !defined S390 && !defined PA
+#if defined(X86_DARWIN)
+ {
+ int align = (*ptr)->alignment;
+ if (align > 4) align = 4;
+ if ((align - 1) & bytes)
+ bytes = ALIGN(bytes, align);
+ bytes += STACK_ARG_SIZE((*ptr)->size);
+ }
+
+#elif !defined __x86_64__ && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
Modified: python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h
==============================================================================
--- python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h (original)
+++ python/branches/blais-bytebuf/Modules/_ctypes/libffi/src/x86/ffitarget.h Fri May 26 13:03:30 2006
@@ -51,7 +51,7 @@
#endif
/* ---- Intel x86 and AMD x86-64 - */
-#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
+#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
FFI_SYSV,
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
#ifdef __i386__
Modified: python/branches/blais-bytebuf/Modules/_struct.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_struct.c (original)
+++ python/branches/blais-bytebuf/Modules/_struct.c Fri May 26 13:03:30 2006
@@ -18,6 +18,14 @@
/* Forward declarations */
static Py_ssize_t convertbuffer(PyObject *, void **p);
+/* PY_USE_INT_WHEN_POSSIBLE is an experimental flag that changes the
+ struct API to return int instead of long when possible. This is
+ often a significant performance improvement. */
+/*
+#define PY_USE_INT_WHEN_POSSIBLE 1
+*/
+
+
/* The translation function for each format character is table driven */
typedef struct _formatdef {
char format;
@@ -284,6 +292,10 @@
{
unsigned int x;
memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
+ return PyInt_FromLong((long)x);
+#endif
return PyLong_FromUnsignedLong((unsigned long)x);
}
@@ -300,6 +312,10 @@
{
unsigned long x;
memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
+ return PyInt_FromLong((long)x);
+#endif
return PyLong_FromUnsignedLong(x);
}
@@ -313,6 +329,10 @@
{
PY_LONG_LONG x;
memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x >= LONG_MIN && x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
return PyLong_FromLongLong(x);
}
@@ -321,6 +341,10 @@
{
unsigned PY_LONG_LONG x;
memcpy((char *)&x, p, sizeof x);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
return PyLong_FromUnsignedLongLong(x);
}
@@ -550,13 +574,13 @@
{'I', sizeof(int), INT_ALIGN, nu_uint, np_uint},
{'l', sizeof(long), LONG_ALIGN, nu_long, np_long},
{'L', sizeof(long), LONG_ALIGN, nu_ulong, np_ulong},
- {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
- {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
- {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
#ifdef HAVE_LONG_LONG
{'q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
{'Q', sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
#endif
+ {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
+ {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
+ {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
{0}
};
@@ -584,28 +608,61 @@
do {
x = (x<<8) | (*p++ & 0xFF);
} while (--i > 0);
- if (f->size >= 4)
- return PyLong_FromUnsignedLong(x);
- else
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
return PyInt_FromLong((long)x);
+#else
+ if (SIZEOF_LONG > f->size)
+ return PyInt_FromLong((long)x);
+#endif
+ return PyLong_FromUnsignedLong(x);
}
static PyObject *
bu_longlong(const char *p, const formatdef *f)
{
+#if HAVE_LONG_LONG
+ PY_LONG_LONG x = 0;
+ int i = f->size;
+ do {
+ x = (x<<8) | (*p++ & 0xFF);
+ } while (--i > 0);
+ /* Extend the sign bit. */
+ if (SIZEOF_LONG_LONG > f->size)
+ x |= -(x & (1L << (8 * f->size - 1)));
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x >= LONG_MIN && x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
+ return PyLong_FromLongLong(x);
+#else
return _PyLong_FromByteArray((const unsigned char *)p,
8,
0, /* little-endian */
1 /* signed */);
+#endif
}
static PyObject *
bu_ulonglong(const char *p, const formatdef *f)
{
+#if HAVE_LONG_LONG
+ unsigned PY_LONG_LONG x = 0;
+ int i = f->size;
+ do {
+ x = (x<<8) | (*p++ & 0xFF);
+ } while (--i > 0);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
+ return PyLong_FromUnsignedLongLong(x);
+#else
return _PyLong_FromByteArray((const unsigned char *)p,
8,
0, /* little-endian */
0 /* signed */);
+#endif
}
static PyObject *
@@ -750,28 +807,61 @@
do {
x = (x<<8) | (p[--i] & 0xFF);
} while (i > 0);
- if (f->size >= 4)
- return PyLong_FromUnsignedLong(x);
- else
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
return PyInt_FromLong((long)x);
+#else
+ if (SIZEOF_LONG > f->size)
+ return PyInt_FromLong((long)x);
+#endif
+ return PyLong_FromUnsignedLong((long)x);
}
static PyObject *
lu_longlong(const char *p, const formatdef *f)
{
+#if HAVE_LONG_LONG
+ PY_LONG_LONG x = 0;
+ int i = f->size;
+ do {
+ x = (x<<8) | (p[--i] & 0xFF);
+ } while (i > 0);
+ /* Extend the sign bit. */
+ if (SIZEOF_LONG_LONG > f->size)
+ x |= -(x & (1L << (8 * f->size - 1)));
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x >= LONG_MIN && x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
+#endif
+ return PyLong_FromLongLong(x);
+#else
return _PyLong_FromByteArray((const unsigned char *)p,
8,
1, /* little-endian */
1 /* signed */);
+#endif
}
static PyObject *
lu_ulonglong(const char *p, const formatdef *f)
{
+#if HAVE_LONG_LONG
+ unsigned PY_LONG_LONG x = 0;
+ int i = f->size;
+ do {
+ x = (x<<8) | (p[--i] & 0xFF);
+ } while (i > 0);
+#ifdef PY_USE_INT_WHEN_POSSIBLE
+ if (x <= LONG_MAX)
+ return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
+#endif
+ return PyLong_FromUnsignedLongLong(x);
+#else
return _PyLong_FromByteArray((const unsigned char *)p,
8,
1, /* little-endian */
0 /* signed */);
+#endif
}
static PyObject *
@@ -1446,7 +1536,7 @@
static
PyTypeObject PyStructType = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0,
"Struct",
sizeof(PyStructObject),
@@ -1497,14 +1587,59 @@
if (m == NULL)
return;
+ PyStructType.ob_type = &PyType_Type;
+ if (PyType_Ready(&PyStructType) < 0)
+ return;
+
+ /* Check endian and swap in faster functions */
+ {
+ int one = 1;
+ formatdef *native = native_table;
+ formatdef *other, *ptr;
+ if ((int)*(unsigned char*)&one)
+ other = lilendian_table;
+ else
+ other = bigendian_table;
+ /* Scan through the native table, find a matching
+ entry in the endian table and swap in the
+ native implementations whenever possible
+ (64-bit platforms may not have "standard" sizes) */
+ while (native->format != '\0' && other->format != '\0') {
+ ptr = other;
+ while (ptr->format != '\0') {
+ if (ptr->format == native->format) {
+ /* Match faster when formats are
+ listed in the same order */
+ if (ptr == other)
+ other++;
+ /* Only use the trick if the
+ size matches */
+ if (ptr->size != native->size)
+ break;
+ /* Skip float and double, could be
+ "unknown" float format */
+ if (ptr->format == 'd' || ptr->format == 'f')
+ break;
+ ptr->pack = native->pack;
+ ptr->unpack = native->unpack;
+ break;
+ }
+ ptr++;
+ }
+ native++;
+ }
+ }
+
/* Add some symbolic constants to the module */
if (StructError == NULL) {
StructError = PyErr_NewException("struct.error", NULL, NULL);
if (StructError == NULL)
return;
}
+
Py_INCREF(StructError);
PyModule_AddObject(m, "error", StructError);
+
Py_INCREF((PyObject*)&PyStructType);
PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
}
Modified: python/branches/blais-bytebuf/Modules/cPickle.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/cPickle.c (original)
+++ python/branches/blais-bytebuf/Modules/cPickle.c Fri May 26 13:03:30 2006
@@ -3073,8 +3073,8 @@
"pickles are not supported.");
return NULL;
}
- return PyObject_CallFunction(fc, "OO", py_module_name,
- py_global_name);
+ return PyObject_CallFunctionObjArgs(fc, py_module_name,
+ py_global_name, NULL);
}
module = PySys_GetObject("modules");
Modified: python/branches/blais-bytebuf/Modules/gcmodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/gcmodule.c (original)
+++ python/branches/blais-bytebuf/Modules/gcmodule.c Fri May 26 13:03:30 2006
@@ -603,7 +603,7 @@
assert(callback != NULL);
/* copy-paste of weakrefobject.c's handle_callback() */
- temp = PyObject_CallFunction(callback, "O", wr);
+ temp = PyObject_CallFunctionObjArgs(callback, wr, NULL);
if (temp == NULL)
PyErr_WriteUnraisable(callback);
else
Modified: python/branches/blais-bytebuf/Modules/grpmodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/grpmodule.c (original)
+++ python/branches/blais-bytebuf/Modules/grpmodule.c Fri May 26 13:03:30 2006
@@ -84,12 +84,18 @@
}
static PyObject *
-grp_getgrgid(PyObject *self, PyObject *args)
+grp_getgrgid(PyObject *self, PyObject *pyo_id)
{
+ PyObject *py_int_id;
unsigned int gid;
struct group *p;
- if (!PyArg_ParseTuple(args, "I:getgrgid", &gid))
- return NULL;
+
+ py_int_id = PyNumber_Int(pyo_id);
+ if (!py_int_id)
+ return NULL;
+ gid = PyInt_AS_LONG(py_int_id);
+ Py_DECREF(py_int_id);
+
if ((p = getgrgid(gid)) == NULL) {
PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %d", gid);
return NULL;
@@ -98,27 +104,33 @@
}
static PyObject *
-grp_getgrnam(PyObject *self, PyObject *args)
+grp_getgrnam(PyObject *self, PyObject *pyo_name)
{
+ PyObject *py_str_name;
char *name;
struct group *p;
- if (!PyArg_ParseTuple(args, "s:getgrnam", &name))
- return NULL;
+
+ py_str_name = PyObject_Str(pyo_name);
+ if (!py_str_name)
+ return NULL;
+ name = PyString_AS_STRING(py_str_name);
+
if ((p = getgrnam(name)) == NULL) {
PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name);
+ Py_DECREF(py_str_name);
return NULL;
}
+
+ Py_DECREF(py_str_name);
return mkgrent(p);
}
static PyObject *
-grp_getgrall(PyObject *self, PyObject *args)
+grp_getgrall(PyObject *self, PyObject *ignore)
{
PyObject *d;
struct group *p;
- if (!PyArg_ParseTuple(args, ":getgrall"))
- return NULL;
if ((d = PyList_New(0)) == NULL)
return NULL;
setgrent();
@@ -136,15 +148,15 @@
}
static PyMethodDef grp_methods[] = {
- {"getgrgid", grp_getgrgid, METH_VARARGS,
+ {"getgrgid", grp_getgrgid, METH_O,
"getgrgid(id) -> tuple\n\
Return the group database entry for the given numeric group ID. If\n\
id is not valid, raise KeyError."},
- {"getgrnam", grp_getgrnam, METH_VARARGS,
+ {"getgrnam", grp_getgrnam, METH_O,
"getgrnam(name) -> tuple\n\
Return the group database entry for the given group name. If\n\
name is not valid, raise KeyError."},
- {"getgrall", grp_getgrall, METH_VARARGS,
+ {"getgrall", grp_getgrall, METH_NOARGS,
"getgrall() -> list of tuples\n\
Return a list of all available group entries, in arbitrary order."},
{NULL, NULL} /* sentinel */
Modified: python/branches/blais-bytebuf/Modules/parsermodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/parsermodule.c (original)
+++ python/branches/blais-bytebuf/Modules/parsermodule.c Fri May 26 13:03:30 2006
@@ -3267,8 +3267,8 @@
&& (pickler != NULL)) {
PyObject *res;
- res = PyObject_CallFunction(func, "OOO", &PyST_Type, pickler,
- pickle_constructor);
+ res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler,
+ pickle_constructor, NULL);
Py_XDECREF(res);
}
Py_XDECREF(func);
Modified: python/branches/blais-bytebuf/Modules/timemodule.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/timemodule.c (original)
+++ python/branches/blais-bytebuf/Modules/timemodule.c Fri May 26 13:03:30 2006
@@ -63,11 +63,10 @@
#endif /* MS_WINDOWS */
#endif /* !__WATCOMC__ || __QNX__ */
-#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__)
-/* Win32 has better clock replacement
- XXX Win64 does not yet, but might when the platform matures. */
-#undef HAVE_CLOCK /* We have our own version down below */
-#endif /* MS_WINDOWS && !MS_WIN64 */
+#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
+/* Win32 has better clock replacement; we have our own version below. */
+#undef HAVE_CLOCK
+#endif /* MS_WINDOWS && !defined(__BORLANDC__) */
#if defined(PYOS_OS2)
#define INCL_DOS
@@ -162,7 +161,7 @@
}
#endif /* HAVE_CLOCK */
-#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__)
+#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
/* Due to Mark Hammond and Tim Peters */
static PyObject *
time_clock(PyObject *self, PyObject *args)
@@ -191,7 +190,7 @@
}
#define HAVE_CLOCK /* So it gets included in the methods */
-#endif /* MS_WINDOWS && !MS_WIN64 */
+#endif /* MS_WINDOWS && !defined(__BORLANDC__) */
#ifdef HAVE_CLOCK
PyDoc_STRVAR(clock_doc,
@@ -821,7 +820,7 @@
SetConsoleCtrlHandler( PyCtrlHandler, TRUE);
#endif /* MS_WINDOWS */
if (!initialized) {
- PyStructSequence_InitType(&StructTimeType,
+ PyStructSequence_InitType(&StructTimeType,
&struct_time_type_desc);
}
Py_INCREF(&StructTimeType);
Modified: python/branches/blais-bytebuf/Objects/classobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/classobject.c (original)
+++ python/branches/blais-bytebuf/Objects/classobject.c Fri May 26 13:03:30 2006
@@ -81,12 +81,9 @@
if (!PyClass_Check(base)) {
if (PyCallable_Check(
(PyObject *) base->ob_type))
- return PyObject_CallFunction(
+ return PyObject_CallFunctionObjArgs(
(PyObject *) base->ob_type,
- "OOO",
- name,
- bases,
- dict);
+ name, bases, dict, NULL);
PyErr_SetString(PyExc_TypeError,
"PyClass_New: base must be a class");
return NULL;
Modified: python/branches/blais-bytebuf/Objects/floatobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/floatobject.c (original)
+++ python/branches/blais-bytebuf/Objects/floatobject.c Fri May 26 13:03:30 2006
@@ -384,7 +384,7 @@
if (PyFloat_Check(w))
j = PyFloat_AS_DOUBLE(w);
- else if (Py_IS_INFINITY(i) || Py_IS_NAN(i)) {
+ else if (!Py_IS_FINITE(i)) {
if (PyInt_Check(w) || PyLong_Check(w))
/* If i is an infinity, its magnitude exceeds any
* finite integer, so it doesn't matter which int we
@@ -802,10 +802,7 @@
* bug; we let that slide in math.pow() (which currently
* reflects all platform accidents), but not for Python's **.
*/
- if (iv == -1.0 && !Py_IS_INFINITY(iw) && iw == iw) {
- /* XXX the "iw == iw" was to weed out NaNs. This
- * XXX doesn't actually work on all platforms.
- */
+ if (iv == -1.0 && Py_IS_FINITE(iw)) {
/* Return 1 if iw is even, -1 if iw is odd; there's
* no guarantee that any C integral type is big
* enough to hold iw, so we have to check this
Modified: python/branches/blais-bytebuf/Objects/longobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/longobject.c (original)
+++ python/branches/blais-bytebuf/Objects/longobject.c Fri May 26 13:03:30 2006
@@ -40,7 +40,7 @@
#define SIGCHECK(PyTryBlock) \
if (--_Py_Ticker < 0) { \
_Py_Ticker = _Py_CheckInterval; \
- if (PyErr_CheckSignals()) { PyTryBlock; } \
+ if (PyErr_CheckSignals()) PyTryBlock \
}
/* Normalize (remove leading zeros from) a long int object.
@@ -844,11 +844,36 @@
PyObject *
PyLong_FromLongLong(PY_LONG_LONG ival)
{
- PY_LONG_LONG bytes = ival;
- int one = 1;
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
+ PyLongObject *v;
+ unsigned PY_LONG_LONG t; /* unsigned so >> doesn't propagate sign bit */
+ int ndigits = 0;
+ int negative = 0;
+
+ if (ival < 0) {
+ ival = -ival;
+ negative = 1;
+ }
+
+ /* Count the number of Python digits.
+ We used to pick 5 ("big enough for anything"), but that's a
+ waste of time and space given that 5*15 = 75 bits are rarely
+ needed. */
+ t = (unsigned PY_LONG_LONG)ival;
+ while (t) {
+ ++ndigits;
+ t >>= SHIFT;
+ }
+ v = _PyLong_New(ndigits);
+ if (v != NULL) {
+ digit *p = v->ob_digit;
+ v->ob_size = negative ? -ndigits : ndigits;
+ t = (unsigned PY_LONG_LONG)ival;
+ while (t) {
+ *p++ = (digit)(t & MASK);
+ t >>= SHIFT;
+ }
+ }
+ return (PyObject *)v;
}
/* Create a new long int object from a C unsigned PY_LONG_LONG int. */
@@ -856,11 +881,26 @@
PyObject *
PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
{
- unsigned PY_LONG_LONG bytes = ival;
- int one = 1;
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
+ PyLongObject *v;
+ unsigned PY_LONG_LONG t;
+ int ndigits = 0;
+
+ /* Count the number of Python digits. */
+ t = (unsigned PY_LONG_LONG)ival;
+ while (t) {
+ ++ndigits;
+ t >>= SHIFT;
+ }
+ v = _PyLong_New(ndigits);
+ if (v != NULL) {
+ digit *p = v->ob_digit;
+ v->ob_size = ndigits;
+ while (ival) {
+ *p++ = (digit)(ival & MASK);
+ ival >>= SHIFT;
+ }
+ }
+ return (PyObject *)v;
}
/* Create a new long int object from a C Py_ssize_t. */
@@ -1304,7 +1344,14 @@
return (PyObject *)str;
}
-static int digval[] = {
+/* Table of digit values for 8-bit string -> integer conversion.
+ * '0' maps to 0, ..., '9' maps to 9.
+ * 'a' and 'A' map to 10, ..., 'z' and 'Z' map to 35.
+ * All other indices map to 37.
+ * Note that when converting a base B string, a char c is a legitimate
+ * base B digit iff _PyLong_DigitValue[Py_CHARMASK(c)] < B.
+ */
+int _PyLong_DigitValue[256] = {
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
@@ -1321,14 +1368,6 @@
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
};
/* *str points to the first digit in a string of base `base` digits. base
@@ -1355,7 +1394,7 @@
n >>= 1;
/* n <- total # of bits needed, while setting p to end-of-string */
n = 0;
- while (digval[Py_CHARMASK(*p)] < base)
+ while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base)
++p;
*str = p;
n = (p - start) * bits_per_char;
@@ -1376,7 +1415,7 @@
bits_in_accum = 0;
pdigit = z->ob_digit;
while (--p >= start) {
- int k = digval[Py_CHARMASK(*p)];
+ int k = _PyLong_DigitValue[Py_CHARMASK(*p)];
assert(k >= 0 && k < base);
accum |= (twodigits)(k << bits_in_accum);
bits_in_accum += bits_per_char;
@@ -1503,7 +1542,7 @@
/* Find length of the string of numeric characters. */
scan = str;
- while (digval[Py_CHARMASK(*scan)] < base)
+ while (_PyLong_DigitValue[Py_CHARMASK(*scan)] < base)
++scan;
/* Create a long object that can contain the largest possible
@@ -1527,10 +1566,10 @@
/* Work ;-) */
while (str < scan) {
/* grab up to convwidth digits from the input string */
- c = (digit)digval[Py_CHARMASK(*str++)];
+ c = (digit)_PyLong_DigitValue[Py_CHARMASK(*str++)];
for (i = 1; i < convwidth && str != scan; ++i, ++str) {
c = (twodigits)(c * base +
- digval[Py_CHARMASK(*str)]);
+ _PyLong_DigitValue[Py_CHARMASK(*str)]);
assert(c < BASE);
}
Modified: python/branches/blais-bytebuf/Objects/stringobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/stringobject.c (original)
+++ python/branches/blais-bytebuf/Objects/stringobject.c Fri May 26 13:03:30 2006
@@ -5,6 +5,18 @@
#include <ctype.h>
+#undef USE_INLINE /* XXX - set via configure? */
+
+#if defined(_MSC_VER) /* this is taken from _sre.c */
+#pragma warning(disable: 4710)
+/* fastest possible local call under MSVC */
+#define LOCAL(type) static __inline type __fastcall
+#elif defined(USE_INLINE)
+#define LOCAL(type) static inline type
+#else
+#define LOCAL(type) static type
+#endif
+
#ifdef COUNT_ALLOCS
int null_strings, one_strings;
#endif
@@ -763,6 +775,105 @@
return 0;
}
+/* -------------------------------------------------------------------- */
+/* Helpers */
+
+#define USE_FAST /* experimental fast search implementation */
+
+/* XXX - this code is copied from unicodeobject.c. we really should
+ refactor the core implementations (see _sre.c for how this can be
+ done), but that'll have to wait -- fredrik */
+
+/* fast search/count implementation, based on a mix between boyer-
+ moore and horspool, with a few more bells and whistles on the top.
+ for some more background, see: http://effbot.org/stringlib */
+
+/* note: fastsearch may access s[n], which isn't a problem when using
+ Python's ordinary string types, but may cause problems if you're
+ using this code in other contexts. also, the count mode returns -1
+ if there cannot possibly be a match in the target string, and 0 if
+ it has actually checked for matches, but didn't find any. callers
+ beware! */
+
+#define FAST_COUNT 0
+#define FAST_SEARCH 1
+
+LOCAL(Py_ssize_t)
+fastsearch(const char* s, Py_ssize_t n, const char* p, Py_ssize_t m, int mode)
+{
+ long mask;
+ Py_ssize_t skip, count = 0;
+ Py_ssize_t i, j, mlast, w;
+
+ w = n - m;
+
+ if (w < 0)
+ return -1;
+
+ /* look for special cases */
+ if (m <= 1) {
+ if (m <= 0)
+ return -1;
+ /* use special case for 1-character strings */
+ if (mode == FAST_COUNT) {
+ for (i = 0; i < n; i++)
+ if (s[i] == p[0])
+ count++;
+ return count;
+ } else {
+ for (i = 0; i < n; i++)
+ if (s[i] == p[0])
+ return i;
+ }
+ return -1;
+ }
+
+ mlast = m - 1;
+
+ /* create compressed boyer-moore delta 1 table */
+ skip = mlast - 1;
+ /* process pattern[:-1] */
+ for (mask = i = 0; i < mlast; i++) {
+ mask |= (1 << (p[i] & 0x1F));
+ if (p[i] == p[mlast])
+ skip = mlast - i - 1;
+ }
+ /* process pattern[-1] outside the loop */
+ mask |= (1 << (p[mlast] & 0x1F));
+
+ for (i = 0; i <= w; i++) {
+ /* note: using mlast in the skip path slows things down on x86 */
+ if (s[i+m-1] == p[m-1]) {
+ /* candidate match */
+ for (j = 0; j < mlast; j++)
+ if (s[i+j] != p[j])
+ break;
+ if (j == mlast) {
+ /* got a match! */
+ if (mode != FAST_COUNT)
+ return i;
+ count++;
+ i = i + mlast;
+ continue;
+ }
+ /* miss: check if next character is part of pattern */
+ if (!(mask & (1 << (s[i+m] & 0x1F))))
+ i = i + m;
+ else
+ i = i + skip;
+ } else {
+ /* skip: check if next character is part of pattern */
+ if (!(mask & (1 << (s[i+m] & 0x1F))))
+ i = i + m;
+ }
+ }
+
+ if (mode != FAST_COUNT)
+ return -1;
+ return count;
+}
+
+/* -------------------------------------------------------------------- */
/* Methods */
static int
@@ -909,7 +1020,7 @@
static PyObject *
string_concat(register PyStringObject *a, register PyObject *bb)
{
- register size_t size;
+ register Py_ssize_t size;
register PyStringObject *op;
if (!PyString_Check(bb)) {
#ifdef Py_USING_UNICODE
@@ -933,7 +1044,12 @@
return (PyObject *)a;
}
size = a->ob_size + b->ob_size;
- /* XXX check overflow */
+ if (size < 0) {
+ PyErr_SetString(PyExc_OverflowError,
+ "strings are too large to concat");
+ return NULL;
+ }
+
/* Inline PyObject_NewVar */
op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
if (op == NULL)
@@ -1030,10 +1146,14 @@
{
char *s = PyString_AS_STRING(a);
const char *sub = PyString_AS_STRING(el);
- char *last;
Py_ssize_t len_sub = PyString_GET_SIZE(el);
+#ifdef USE_FAST
+ Py_ssize_t pos;
+#else
+ char *last;
Py_ssize_t shortsub;
char firstchar, lastchar;
+#endif
if (!PyString_CheckExact(el)) {
#ifdef Py_USING_UNICODE
@@ -1049,6 +1169,14 @@
if (len_sub == 0)
return 1;
+
+#ifdef USE_FAST
+ pos = fastsearch(
+ s, PyString_GET_SIZE(a),
+ sub, len_sub, FAST_SEARCH
+ );
+ return (pos != -1);
+#else
/* last points to one char beyond the start of the rightmost
substring. When s<last, there is still room for a possible match
and s[0] through s[len_sub-1] will be in bounds.
@@ -1069,6 +1197,7 @@
return 1;
s++;
}
+#endif
return 0;
}
@@ -1329,18 +1458,6 @@
else \
Py_DECREF(str);
-#define SPLIT_INSERT(data, left, right) \
- str = PyString_FromStringAndSize((data) + (left), \
- (right) - (left)); \
- if (str == NULL) \
- goto onError; \
- if (PyList_Insert(list, 0, str)) { \
- Py_DECREF(str); \
- goto onError; \
- } \
- else \
- Py_DECREF(str);
-
static PyObject *
split_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
{
@@ -1481,6 +1598,65 @@
return NULL;
}
+PyDoc_STRVAR(partition__doc__,
+"S.partition(sep) -> (head, sep, tail)\n\
+\n\
+Searches for the separator sep in S, and returns the part before it,\n\
+the separator itself, and the part after it. If the separator is not\n\
+found, returns S and two empty strings.");
+
+static PyObject *
+string_partition(PyStringObject *self, PyObject *sep_obj)
+{
+ Py_ssize_t len = PyString_GET_SIZE(self), sep_len, pos;
+ const char *str = PyString_AS_STRING(self), *sep;
+ PyObject * out;
+
+ if (PyString_Check(sep_obj)) {
+ sep = PyString_AS_STRING(sep_obj);
+ sep_len = PyString_GET_SIZE(sep_obj);
+ }
+#ifdef Py_USING_UNICODE
+ else if (PyUnicode_Check(sep_obj))
+ return PyUnicode_Partition((PyObject *)self, sep_obj);
+#endif
+ else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
+ return NULL;
+
+ if (sep_len == 0) {
+ PyErr_SetString(PyExc_ValueError, "empty separator");
+ return NULL;
+ }
+
+ out = PyTuple_New(3);
+ if (!out)
+ return NULL;
+
+ pos = fastsearch(str, len, sep, sep_len, FAST_SEARCH);
+ if (pos < 0) {
+ Py_INCREF(self);
+ PyTuple_SET_ITEM(out, 0, (PyObject*) self);
+ Py_INCREF(nullstring);
+ PyTuple_SET_ITEM(out, 1, (PyObject*) nullstring);
+ Py_INCREF(nullstring);
+ PyTuple_SET_ITEM(out, 2, (PyObject*) nullstring);
+ } else {
+ PyObject* obj;
+ PyTuple_SET_ITEM(out, 0, PyString_FromStringAndSize(str, pos));
+ Py_INCREF(sep_obj);
+ PyTuple_SET_ITEM(out, 1, sep_obj);
+ pos += sep_len;
+ obj = PyString_FromStringAndSize(str + pos, len - pos);
+ PyTuple_SET_ITEM(out, 2, obj);
+ if (PyErr_Occurred()) {
+ Py_DECREF(out);
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
static PyObject *
rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
{
@@ -1500,15 +1676,17 @@
if (j > i) {
if (maxsplit-- <= 0)
break;
- SPLIT_INSERT(s, i + 1, j + 1);
+ SPLIT_APPEND(s, i + 1, j + 1);
while (i >= 0 && isspace(Py_CHARMASK(s[i])))
i--;
j = i;
}
}
if (j >= 0) {
- SPLIT_INSERT(s, 0, j + 1);
+ SPLIT_APPEND(s, 0, j + 1);
}
+ if (PyList_Reverse(list) < 0)
+ goto onError;
return list;
onError:
Py_DECREF(list);
@@ -1529,14 +1707,16 @@
if (s[i] == ch) {
if (maxcount-- <= 0)
break;
- SPLIT_INSERT(s, i + 1, j + 1);
+ SPLIT_APPEND(s, i + 1, j + 1);
j = i = i - 1;
} else
i--;
}
if (j >= -1) {
- SPLIT_INSERT(s, 0, j + 1);
+ SPLIT_APPEND(s, 0, j + 1);
}
+ if (PyList_Reverse(list) < 0)
+ goto onError;
return list;
onError:
@@ -1776,6 +1956,17 @@
string_adjust_indices(&i, &last, len);
+#ifdef USE_FAST
+ if (n == 0)
+ return (dir > 0) ? i : last;
+ if (dir > 0) {
+ Py_ssize_t pos = fastsearch(s + i, last - i, sub, n,
+ FAST_SEARCH);
+ if (pos < 0)
+ return pos;
+ return pos + i;
+ }
+#endif
if (dir > 0) {
if (n == 0 && i <= last)
return (long)i;
@@ -2033,57 +2224,68 @@
\n\
Return a copy of the string S converted to lowercase.");
+/* _tolower and _toupper are defined by SUSv2, but they're not ISO C */
+#ifndef _tolower
+#define _tolower tolower
+#endif
+
static PyObject *
string_lower(PyStringObject *self)
{
- char *s = PyString_AS_STRING(self), *s_new;
+ char *s;
Py_ssize_t i, n = PyString_GET_SIZE(self);
PyObject *newobj;
newobj = PyString_FromStringAndSize(NULL, n);
- if (newobj == NULL)
+ if (!newobj)
return NULL;
- s_new = PyString_AsString(newobj);
+
+ s = PyString_AS_STRING(newobj);
+
+ memcpy(s, PyString_AS_STRING(self), n);
+
for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(*s++);
- if (isupper(c)) {
- *s_new = tolower(c);
- } else
- *s_new = c;
- s_new++;
+ int c = Py_CHARMASK(s[i]);
+ if (isupper(c))
+ s[i] = _tolower(c);
}
+
return newobj;
}
-
PyDoc_STRVAR(upper__doc__,
"S.upper() -> string\n\
\n\
Return a copy of the string S converted to uppercase.");
+#ifndef _toupper
+#define _toupper toupper
+#endif
+
static PyObject *
string_upper(PyStringObject *self)
{
- char *s = PyString_AS_STRING(self), *s_new;
+ char *s;
Py_ssize_t i, n = PyString_GET_SIZE(self);
PyObject *newobj;
newobj = PyString_FromStringAndSize(NULL, n);
- if (newobj == NULL)
+ if (!newobj)
return NULL;
- s_new = PyString_AsString(newobj);
+
+ s = PyString_AS_STRING(newobj);
+
+ memcpy(s, PyString_AS_STRING(self), n);
+
for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(*s++);
- if (islower(c)) {
- *s_new = toupper(c);
- } else
- *s_new = c;
- s_new++;
+ int c = Py_CHARMASK(s[i]);
+ if (islower(c))
+ s[i] = _toupper(c);
}
+
return newobj;
}
-
PyDoc_STRVAR(title__doc__,
"S.title() -> string\n\
\n\
@@ -2166,7 +2368,7 @@
static PyObject *
string_count(PyStringObject *self, PyObject *args)
{
- const char *s = PyString_AS_STRING(self), *sub, *t;
+ const char *s = PyString_AS_STRING(self), *sub;
Py_ssize_t len = PyString_GET_SIZE(self), n;
Py_ssize_t i = 0, last = PY_SSIZE_T_MAX;
Py_ssize_t m, r;
@@ -2199,8 +2401,14 @@
if (n == 0)
return PyInt_FromSsize_t(m-i);
+#ifdef USE_FAST
+ r = fastsearch(s + i, last - i, sub, n, FAST_COUNT);
+ if (r < 0)
+ r = 0; /* no match */
+#else
r = 0;
while (i < m) {
+ const char *t
if (!memcmp(s+i, sub, n)) {
r++;
i += n;
@@ -2214,6 +2422,7 @@
break;
i = t - s;
}
+#endif
return PyInt_FromSsize_t(r);
}
@@ -2368,156 +2577,625 @@
}
-/* What follows is used for implementing replace(). Perry Stoll. */
+#define FORWARD 1
+#define REVERSE -1
-/*
- mymemfind
+/* find and count characters and substrings */
- strstr replacement for arbitrary blocks of memory.
+/* Don't call if length < 2 */
+#define Py_STRING_MATCH(target, offset, pattern, length) \
+ (target[offset] == pattern[0] && \
+ target[offset+length-1] == pattern[length-1] && \
+ !memcmp(target+offset+1, pattern+1, length-2) )
+
+#define findchar(target, target_len, c) \
+ ((char *)memchr((const void *)(target), c, target_len))
+
+/* String ops must return a string. */
+/* If the object is subclass of string, create a copy */
+static PyStringObject *
+return_self(PyStringObject *self)
+{
+ if (PyString_CheckExact(self)) {
+ Py_INCREF(self);
+ return self;
+ }
+ return (PyStringObject *)PyString_FromStringAndSize(
+ PyString_AS_STRING(self),
+ PyString_GET_SIZE(self));
+}
- Locates the first occurrence in the memory pointed to by MEM of the
- contents of memory pointed to by PAT. Returns the index into MEM if
- found, or -1 if not found. If len of PAT is greater than length of
- MEM, the function returns -1.
-*/
static Py_ssize_t
-mymemfind(const char *mem, Py_ssize_t len, const char *pat, Py_ssize_t pat_len)
+countchar(char *target, int target_len, char c)
{
- register Py_ssize_t ii;
+ Py_ssize_t count=0;
+ char *start=target;
+ char *end=target+target_len;
- /* pattern can not occur in the last pat_len-1 chars */
- len -= pat_len;
+ while ( (start=findchar(start, end-start, c)) != NULL ) {
+ count++;
+ start += 1;
+ }
- for (ii = 0; ii <= len; ii++) {
- if (mem[ii] == pat[0] && memcmp(&mem[ii], pat, pat_len) == 0) {
- return ii;
- }
+ return count;
+}
+
+static Py_ssize_t
+findstring(char *target, Py_ssize_t target_len,
+ char *pattern, Py_ssize_t pattern_len,
+ Py_ssize_t start,
+ Py_ssize_t end,
+ int direction)
+{
+ if (start < 0) {
+ start += target_len;
+ if (start < 0)
+ start = 0;
+ }
+ if (end > target_len) {
+ end = target_len;
+ } else if (end < 0) {
+ end += target_len;
+ if (end < 0)
+ end = 0;
+ }
+
+ /* zero-length substrings always match at the first attempt */
+ if (pattern_len == 0)
+ return (direction > 0) ? start : end;
+
+ end -= pattern_len;
+
+ if (direction < 0) {
+ for (; end >= start; end--)
+ if (Py_STRING_MATCH(target, end, pattern, pattern_len))
+ return end;
+ } else {
+ for (; start <= end; start++)
+ if (Py_STRING_MATCH(target, start, pattern, pattern_len))
+ return start;
}
return -1;
}
-/*
- mymemcnt
+Py_ssize_t
+countstring(char *target, Py_ssize_t target_len,
+ char *pattern, Py_ssize_t pattern_len,
+ Py_ssize_t start,
+ Py_ssize_t end,
+ int direction)
+{
+ Py_ssize_t count=0;
+
+ if (start < 0) {
+ start += target_len;
+ if (start < 0)
+ start = 0;
+ }
+ if (end > target_len) {
+ end = target_len;
+ } else if (end < 0) {
+ end += target_len;
+ if (end < 0)
+ end = 0;
+ }
+
+ /* zero-length substrings match everywhere */
+ if (pattern_len == 0)
+ return target_len+1;
+
+ end -= pattern_len;
+
+ if (direction < 0) {
+ for (; end >= start; end--)
+ if (Py_STRING_MATCH(target, end, pattern, pattern_len)) {
+ count++;
+ end -= pattern_len-1;
+ }
+ } else {
+ for (; start <= end; start++)
+ if (Py_STRING_MATCH(target, start, pattern, pattern_len)) {
+ count++;
+ start += pattern_len-1;
+ }
+ }
+ return count;
+}
- Return the number of distinct times PAT is found in MEM.
- meaning mem=1111 and pat==11 returns 2.
- mem=11111 and pat==11 also return 2.
- */
-static Py_ssize_t
-mymemcnt(const char *mem, Py_ssize_t len, const char *pat, Py_ssize_t pat_len)
-{
- register Py_ssize_t offset = 0;
- Py_ssize_t nfound = 0;
- while (len >= 0) {
- offset = mymemfind(mem, len, pat, pat_len);
+/* Algorithms for difference cases of string replacement */
+
+/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
+static PyStringObject *
+replace_interleave(PyStringObject *self,
+ PyStringObject *to,
+ Py_ssize_t maxcount)
+{
+ char *self_s, *to_s, *result_s;
+ Py_ssize_t self_len, to_len, result_len;
+ Py_ssize_t count, i, product;
+ PyStringObject *result;
+
+ self_len = PyString_GET_SIZE(self);
+ to_len = PyString_GET_SIZE(to);
+
+ /* 1 at the end plus 1 after every character */
+ count = self_len+1;
+ if (maxcount < count)
+ count = maxcount;
+
+ /* Check for overflow */
+ /* result_len = count * to_len + self_len; */
+ product = count * to_len;
+ if (product / to_len != count) {
+ PyErr_SetString(PyExc_OverflowError,
+ "replace string is too long");
+ return NULL;
+ }
+ result_len = product + self_len;
+ if (result_len < 0) {
+ PyErr_SetString(PyExc_OverflowError,
+ "replace string is too long");
+ return NULL;
+ }
+
+ if (! (result = (PyStringObject *)
+ PyString_FromStringAndSize(NULL, result_len)) )
+ return NULL;
+
+ self_s = PyString_AS_STRING(self);
+ to_s = PyString_AS_STRING(to);
+ to_len = PyString_GET_SIZE(to);
+ result_s = PyString_AS_STRING(result);
+
+ /* TODO: special case single character, which doesn't need memcpy */
+
+ /* Lay the first one down (guaranteed this will occur) */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ count -= 1;
+
+ for (i=0; i<count; i++) {
+ *result_s++ = *self_s++;
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ }
+
+ /* Copy the rest of the original string */
+ memcpy(result_s, self_s, self_len-i);
+
+ return result;
+}
+
+/* Special case for deleting a single character */
+/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
+static PyStringObject *
+replace_delete_single_character(PyStringObject *self,
+ char from_c, Py_ssize_t maxcount)
+{
+ char *self_s, *result_s;
+ char *start, *next, *end;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count;
+ PyStringObject *result;
+
+ self_len = PyString_GET_SIZE(self);
+ self_s = PyString_AS_STRING(self);
+
+ count = countchar(self_s, self_len, from_c);
+ if (count == 0) {
+ return return_self(self);
+ }
+ if (count > maxcount)
+ count = maxcount;
+
+ result_len = self_len - count; /* from_len == 1 */
+ assert(result_len>=0);
+
+ if ( (result = (PyStringObject *)
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)
+ return NULL;
+ result_s = PyString_AS_STRING(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ next = findchar(start, end-start, from_c);
+ if (next == NULL)
+ break;
+ memcpy(result_s, start, next-start);
+ result_s += (next-start);
+ start = next+1;
+ }
+ memcpy(result_s, start, end-start);
+
+ return result;
+}
+
+/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
+
+static PyStringObject *
+replace_delete_substring(PyStringObject *self, PyStringObject *from,
+ Py_ssize_t maxcount) {
+ char *self_s, *from_s, *result_s;
+ char *start, *next, *end;
+ Py_ssize_t self_len, from_len, result_len;
+ Py_ssize_t count, offset;
+ PyStringObject *result;
+
+ self_len = PyString_GET_SIZE(self);
+ self_s = PyString_AS_STRING(self);
+ from_len = PyString_GET_SIZE(from);
+ from_s = PyString_AS_STRING(from);
+
+ count = countstring(self_s, self_len,
+ from_s, from_len,
+ 0, self_len, 1);
+
+ if (count > maxcount)
+ count = maxcount;
+
+ if (count == 0) {
+ /* no matches */
+ return return_self(self);
+ }
+
+ result_len = self_len - (count * from_len);
+ assert (result_len>=0);
+
+ if ( (result = (PyStringObject *)
+ PyString_FromStringAndSize(NULL, result_len)) == NULL )
+ return NULL;
+
+ result_s = PyString_AS_STRING(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ offset = findstring(start, end-start,
+ from_s, from_len,
+ 0, end-start, FORWARD);
if (offset == -1)
break;
- mem += offset + pat_len;
- len -= offset + pat_len;
- nfound++;
+ next = start + offset;
+
+ memcpy(result_s, start, next-start);
+
+ result_s += (next-start);
+ start = next+from_len;
}
- return nfound;
+ memcpy(result_s, start, end-start);
+ return result;
}
-/*
- mymemreplace
+/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
+static PyStringObject *
+replace_single_character_in_place(PyStringObject *self,
+ char from_c, char to_c,
+ Py_ssize_t maxcount)
+{
+ char *self_s, *result_s, *start, *end, *next;
+ Py_ssize_t self_len;
+ PyStringObject *result;
+
+ /* The result string will be the same size */
+ self_s = PyString_AS_STRING(self);
+ self_len = PyString_GET_SIZE(self);
+
+ next = findchar(self_s, self_len, from_c);
+
+ if (next == NULL) {
+ /* No matches; return the original string */
+ return return_self(self);
+ }
+
+ /* Need to make a new string */
+ result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
+ if (result == NULL)
+ return NULL;
+ result_s = PyString_AS_STRING(result);
+ memcpy(result_s, self_s, self_len);
+
+ /* change everything in-place, starting with this one */
+ start = result_s + (next-self_s);
+ *start = to_c;
+ start++;
+ end = result_s + self_len;
+
+ while (--maxcount > 0) {
+ next = findchar(start, end-start, from_c);
+ if (next == NULL)
+ break;
+ *next = to_c;
+ start = next+1;
+ }
+
+ return result;
+}
- Return a string in which all occurrences of PAT in memory STR are
- replaced with SUB.
+/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_substring_in_place(PyStringObject *self,
+ PyStringObject *from,
+ PyStringObject *to,
+ Py_ssize_t maxcount)
+{
+ char *result_s, *start, *end;
+ char *self_s, *from_s, *to_s;
+ Py_ssize_t self_len, from_len, offset;
+ PyStringObject *result;
+
+ /* The result string will be the same size */
+
+ self_s = PyString_AS_STRING(self);
+ self_len = PyString_GET_SIZE(self);
+
+ from_s = PyString_AS_STRING(from);
+ from_len = PyString_GET_SIZE(from);
+ to_s = PyString_AS_STRING(to);
+
+ offset = findstring(self_s, self_len,
+ from_s, from_len,
+ 0, self_len, FORWARD);
+
+ if (offset == -1) {
+ /* No matches; return the original string */
+ return return_self(self);
+ }
+
+ /* Need to make a new string */
+ result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
+ if (result == NULL)
+ return NULL;
+ result_s = PyString_AS_STRING(result);
+ memcpy(result_s, self_s, self_len);
- If length of PAT is less than length of STR or there are no occurrences
- of PAT in STR, then the original string is returned. Otherwise, a new
- string is allocated here and returned.
-
- on return, out_len is:
- the length of output string, or
- -1 if the input string is returned, or
- unchanged if an error occurs (no memory).
-
- return value is:
- the new string allocated locally, or
- NULL if an error occurred.
-*/
-static char *
-mymemreplace(const char *str, Py_ssize_t len, /* input string */
- const char *pat, Py_ssize_t pat_len, /* pattern string to find */
- const char *sub, Py_ssize_t sub_len, /* substitution string */
- Py_ssize_t count, /* number of replacements */
- Py_ssize_t *out_len)
-{
- char *out_s;
- char *new_s;
- Py_ssize_t nfound, offset, new_len;
-
- if (len == 0 || (pat_len == 0 && sub_len == 0) || pat_len > len)
- goto return_same;
-
- /* find length of output string */
- nfound = (pat_len > 0) ? mymemcnt(str, len, pat, pat_len) : len + 1;
- if (count < 0)
- count = PY_SSIZE_T_MAX;
- else if (nfound > count)
- nfound = count;
- if (nfound == 0)
- goto return_same;
-
- new_len = len + nfound*(sub_len - pat_len);
- if (new_len == 0) {
- /* Have to allocate something for the caller to free(). */
- out_s = (char *)PyMem_MALLOC(1);
- if (out_s == NULL)
- return NULL;
- out_s[0] = '\0';
+
+ /* change everything in-place, starting with this one */
+ start = result_s + offset;
+ memcpy(start, to_s, from_len);
+ start += from_len;
+ end = result_s + self_len;
+
+ while ( --maxcount > 0) {
+ offset = findstring(start, end-start,
+ from_s, from_len,
+ 0, end-start, FORWARD);
+ if (offset==-1)
+ break;
+ memcpy(start+offset, to_s, from_len);
+ start += offset+from_len;
}
- else {
- assert(new_len > 0);
- new_s = (char *)PyMem_MALLOC(new_len);
- if (new_s == NULL)
- return NULL;
- out_s = new_s;
+
+ return result;
+}
- if (pat_len > 0) {
- for (; nfound > 0; --nfound) {
- /* find index of next instance of pattern */
- offset = mymemfind(str, len, pat, pat_len);
- if (offset == -1)
- break;
+/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_single_character(PyStringObject *self,
+ char from_c,
+ PyStringObject *to,
+ Py_ssize_t maxcount)
+{
+ char *self_s, *to_s, *result_s;
+ char *start, *next, *end;
+ Py_ssize_t self_len, to_len, result_len;
+ Py_ssize_t count, product;
+ PyStringObject *result;
+
+ self_s = PyString_AS_STRING(self);
+ self_len = PyString_GET_SIZE(self);
+
+ count = countchar(self_s, self_len, from_c);
+ if (count > maxcount)
+ count = maxcount;
+
+ if (count == 0) {
+ /* no matches, return unchanged */
+ return return_self(self);
+ }
+
+ to_s = PyString_AS_STRING(to);
+ to_len = PyString_GET_SIZE(to);
+
+ /* use the difference between current and new, hence the "-1" */
+ /* result_len = self_len + count * (to_len-1) */
+ product = count * (to_len-1);
+ if (product / (to_len-1) != count) {
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+ return NULL;
+ }
+ result_len = self_len + product;
+ if (result_len < 0) {
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+ return NULL;
+ }
+
+ if ( (result = (PyStringObject *)
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)
+ return NULL;
+ result_s = PyString_AS_STRING(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ next = findchar(start, end-start, from_c);
+ if (next == NULL)
+ break;
+
+ if (next == start) {
+ /* replace with the 'to' */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start += 1;
+ } else {
+ /* copy the unchanged old then the 'to' */
+ memcpy(result_s, start, next-start);
+ result_s += (next-start);
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start = next+1;
+ }
+ }
+ /* Copy the remainder of the remaining string */
+ memcpy(result_s, start, end-start);
+
+ return result;
+}
- /* copy non matching part of input string */
- memcpy(new_s, str, offset);
- str += offset + pat_len;
- len -= offset + pat_len;
-
- /* copy substitute into the output string */
- new_s += offset;
- memcpy(new_s, sub, sub_len);
- new_s += sub_len;
- }
- /* copy any remaining values into output string */
- if (len > 0)
- memcpy(new_s, str, len);
+/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
+static PyStringObject *
+replace_substring(PyStringObject *self,
+ PyStringObject *from,
+ PyStringObject *to,
+ Py_ssize_t maxcount) {
+ char *self_s, *from_s, *to_s, *result_s;
+ char *start, *next, *end;
+ Py_ssize_t self_len, from_len, to_len, result_len;
+ Py_ssize_t count, offset, product;
+ PyStringObject *result;
+
+ self_s = PyString_AS_STRING(self);
+ self_len = PyString_GET_SIZE(self);
+ from_s = PyString_AS_STRING(from);
+ from_len = PyString_GET_SIZE(from);
+
+ count = countstring(self_s, self_len,
+ from_s, from_len,
+ 0, self_len, FORWARD);
+ if (count > maxcount)
+ count = maxcount;
+
+ if (count == 0) {
+ /* no matches, return unchanged */
+ return return_self(self);
+ }
+
+ to_s = PyString_AS_STRING(to);
+ to_len = PyString_GET_SIZE(to);
+
+ /* Check for overflow */
+ /* result_len = self_len + count * (to_len-from_len) */
+ product = count * (to_len-from_len);
+ if (product / (to_len-from_len) != count) {
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+ return NULL;
+ }
+ result_len = self_len + product;
+ if (result_len < 0) {
+ PyErr_SetString(PyExc_OverflowError, "replace string is too long");
+ return NULL;
+ }
+
+ if ( (result = (PyStringObject *)
+ PyString_FromStringAndSize(NULL, result_len)) == NULL)
+ return NULL;
+ result_s = PyString_AS_STRING(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ offset = findstring(start, end-start,
+ from_s, from_len,
+ 0, end-start, FORWARD);
+ if (offset == -1)
+ break;
+ next = start+offset;
+ if (next == start) {
+ /* replace with the 'to' */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start += from_len;
+ } else {
+ /* copy the unchanged old then the 'to' */
+ memcpy(result_s, start, next-start);
+ result_s += (next-start);
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start = next+from_len;
}
- else {
- for (;;++str, --len) {
- memcpy(new_s, sub, sub_len);
- new_s += sub_len;
- if (--nfound <= 0) {
- memcpy(new_s, str, len);
- break;
- }
- *new_s++ = *str;
- }
+ }
+ /* Copy the remainder of the remaining string */
+ memcpy(result_s, start, end-start);
+
+ return result;
+}
+
+
+static PyStringObject *
+replace(PyStringObject *self,
+ PyStringObject *from,
+ PyStringObject *to,
+ Py_ssize_t maxcount)
+{
+ Py_ssize_t from_len, to_len;
+
+ if (maxcount < 0) {
+ maxcount = PY_SSIZE_T_MAX;
+ } else if (maxcount == 0 || PyString_GET_SIZE(self) == 0) {
+ /* nothing to do; return the original string */
+ return return_self(self);
+ }
+
+ from_len = PyString_GET_SIZE(from);
+ to_len = PyString_GET_SIZE(to);
+
+ if (maxcount == 0 ||
+ (from_len == 0 && to_len == 0)) {
+ /* nothing to do; return the original string */
+ return return_self(self);
+ }
+
+ /* Handle zero-length special cases */
+
+ if (from_len == 0) {
+ /* insert the 'to' string everywhere. */
+ /* >>> "Python".replace("", ".") */
+ /* '.P.y.t.h.o.n.' */
+ return replace_interleave(self, to, maxcount);
+ }
+
+ /* Except for "".replace("", "A") == "A" there is no way beyond this */
+ /* point for an empty self string to generate a non-empty string */
+ /* Special case so the remaining code always gets a non-empty string */
+ if (PyString_GET_SIZE(self) == 0) {
+ return return_self(self);
+ }
+
+ if (to_len == 0) {
+ /* delete all occurances of 'from' string */
+ if (from_len == 1) {
+ return replace_delete_single_character(
+ self, PyString_AS_STRING(from)[0], maxcount);
+ } else {
+ return replace_delete_substring(self, from, maxcount);
}
}
- *out_len = new_len;
- return out_s;
- return_same:
- *out_len = -1;
- return (char *)str; /* cast away const */
-}
+ /* Handle special case where both strings have the same length */
+
+ if (from_len == to_len) {
+ if (from_len == 1) {
+ return replace_single_character_in_place(
+ self,
+ PyString_AS_STRING(from)[0],
+ PyString_AS_STRING(to)[0],
+ maxcount);
+ } else {
+ return replace_substring_in_place(
+ self, from, to, maxcount);
+ }
+ }
+ /* Otherwise use the more generic algorithms */
+ if (from_len == 1) {
+ return replace_single_character(self, PyString_AS_STRING(from)[0],
+ to, maxcount);
+ } else {
+ /* len('from')>=2, len('to')>=1 */
+ return replace_substring(self, from, to, maxcount);
+ }
+}
PyDoc_STRVAR(replace__doc__,
"S.replace (old, new[, count]) -> string\n\
@@ -2529,66 +3207,42 @@
static PyObject *
string_replace(PyStringObject *self, PyObject *args)
{
- const char *str = PyString_AS_STRING(self), *sub, *repl;
- char *new_s;
- const Py_ssize_t len = PyString_GET_SIZE(self);
- Py_ssize_t sub_len, repl_len, out_len;
Py_ssize_t count = -1;
- PyObject *newobj;
- PyObject *subobj, *replobj;
+ PyObject *from, *to;
+ const char *tmp_s;
+ Py_ssize_t tmp_len;
- if (!PyArg_ParseTuple(args, "OO|n:replace",
- &subobj, &replobj, &count))
+ if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
return NULL;
- if (PyString_Check(subobj)) {
- sub = PyString_AS_STRING(subobj);
- sub_len = PyString_GET_SIZE(subobj);
+ if (PyString_Check(from)) {
+ /* Can this be made a '!check' after the Unicode check? */
}
#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(subobj))
+ if (PyUnicode_Check(from))
return PyUnicode_Replace((PyObject *)self,
- subobj, replobj, count);
+ from, to, count);
#endif
- else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
+ else if (PyObject_AsCharBuffer(from, &tmp_s, &tmp_len))
return NULL;
- if (PyString_Check(replobj)) {
- repl = PyString_AS_STRING(replobj);
- repl_len = PyString_GET_SIZE(replobj);
+ if (PyString_Check(to)) {
+ /* Can this be made a '!check' after the Unicode check? */
}
#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(replobj))
+ else if (PyUnicode_Check(to))
return PyUnicode_Replace((PyObject *)self,
- subobj, replobj, count);
+ from, to, count);
#endif
- else if (PyObject_AsCharBuffer(replobj, &repl, &repl_len))
+ else if (PyObject_AsCharBuffer(to, &tmp_s, &tmp_len))
return NULL;
- new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
- if (new_s == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- if (out_len == -1) {
- if (PyString_CheckExact(self)) {
- /* we're returning another reference to self */
- newobj = (PyObject*)self;
- Py_INCREF(newobj);
- }
- else {
- newobj = PyString_FromStringAndSize(str, len);
- if (newobj == NULL)
- return NULL;
- }
- }
- else {
- newobj = PyString_FromStringAndSize(new_s, out_len);
- PyMem_FREE(new_s);
- }
- return newobj;
+ return (PyObject *)replace((PyStringObject *) self,
+ (PyStringObject *) from,
+ (PyStringObject *) to, count);
}
+/** End DALKE **/
PyDoc_STRVAR(startswith__doc__,
"S.startswith(prefix[, start[, end]]) -> bool\n\
@@ -3312,6 +3966,7 @@
{"count", (PyCFunction)string_count, METH_VARARGS, count__doc__},
{"endswith", (PyCFunction)string_endswith, METH_VARARGS,
endswith__doc__},
+ {"partition", (PyCFunction)string_partition, METH_O, partition__doc__},
{"find", (PyCFunction)string_find, METH_VARARGS, find__doc__},
{"index", (PyCFunction)string_index, METH_VARARGS, index__doc__},
{"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},
Modified: python/branches/blais-bytebuf/Objects/typeobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/typeobject.c (original)
+++ python/branches/blais-bytebuf/Objects/typeobject.c Fri May 26 13:03:30 2006
@@ -4641,10 +4641,10 @@
(void *)PyObject_GenericGetAttr))
res = PyObject_GenericGetAttr(self, name);
else
- res = PyObject_CallFunction(getattribute, "OO", self, name);
+ res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL);
if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
- res = PyObject_CallFunction(getattr, "OO", self, name);
+ res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
}
return res;
}
@@ -4781,7 +4781,7 @@
obj = Py_None;
if (type == NULL)
type = Py_None;
- return PyObject_CallFunction(get, "OOO", self, obj, type);
+ return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);
}
static int
@@ -5728,8 +5728,8 @@
if (su->ob_type != &PySuper_Type)
/* If su is an instance of a (strict) subclass of super,
call its type */
- return PyObject_CallFunction((PyObject *)su->ob_type,
- "OO", su->type, obj);
+ return PyObject_CallFunctionObjArgs((PyObject *)su->ob_type,
+ su->type, obj, NULL);
else {
/* Inline the common case */
PyTypeObject *obj_type = supercheck(su->type, obj);
Modified: python/branches/blais-bytebuf/Objects/unicodeobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/unicodeobject.c (original)
+++ python/branches/blais-bytebuf/Objects/unicodeobject.c Fri May 26 13:03:30 2006
@@ -4,6 +4,9 @@
modified by Marc-Andre Lemburg <mal at lemburg.com> according to the
Unicode Integration Proposal (see file Misc/unicode.txt).
+Major speed upgrades to the method implementations at the Reykjavik
+NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
+
Copyright (c) Corporation for National Research Initiatives.
--------------------------------------------------------------------
@@ -193,6 +196,7 @@
/* Resizing shared object (unicode_empty or single character
objects) in-place is not allowed. Use PyUnicode_Resize()
instead ! */
+
if (unicode == unicode_empty ||
(unicode->length == 1 &&
unicode->str[0] < 256U &&
@@ -202,8 +206,11 @@
return -1;
}
- /* We allocate one more byte to make sure the string is
- Ux0000 terminated -- XXX is this needed ? */
+ /* We allocate one more byte to make sure the string is Ux0000 terminated.
+ The overallocation is also used by fastsearch, which assumes that it's
+ safe to look at str[length] (without makeing any assumptions about what
+ it contains). */
+
oldstr = unicode->str;
PyMem_RESIZE(unicode->str, Py_UNICODE, length + 1);
if (!unicode->str) {
@@ -3859,16 +3866,16 @@
/* --- Helpers ------------------------------------------------------------ */
-#define USE_FAST /* experimental fast search implementation */
-
/* fast search/count implementation, based on a mix between boyer-
moore and horspool, with a few more bells and whistles on the top.
for some more background, see: http://effbot.org/stringlib */
/* note: fastsearch may access s[n], which isn't a problem when using
- Python's ordinary string types. also, the count mode returns -1 if
- there cannot possible be a match in the target string, and 0 if it
- has actually checked for matches. */
+ Python's ordinary string types, but may cause problems if you're
+ using this code in other contexts. also, the count mode returns -1
+ if there cannot possible be a match in the target string, and 0 if
+ it has actually checked for matches, but didn't find any. callers
+ beware! */
#define FAST_COUNT 0
#define FAST_SEARCH 1
@@ -3877,7 +3884,7 @@
fastsearch(Py_UNICODE* s, Py_ssize_t n, Py_UNICODE* p, Py_ssize_t m, int mode)
{
long mask;
- int skip, count = 0;
+ Py_ssize_t skip, count = 0;
Py_ssize_t i, j, mlast, w;
w = n - m;
@@ -3934,10 +3941,8 @@
/* miss: check if next character is part of pattern */
if (!(mask & (1 << (s[i+m] & 0x1F))))
i = i + m;
- else {
+ else
i = i + skip;
- continue;
- }
} else {
/* skip: check if next character is part of pattern */
if (!(mask & (1 << (s[i+m] & 0x1F))))
@@ -3971,23 +3976,13 @@
if (substring->length == 0)
return (end - start + 1);
-#ifdef USE_FAST
count = fastsearch(
PyUnicode_AS_UNICODE(self) + start, end - start,
substring->str, substring->length, FAST_COUNT
);
+
if (count < 0)
count = 0; /* no match */
-#else
- end -= substring->length;
-
- while (start <= end)
- if (Py_UNICODE_MATCH(self, start, substring)) {
- count++;
- start += substring->length;
- } else
- start++;
-#endif
return count;
}
@@ -4038,30 +4033,19 @@
if (substring->length == 0)
return (direction > 0) ? start : end;
-#ifdef USE_FAST
if (direction > 0) {
Py_ssize_t pos = fastsearch(
PyUnicode_AS_UNICODE(self) + start, end - start,
substring->str, substring->length, FAST_SEARCH
);
- if (pos < 0)
- return pos;
- return pos + start;
- }
-#endif
-
- end -= substring->length;
-
- if (direction < 0) {
+ if (pos >= 0)
+ return pos + start;
+ } else {
+ end -= substring->length;
for (; end >= start; end--)
if (Py_UNICODE_MATCH(self, end, substring))
return end;
- } else {
- for (; start <= end; start++)
- if (Py_UNICODE_MATCH(self, start, substring))
- return start;
}
-
return -1;
}
@@ -4862,6 +4846,7 @@
} else {
Py_ssize_t n, i;
+ Py_ssize_t product, new_size, delta;
Py_UNICODE *p;
/* replace strings */
@@ -4870,7 +4855,25 @@
n = maxcount;
if (n == 0)
goto nothing;
- u = _PyUnicode_New(self->length + n * (str2->length - str1->length));
+ /* new_size = self->length + n * (str2->length - str1->length)); */
+ delta = (str2->length - str1->length);
+ if (delta == 0) {
+ new_size = self->length;
+ } else {
+ product = n * (str2->length - str1->length);
+ if ((product / (str2->length - str1->length)) != n) {
+ PyErr_SetString(PyExc_OverflowError,
+ "replace string is too long");
+ return NULL;
+ }
+ new_size = self->length + product;
+ if (new_size < 0) {
+ PyErr_SetString(PyExc_OverflowError,
+ "replace string is too long");
+ return NULL;
+ }
+ }
+ u = _PyUnicode_New(new_size);
if (!u)
return NULL;
i = 0;
@@ -5146,11 +5149,8 @@
PyObject *element)
{
PyUnicodeObject *u, *v;
- int result;
Py_ssize_t size;
-#ifdef USE_FAST
Py_ssize_t pos;
-#endif
/* Coerce the two arguments */
v = (PyUnicodeObject *) PyUnicode_FromObject(element);
@@ -5168,44 +5168,19 @@
size = PyUnicode_GET_SIZE(v);
if (!size) {
- result = 1;
+ pos = 0;
goto done;
}
-#ifdef USE_FAST
pos = fastsearch(
PyUnicode_AS_UNICODE(u), PyUnicode_GET_SIZE(u),
PyUnicode_AS_UNICODE(v), size, FAST_SEARCH
);
- result = (pos != -1);
-#else
- result = 0;
-
- if (size == 1) {
- Py_UNICODE chr = PyUnicode_AS_UNICODE(v)[0];
- Py_UNICODE* ptr = PyUnicode_AS_UNICODE(u);
- Py_UNICODE* end = ptr + PyUnicode_GET_SIZE(u);
- for (; ptr < end; ptr++) {
- if (*ptr == chr) {
- result = 1;
- break;
- }
- }
- } else {
- Py_ssize_t start = 0;
- Py_ssize_t end = PyUnicode_GET_SIZE(u) - size;
- for (; start <= end; start++)
- if (Py_UNICODE_MATCH(u, start, v)) {
- result = 1;
- break;
- }
- }
-#endif
done:
Py_DECREF(u);
Py_DECREF(v);
- return result;
+ return (pos != -1);
}
/* Concat to string or Unicode object giving a new Unicode object. */
@@ -5285,7 +5260,7 @@
if (end < 0)
end = 0;
- result = PyInt_FromLong((long) count(self, start, end, substring));
+ result = PyInt_FromSsize_t(count(self, start, end, substring));
Py_DECREF(substring);
return result;
@@ -6314,6 +6289,79 @@
return PyUnicode_Split((PyObject *)self, substring, maxcount);
}
+PyObject *
+PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
+{
+ PyObject* str_obj;
+ PyObject* sep_obj;
+ Py_UNICODE *str, *sep;
+ Py_ssize_t len, sep_len, pos;
+ PyObject* out;
+
+ str_obj = PyUnicode_FromObject(str_in);
+ if (!str_obj)
+ return NULL;
+ sep_obj = PyUnicode_FromObject(sep_in);
+ if (!sep_obj)
+ goto error;
+
+ str = PyUnicode_AS_UNICODE(str_obj);
+ len = PyUnicode_GET_SIZE(str_obj);
+
+ sep = PyUnicode_AS_UNICODE(sep_obj);
+ sep_len = PyUnicode_GET_SIZE(sep_obj);
+
+ if (sep_len == 0) {
+ PyErr_SetString(PyExc_ValueError, "empty separator");
+ goto error;
+ }
+
+ out = PyTuple_New(3);
+ if (!out)
+ goto error;
+
+ pos = fastsearch(str, len, sep, sep_len, FAST_SEARCH);
+ if (pos < 0) {
+ Py_INCREF(str_obj);
+ PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
+ Py_INCREF(unicode_empty);
+ PyTuple_SET_ITEM(out, 1, (PyObject*) unicode_empty);
+ Py_INCREF(unicode_empty);
+ PyTuple_SET_ITEM(out, 2, (PyObject*) unicode_empty);
+ } else {
+ PyObject* obj;
+ PyTuple_SET_ITEM(out, 0, PyUnicode_FromUnicode(str, pos));
+ Py_INCREF(sep_obj);
+ PyTuple_SET_ITEM(out, 1, sep_obj);
+ obj = PyUnicode_FromUnicode(str + sep_len + pos, len - sep_len - pos);
+ PyTuple_SET_ITEM(out, 2, obj);
+ if (PyErr_Occurred()) {
+ Py_DECREF(out);
+ goto error;
+ }
+ }
+
+ return out;
+
+error:
+ Py_XDECREF(sep_obj);
+ Py_DECREF(str_obj);
+ return NULL;
+}
+
+PyDoc_STRVAR(partition__doc__,
+"S.partition(sep) -> (head, sep, tail)\n\
+\n\
+Searches for the separator sep in S, and returns the part before it,\n\
+the separator itself, and the part after it. If the separator is not\n\
+found, returns S and two empty strings.");
+
+static PyObject*
+unicode_partition(PyUnicodeObject *self, PyObject *separator)
+{
+ return PyUnicode_Partition((PyObject *)self, separator);
+}
+
PyObject *PyUnicode_RSplit(PyObject *s,
PyObject *sep,
Py_ssize_t maxsplit)
@@ -6567,6 +6615,7 @@
{"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__},
{"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__},
{"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__},
+ {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__},
{"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__},
{"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__},
{"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__},
Modified: python/branches/blais-bytebuf/Objects/weakrefobject.c
==============================================================================
--- python/branches/blais-bytebuf/Objects/weakrefobject.c (original)
+++ python/branches/blais-bytebuf/Objects/weakrefobject.c Fri May 26 13:03:30 2006
@@ -851,7 +851,7 @@
static void
handle_callback(PyWeakReference *ref, PyObject *callback)
{
- PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
+ PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
if (cbresult == NULL)
PyErr_WriteUnraisable(callback);
Modified: python/branches/blais-bytebuf/PC/pyconfig.h
==============================================================================
--- python/branches/blais-bytebuf/PC/pyconfig.h (original)
+++ python/branches/blais-bytebuf/PC/pyconfig.h Fri May 26 13:03:30 2006
@@ -162,6 +162,7 @@
#include <float.h>
#define Py_IS_NAN _isnan
#define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X))
+#define Py_IS_FINITE(X) _finite(X)
#endif /* _MSC_VER */
Modified: python/branches/blais-bytebuf/Python/ceval.c
==============================================================================
--- python/branches/blais-bytebuf/Python/ceval.c (original)
+++ python/branches/blais-bytebuf/Python/ceval.c Fri May 26 13:03:30 2006
@@ -4053,7 +4053,7 @@
metaclass = (PyObject *) &PyClass_Type;
Py_INCREF(metaclass);
}
- result = PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
+ result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL);
Py_DECREF(metaclass);
if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
/* A type error here likely means that the user passed
Modified: python/branches/blais-bytebuf/Python/import.c
==============================================================================
--- python/branches/blais-bytebuf/Python/import.c (original)
+++ python/branches/blais-bytebuf/Python/import.c Fri May 26 13:03:30 2006
@@ -1043,7 +1043,7 @@
PyObject *hook = PyList_GetItem(path_hooks, j);
if (hook == NULL)
return NULL;
- importer = PyObject_CallFunction(hook, "O", p);
+ importer = PyObject_CallFunctionObjArgs(hook, p, NULL);
if (importer != NULL)
break;
@@ -2499,8 +2499,8 @@
goto err;
/* Call the _import__ function with the proper argument list */
- r = PyObject_CallFunction(import, "OOOO",
- module_name, globals, globals, silly_list);
+ r = PyObject_CallFunctionObjArgs(import, module_name, globals,
+ globals, silly_list, NULL);
err:
Py_XDECREF(globals);
Modified: python/branches/blais-bytebuf/Python/mystrtoul.c
==============================================================================
--- python/branches/blais-bytebuf/Python/mystrtoul.c (original)
+++ python/branches/blais-bytebuf/Python/mystrtoul.c Fri May 26 13:03:30 2006
@@ -75,34 +75,6 @@
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
-/* char-to-digit conversion for bases 2-36; all non-digits are 37 */
-static int digitlookup[] = {
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 37, 37, 37, 37, 37, 37,
- 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
- 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
-};
-
/*
** strtoul
** This is a general purpose routine for converting
@@ -167,7 +139,7 @@
ovlimit = digitlimit[base];
/* do the conversion until non-digit character encountered */
- while ((c = digitlookup[Py_CHARMASK(*str)]) < base) {
+ while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
if (ovlimit > 0) /* no overflow check required */
result = result * base + c;
else { /* requires overflow check */
@@ -204,7 +176,7 @@
overflowed:
if (ptr) {
/* spool through remaining digit characters */
- while (digitlookup[Py_CHARMASK(*str)] < base)
+ while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
++str;
*ptr = str;
}
Modified: python/branches/blais-bytebuf/Python/pystrtod.c
==============================================================================
--- python/branches/blais-bytebuf/Python/pystrtod.c (original)
+++ python/branches/blais-bytebuf/Python/pystrtod.c Fri May 26 13:03:30 2006
@@ -101,7 +101,7 @@
char *copy, *c;
/* We need to convert the '.' to the locale specific decimal point */
- copy = (char *)malloc(end - nptr + 1 + decimal_point_len);
+ copy = (char *)PyMem_MALLOC(end - nptr + 1 + decimal_point_len);
c = copy;
memcpy(c, nptr, decimal_point_pos - nptr);
@@ -122,7 +122,7 @@
fail_pos = (char *)nptr + (fail_pos - copy);
}
- free(copy);
+ PyMem_FREE(copy);
}
else {
More information about the Python-checkins
mailing list