[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

AltStyle によって変換されたページ (->オリジナル) /