diff options
author | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
---|---|---|
committer | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
commit | 22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch) | |
tree | bffa27765faf54126ad44bcafa89fadecb7a73d7 /contrib/libs/pycxx | |
parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (diff) | |
download | ydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz |
validate canons without yatest_common
Diffstat (limited to 'contrib/libs/pycxx')
47 files changed, 17578 insertions, 0 deletions
diff --git a/contrib/libs/pycxx/COPYRIGHT b/contrib/libs/pycxx/COPYRIGHT new file mode 100644 index 00000000000..6d7be450b0a --- /dev/null +++ b/contrib/libs/pycxx/COPYRIGHT @@ -0,0 +1,56 @@ + + Copyright (c) 1998 - 2007 + The Regents of the University of California + Produced at the Lawrence Livermore National Laboratory + Written by Geoff Furnish, Paul F. Dubois, Barry A. Scott + UCRL-CODE-227018 + All rights reserved. + +This file is part of PyCXX. For details, see http://cxx.sourceforge.net. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the disclaimer below. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the disclaimer (as noted below) in the + documentation and/or materials provided with the distribution. + - Neither the name of the UC/LLNL nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA, +THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Additional BSD Notice + +1. This notice is required to be provided under our contract with the U.S. + Department of Energy (DOE). This work was produced at the University of + California, Lawrence Livermore National Laboratory under Contract No. + W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of California + nor any of their employees, makes any warranty, express or implied, or + assumes any liability or responsibility for the accuracy, completeness, + or usefulness of any information, apparatus, product, or process disclosed, + or represents that its use would not infringe privately-owned rights. + +3. Also, reference herein to any specific commercial products, process, or + services by trade name, trademark, manufacturer or otherwise does not + necessarily constitute or imply its endorsement, recommendation, or + favoring by the United States Government or the University of California. + The views and opinions of authors expressed herein do not necessarily + state or reflect those of the United States Government or the University + of California, and shall not be used for advertising or product endorsement + purposes. + diff --git a/contrib/libs/pycxx/Config.hxx b/contrib/libs/pycxx/Config.hxx new file mode 100755 index 00000000000..54b1ae4a6ef --- /dev/null +++ b/contrib/libs/pycxx/Config.hxx @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if defined( PYCXX_6_2_COMPATIBILITY ) + typedef int PyCxx_ssize_t; +#else + typedef Py_ssize_t PyCxx_ssize_t; +#endif + +#if PY_MAJOR_VERSION == 2 +#include "Python2/Config.hxx" +#else +#include "Python3/Config.hxx" +#endif diff --git a/contrib/libs/pycxx/CxxDebug.hxx b/contrib/libs/pycxx/CxxDebug.hxx new file mode 100644 index 00000000000..abb342966e0 --- /dev/null +++ b/contrib/libs/pycxx/CxxDebug.hxx @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#if PY_MAJOR_VERSION == 2 +#include "Python2/CxxDebug.hxx" +#else +#include "Python3/CxxDebug.hxx" +#endif diff --git a/contrib/libs/pycxx/Exception.hxx b/contrib/libs/pycxx/Exception.hxx new file mode 100644 index 00000000000..25b2195ea4c --- /dev/null +++ b/contrib/libs/pycxx/Exception.hxx @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/Exception.hxx" +#else +#include "Python3/Exception.hxx" +#endif diff --git a/contrib/libs/pycxx/Extensions.hxx b/contrib/libs/pycxx/Extensions.hxx new file mode 100644 index 00000000000..6bd7024c5d3 --- /dev/null +++ b/contrib/libs/pycxx/Extensions.hxx @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/Extensions.hxx" +#else +#include "Python3/Extensions.hxx" +#endif diff --git a/contrib/libs/pycxx/IndirectPythonInterface.cxx b/contrib/libs/pycxx/IndirectPythonInterface.cxx new file mode 100644 index 00000000000..ac029f0c901 --- /dev/null +++ b/contrib/libs/pycxx/IndirectPythonInterface.cxx @@ -0,0 +1,516 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#include "IndirectPythonInterface.hxx" + +namespace Py +{ +bool _CFunction_Check( PyObject *op ) { return op->ob_type == _CFunction_Type(); } +bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); } +bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); } +bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); } +#endif +bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); } +bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); } +bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); } +#endif +bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); } +bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); } +bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); } +bool _TraceBack_Check( PyObject *op ) { return op->ob_type == _TraceBack_Type(); } +bool _Tuple_Check( PyObject *op ) { return op->ob_type == _Tuple_Type(); } +bool _Type_Check( PyObject *op ) { return op->ob_type == _Type_Type(); } +bool _Unicode_Check( PyObject *op ) { return op->ob_type == _Unicode_Type(); } +#if PY_MAJOR_VERSION == 2 +bool _String_Check( PyObject *op ) { return op->ob_type == _String_Type(); } +bool _Int_Check( PyObject *op ) { return op->ob_type == _Int_Type(); } +bool _CObject_Check( PyObject *op ) { return op->ob_type == _CObject_Type(); } +#endif +#if PY_MAJOR_VERSION >= 3 +bool _Bytes_Check( PyObject *op ) { return op->ob_type == _Bytes_Type(); } +#endif + +#if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) + +#if defined(MS_WINDOWS) +#include <windows.h> + + +static HMODULE python_dll; + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + static PyObject *ptr_Exc_##eclass = NULL; + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxx_standard_exceptions.hxx" +#else +#include "Python3/cxx_standard_exceptions.hxx" +#endif + +#undef PYCXX_STANDARD_EXCEPTION + +static PyTypeObject *ptr__CFunction_Type = NULL; +static PyTypeObject *ptr__Complex_Type = NULL; +static PyTypeObject *ptr__Dict_Type = NULL; +static PyTypeObject *ptr__Float_Type = NULL; +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +static PyTypeObject *ptr__Function_Type = NULL; +#endif +static PyTypeObject *ptr__Bool_Type = NULL; +static PyTypeObject *ptr__List_Type = NULL; +static PyTypeObject *ptr__Long_Type = NULL; +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +static PyTypeObject *ptr__Method_Type = NULL; +#endif +static PyTypeObject *ptr__Module_Type = NULL; +static PyTypeObject *ptr__Range_Type = NULL; +static PyTypeObject *ptr__Slice_Type = NULL; +static PyTypeObject *ptr__TraceBack_Type = NULL; +static PyTypeObject *ptr__Tuple_Type = NULL; +static PyTypeObject *ptr__Type_Type = NULL; +static PyTypeObject *ptr__Unicode_Type = NULL; +#if PY_MAJOR_VERSION == 2 +static PyTypeObject *ptr__Int_Type = NULL; +static PyTypeObject *ptr__String_Type = NULL; +static PyTypeObject *ptr__CObject_Type = NULL; +#endif +#if PY_MAJOR_VERSION >= 3 +static PyTypeObject *ptr__Bytes_Type = NULL; +#endif + +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +static int *ptr_Py_DebugFlag = NULL; +static int *ptr_Py_InteractiveFlag = NULL; +static int *ptr_Py_OptimizeFlag = NULL; +static int *ptr_Py_NoSiteFlag = NULL; +static int *ptr_Py_VerboseFlag = NULL; + +static char **ptr__Py_PackageContext = NULL; +#endif + +#ifdef Py_REF_DEBUG +int *ptr_Py_RefTotal; +#endif + + +//-------------------------------------------------------------------------------- +class GetAddressException +{ +public: + GetAddressException( const char *_name ) + : name( _name ) + {} + virtual ~GetAddressException() {} + const char *name; +}; + + +//-------------------------------------------------------------------------------- +static PyObject *GetPyObjectPointer_As_PyObjectPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return *(PyObject **)addr; +} + +static PyObject *GetPyObject_As_PyObjectPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return (PyObject *)addr; +} + +static PyTypeObject *GetPyTypeObjectPointer_As_PyTypeObjectPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return *(PyTypeObject **)addr; +} + +static PyTypeObject *GetPyTypeObject_As_PyTypeObjectPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return (PyTypeObject *)addr; +} + +static int *GetInt_as_IntPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return (int *)addr; +} + +static char **GetCharPointer_as_CharPointerPointer( const char *name ) +{ + FARPROC addr = GetProcAddress( python_dll, name ); + if( addr == NULL ) + throw GetAddressException( name ); + + return (char **)addr; +} + + +#ifdef _DEBUG +static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL"; +#else +static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL"; +#endif + +//-------------------------------------------------------------------------------- +bool InitialisePythonIndirectInterface() +{ + char python_dll_name[sizeof(python_dll_name_format)]; + + _snprintf( python_dll_name, sizeof(python_dll_name_format) / sizeof(char) - 1, python_dll_name_format, PY_MAJOR_VERSION, PY_MINOR_VERSION ); + + python_dll = LoadLibraryA( python_dll_name ); + if( python_dll == NULL ) + return false; + + try + { +#ifdef Py_REF_DEBUG + ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" ); +#endif +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) + ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" ); + ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" ); + ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" ); + ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" ); + ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" ); + ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" ); +#endif + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) + ptr_Exc_#eclass = GetPyTypeObject_As_PyTypeObjectPointer( "PyExc_" #eclass ); + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxx_standard_exceptions.hxx" +#else +#include "Python3/cxx_standard_exceptions.hxx" +#endif + +#undef PYCXX_STANDARD_EXCEPTION + + ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" ); + +#if PY_MAJOR_VERSION == 2 + ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_ZeroStruct" ); +#else + ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_FalseStruct" ); +#endif + ptr__PyTrue = GetPyObject_As_PyObjectPointer( "_Py_TrueStruct" ); + + ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" ); + ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" ); + ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" ); + ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" ); +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) + ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" ); +#endif + ptr__Bool_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" ); + ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" ); + ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" ); +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) + ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" ); +#endif + ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" ); + ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" ); + ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" ); + ptr__TraceBack_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTraceBack_Type" ); + ptr__Tuple_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" ); + ptr__Type_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" ); + ptr__Unicode_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" ); +#if PY_MAJOR_VERSION == 2 + ptr__String_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" ); + ptr__Int_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" ); + ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" ); +#endif +#if PY_MAJOR_VERSION >= 3 + ptr__Bytes_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBytes_Type" ); +#endif + } + catch( GetAddressException &e ) + { + OutputDebugStringA( python_dll_name ); + OutputDebugStringA( " does not contain symbol " ); + OutputDebugStringA( e.name ); + OutputDebugStringA( "\n" ); + + return false; + } + + return true; +} + +// +// Wrap variables as function calls +// +PyObject *_Exc_ArithmeticError() { return ptr__Exc_ArithmeticError; } +PyObject *_Exc_AssertionError() { return ptr__Exc_AssertionError; } +PyObject *_Exc_AttributeError() { return ptr__Exc_AttributeError; } +PyObject *_Exc_EnvironmentError() { return ptr__Exc_EnvironmentError; } +PyObject *_Exc_EOFError() { return ptr__Exc_EOFError; } +PyObject *_Exc_Exception() { return ptr__Exc_Exception; } +PyObject *_Exc_FloatingPointError() { return ptr__Exc_FloatingPointError; } +PyObject *_Exc_ImportError() { return ptr__Exc_ImportError; } +PyObject *_Exc_IndexError() { return ptr__Exc_IndexError; } +PyObject *_Exc_IOError() { return ptr__Exc_IOError; } +PyObject *_Exc_KeyboardInterrupt() { return ptr__Exc_KeyboardInterrupt; } +PyObject *_Exc_KeyError() { return ptr__Exc_KeyError; } +PyObject *_Exc_LookupError() { return ptr__Exc_LookupError; } +PyObject *_Exc_MemoryError() { return ptr__Exc_MemoryError; } +PyObject *_Exc_NameError() { return ptr__Exc_NameError; } +PyObject *_Exc_NotImplementedError() { return ptr__Exc_NotImplementedError; } +PyObject *_Exc_OSError() { return ptr__Exc_OSError; } +PyObject *_Exc_OverflowError() { return ptr__Exc_OverflowError; } +PyObject *_Exc_RuntimeError() { return ptr__Exc_RuntimeError; } +#if PY_MAJOR_VERSION == 2 +PyObject *_Exc_StandardError() { return ptr__Exc_StandardError; } +#endif +PyObject *_Exc_SyntaxError() { return ptr__Exc_SyntaxError; } +PyObject *_Exc_SystemError() { return ptr__Exc_SystemError; } +PyObject *_Exc_SystemExit() { return ptr__Exc_SystemExit; } +PyObject *_Exc_TypeError() { return ptr__Exc_TypeError; } +PyObject *_Exc_ValueError() { return ptr__Exc_ValueError; } +#ifdef MS_WINDOWS +PyObject *_Exc_WindowsError() { return ptr__Exc_WindowsError; } +#endif +PyObject *_Exc_ZeroDivisionError() { return ptr__Exc_ZeroDivisionError; } +PyObject *_Exc_IndentationError() { return ptr__Exc_IndentationError; } +PyObject *_Exc_TabError() { return ptr__Exc_TabError; } +PyObject *_Exc_UnboundLocalError() { return ptr__Exc_UnboundLocalError; } +PyObject *_Exc_UnicodeError() { return ptr__Exc_UnicodeError; } + +// +// wrap items in Object.h +// +PyObject *_None() { return ptr__PyNone; } + +PyObject *_False() { return ptr__PyFalse; } +PyObject *_True() { return ptr__PyTrue; } + +PyTypeObject *_CFunction_Type() { return ptr__CFunction_Type; } +PyTypeObject *_Complex_Type() { return ptr__Complex_Type; } +PyTypeObject *_Dict_Type() { return ptr__Dict_Type; } +PyTypeObject *_Float_Type() { return ptr__Float_Type; } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +PyTypeObject *_Function_Type() { return ptr__Function_Type; } +#endif +PyTypeObject *_Bool_Type() { return ptr__Bool_Type; } +PyTypeObject *_List_Type() { return ptr__List_Type; } +PyTypeObject *_Long_Type() { return ptr__Long_Type; } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +PyTypeObject *_Method_Type() { return ptr__Method_Type; } +#endif +PyTypeObject *_Module_Type() { return ptr__Module_Type; } +PyTypeObject *_Range_Type() { return ptr__Range_Type; } +PyTypeObject *_Slice_Type() { return ptr__Slice_Type; } +PyTypeObject *_TraceBack_Type() { return ptr__TraceBack_Type; } +PyTypeObject *_Tuple_Type() { return ptr__Tuple_Type; } +PyTypeObject *_Type_Type() { return ptr__Type_Type; } +PyTypeObject *_Unicode_Type() { return ptr__Unicode_Type; } +#if PY_MAJOR_VERSION == 2 +PyTypeObject *_String_Type() { return ptr__String_Type; } +PyTypeObject *_Int_Type() { return ptr__Int_Type; } +PyTypeObject *_CObject_Type() { return ptr__CObject_Type; } +#endif +#if PY_MAJOR_VERSION >= 3 +PyTypeObject *_Bytes_Type() { return ptr__Bytes_Type; } +#endif + +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +char *__Py_PackageContext() { return *ptr__Py_PackageContext; } +#endif + + +// +// wrap the Python Flag variables +// +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; } +int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; } +int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; } +int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; } +int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; } +#endif + +#if 0 +#define Py_INCREF(op) ( \ + _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ + ((PyObject*)(op))->ob_refcnt++) + +#define Py_DECREF(op) \ + if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ + --((PyObject*)(op))->ob_refcnt != 0) \ + _Py_CHECK_REFCNT(op) \ + else \ + _Py_Dealloc((PyObject *)(op)) +#endif + +void _XINCREF( PyObject *op ) +{ + // This function must match the contents of Py_XINCREF(op) + if( op == NULL ) + return; + +#ifdef Py_REF_DEBUG + (*ptr_Py_RefTotal)++; +#endif + (op)->ob_refcnt++; + +} + +void _XDECREF( PyObject *op ) +{ + // This function must match the contents of Py_XDECREF(op); + if( op == NULL ) + return; + +#ifdef Py_REF_DEBUG + (*ptr_Py_RefTotal)--; +#endif + + if (--(op)->ob_refcnt == 0) + _Py_Dealloc((PyObject *)(op)); +} + + +#else +#error "Can only delay load under Win32" +#endif + +#else + +//================================================================================ +// +// Map onto Macros +// +//================================================================================ + +// +// Wrap variables as function calls +// +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + PyObject *_Exc_##eclass() { return ::PyExc_##eclass; } + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxx_standard_exceptions.hxx" +#else +#include "Python3/cxx_standard_exceptions.hxx" +#endif + +#undef PYCXX_STANDARD_EXCEPTION + +// +// wrap items in Object.h +// +PyObject *_None() { return &::_Py_NoneStruct; } + +PyObject *_False() { return Py_False; } +PyObject *_True() { return Py_True; } + +PyTypeObject *_CFunction_Type() { return &PyCFunction_Type; } +PyTypeObject *_Complex_Type() { return &PyComplex_Type; } +PyTypeObject *_Dict_Type() { return &PyDict_Type; } +PyTypeObject *_Float_Type() { return &PyFloat_Type; } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +PyTypeObject *_Function_Type() { return &PyFunction_Type; } +#endif +PyTypeObject *_Bool_Type() { return &PyBool_Type; } +PyTypeObject *_List_Type() { return &PyList_Type; } +PyTypeObject *_Long_Type() { return &PyLong_Type; } +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +PyTypeObject *_Method_Type() { return &PyMethod_Type; } +#endif +PyTypeObject *_Module_Type() { return &PyModule_Type; } +PyTypeObject *_Range_Type() { return &PyRange_Type; } +PyTypeObject *_Slice_Type() { return &PySlice_Type; } +PyTypeObject *_TraceBack_Type() { return &PyTraceBack_Type; } +PyTypeObject *_Tuple_Type() { return &PyTuple_Type; } +PyTypeObject *_Type_Type() { return &PyType_Type; } +PyTypeObject *_Unicode_Type() { return &PyUnicode_Type; } +#if PY_MAJOR_VERSION == 2 +PyTypeObject *_String_Type() { return &PyString_Type; } +PyTypeObject *_Int_Type() { return &PyInt_Type; } +PyTypeObject *_CObject_Type() { return &PyCObject_Type; } +#endif +#if PY_MAJOR_VERSION >= 3 +PyTypeObject *_Bytes_Type() { return &PyBytes_Type; } +#endif + +// +// wrap flags +// +#if ( PY_MAJOR_VERSION == 2 ) || !defined( Py_LIMITED_API ) +int &_Py_DebugFlag() { return Py_DebugFlag; } +int &_Py_InteractiveFlag() { return Py_InteractiveFlag; } +int &_Py_OptimizeFlag() { return Py_OptimizeFlag; } +int &_Py_NoSiteFlag() { return Py_NoSiteFlag; } +int &_Py_VerboseFlag() { return Py_VerboseFlag; } +char *__Py_PackageContext() { return _Py_PackageContext; } +#endif +// +// Needed to keep the abstactions for delayload interface +// +void _XINCREF( PyObject *op ) +{ + Py_XINCREF( op ); +} + +void _XDECREF( PyObject *op ) +{ + Py_XDECREF( op ); +} + +#endif +} diff --git a/contrib/libs/pycxx/IndirectPythonInterface.hxx b/contrib/libs/pycxx/IndirectPythonInterface.hxx new file mode 100755 index 00000000000..8a59407d346 --- /dev/null +++ b/contrib/libs/pycxx/IndirectPythonInterface.hxx @@ -0,0 +1,7 @@ +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/IndirectPythonInterface.hxx" +#else +#include "Python3/IndirectPythonInterface.hxx" +#endif diff --git a/contrib/libs/pycxx/Objects.hxx b/contrib/libs/pycxx/Objects.hxx new file mode 100644 index 00000000000..8a7abd6dff5 --- /dev/null +++ b/contrib/libs/pycxx/Objects.hxx @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/Objects.hxx" +#else +#include "Python3/Objects.hxx" +#endif diff --git a/contrib/libs/pycxx/Python2/Config.hxx b/contrib/libs/pycxx/Python2/Config.hxx new file mode 100755 index 00000000000..8e59bd0e9c9 --- /dev/null +++ b/contrib/libs/pycxx/Python2/Config.hxx @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __PyCXX_config_hh__ +#define __PyCXX_config_hh__ + +// +// Microsoft VC++ 6.0 has no traits +// +#if defined( _MSC_VER ) + +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 + +#elif defined( __GNUC__ ) +# if __GNUC__ >= 3 +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 +# else +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 0 +#endif + +// +// Assume all other compilers do +// +#else + +// Macros to deal with deficiencies in compilers +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 +#endif + +#if STANDARD_LIBRARY_HAS_ITERATOR_TRAITS +# define random_access_iterator_parent(itemtype) std::iterator<std::random_access_iterator_tag,itemtype,int> +#else +# define random_access_iterator_parent(itemtype) std::random_access_iterator<itemtype, int> +#endif + +// +// Which C++ standard is in use? +// +#if defined( _MSC_VER ) +# if _MSC_VER <= 1200 +// MSVC++ 6.0 +# define PYCXX_ISO_CPP_LIB 0 +# define STR_STREAM <strstream> +# define TEMPLATE_TYPENAME class +# else +# define PYCXX_ISO_CPP_LIB 1 +# define STR_STREAM <sstream> +# define TEMPLATE_TYPENAME typename +# endif +#elif defined( __GNUC__ ) +# if __GNUC__ >= 3 +# define PYCXX_ISO_CPP_LIB 1 +# define STR_STREAM <sstream> +# define TEMPLATE_TYPENAME typename +# else +# define PYCXX_ISO_CPP_LIB 0 +# define STR_STREAM <strstream> +# define TEMPLATE_TYPENAME class +# endif +#endif + +#if PYCXX_ISO_CPP_LIB +# define STR_STREAM <sstream> +# define OSTRSTREAM ostringstream +# define EXPLICIT_TYPENAME typename +# define EXPLICIT_CLASS class +# define TEMPLATE_TYPENAME typename +#else +# define STR_STREAM <strstream> +# define OSTRSTREAM ostrstream +# define EXPLICIT_TYPENAME +# define EXPLICIT_CLASS +# define TEMPLATE_TYPENAME class +#endif + +// specified for ymake for successful build in sandboxing mode +#if 0 +# include <sstream> +# include <strstream> +#endif + +// before 2.5 Py_ssize_t was missing +#ifndef PY_MAJOR_VERSION +#error not defined PY_MAJOR_VERSION +#endif +#if PY_MAJOR_VERSION < 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5) +typedef int Py_ssize_t; +#endif + +#endif // __PyCXX_config_hh__ diff --git a/contrib/libs/pycxx/Python2/CxxDebug.hxx b/contrib/libs/pycxx/Python2/CxxDebug.hxx new file mode 100755 index 00000000000..b646ffdd9af --- /dev/null +++ b/contrib/libs/pycxx/Python2/CxxDebug.hxx @@ -0,0 +1,17 @@ +// +// CxxDebug.hxx +// +// Copyright (c) 2008 Barry A. Scott +// +#ifndef __CXX_Debug_hxx +#define __CXX_Debug_hxx + +// +// Functions useful when debugging PyCXX +// +#ifdef PYCXX_DEBUG +extern void bpt(); +extern void printRefCount( PyObject *obj ); +#endif + +#endif diff --git a/contrib/libs/pycxx/Python2/Exception.hxx b/contrib/libs/pycxx/Python2/Exception.hxx new file mode 100755 index 00000000000..dd5219cd434 --- /dev/null +++ b/contrib/libs/pycxx/Python2/Exception.hxx @@ -0,0 +1,210 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Exception_h +#define __CXX_Exception_h + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "Config.hxx" +#include "CxxDebug.hxx" +#include "IndirectPythonInterface.hxx" + +#include <string> +#include <iostream> + +// This mimics the Python structure, in order to minimize confusion +namespace Py +{ + class ExtensionExceptionType; + + class Object; + + class BaseException: public std::exception + { + public: + BaseException( ExtensionExceptionType &exception, const std::string &reason ); + BaseException( ExtensionExceptionType &exception, Object &reason ); + BaseException( ExtensionExceptionType &exception, PyObject *reason ); + BaseException( PyObject *exception, Object &reason ); + BaseException( PyObject *exception, PyObject *reason ); + BaseException( PyObject *exception, const std::string &reason ); + explicit BaseException(); + + void clear(); // clear the error + + virtual const char* what() const noexcept; + + // is the exception this specific exception 'exc' + bool matches( ExtensionExceptionType &exc ); + + private: + std::string reasonMessage; + }; + +#if defined( PYCXX_6_2_COMPATIBILITY ) + class Exception : public BaseException + { + public: + Exception( ExtensionExceptionType &exception, const std::string &reason ) + : BaseException( exception, reason ) + {} + + Exception( ExtensionExceptionType &exception, Object &reason ) + : BaseException( exception, reason ) + {} + + Exception( ExtensionExceptionType &exception, PyObject *reason ) + : BaseException( exception, reason ) + {} + + Exception( PyObject *exception, Object &reason ) + : BaseException ( exception, reason ) + {} + + Exception( PyObject *exception, PyObject *reason ) + : BaseException ( exception, reason ) + {} + + Exception( PyObject *exception, const std::string &reason ) + : BaseException( exception, reason ) + {} + + explicit Exception() + : BaseException() + {} + }; +#endif + + // for user defined exceptions to be made know to pycxx + typedef void (*throw_exception_func_t)( PyObject* exc ); + void addPythonException( ExtensionExceptionType &py_exc_type, throw_exception_func_t throw_func ); + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + class eclass : public bclass \ + { \ + public: \ + eclass( const std::string &reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( const char *reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + { } \ + eclass( PyObject *exception, const std::string &reason ) \ + : bclass( exception, reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *exception, const char *reason ) \ + : bclass( exception, reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *exception, PyObject *reason ) \ + : bclass( exception, reason ) \ + { } \ + eclass( PyObject *exception, Object &reason ) \ + : bclass( exception, reason ) \ + { } \ + eclass() : bclass() {} \ + static void throwFunc(const std::string &reason) { throw eclass(reason); } \ + static void throwFuncObj(PyObject *exception) { throw eclass(exception); } \ + static PyObject *exceptionType() { return _Exc_##eclass(); } \ + ~eclass() {} \ + private: \ + std::string reason; \ + }; + +#include "cxx_standard_exceptions.hxx" + +#undef PYCXX_STANDARD_EXCEPTION + +#define PYCXX_USER_EXCEPTION_STR_ARG( uclass ) \ +class uclass : public Py::BaseException \ +{ \ +public: \ + uclass( const std::string &reason ) \ + : Py::BaseException( m_error, reason ) \ + { } \ + ~uclass() {} \ + static void init( Py::ExtensionModuleBase &module ) \ + { \ + m_error.init( module, #uclass ); \ + Py::addPythonException( m_error, throwFunc ); \ + Py::Dict d( module.moduleDictionary() ); \ + d[#uclass] = m_error; \ + } \ +private: \ + uclass() : Py::BaseException() {} \ + static void throwFunc() \ + { \ + throw uclass(); \ + } \ + static Py::ExtensionExceptionType m_error; \ +}; \ +Py::ExtensionExceptionType uclass::m_error; + +#define PYCXX_USER_EXCEPTION_NO_ARG( uclass ) \ +class uclass : public Py::BaseException \ +{ \ +public: \ + uclass() \ + : Py::BaseException() \ + { } \ + ~uclass() {} \ + static void init( Py::ExtensionModuleBase &module ) \ + { \ + m_error.init( module, #uclass ); \ + Py::addPythonException( m_error, throwFunc ); \ + Py::Dict d( module.moduleDictionary() ); \ + d[#uclass] = m_error; \ + } \ +private: \ + static void throwFunc() \ + { \ + throw uclass(); \ + } \ + static Py::ExtensionExceptionType m_error; \ +}; \ +Py::ExtensionExceptionType uclass::m_error; + +}// Py + +#endif diff --git a/contrib/libs/pycxx/Python2/ExtensionModule.hxx b/contrib/libs/pycxx/Python2/ExtensionModule.hxx new file mode 100755 index 00000000000..5f59dc075ff --- /dev/null +++ b/contrib/libs/pycxx/Python2/ExtensionModule.hxx @@ -0,0 +1,207 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionModule__h +#define __CXX_ExtensionModule__h + +namespace Py +{ + class ExtensionModuleBase + { + public: + ExtensionModuleBase( const char *name ); + virtual ~ExtensionModuleBase(); + + Module module( void ) const; // only valid after initialize() has been called + Dict moduleDictionary( void ) const; // only valid after initialize() has been called + + virtual Object invoke_method_noargs( void *method_def ) = 0; + virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0; + virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0; + + const std::string &name() const; + const std::string &fullName() const; + + // what is returned from PyInit_<module> function + Object moduleObject( void ) const; + + protected: + // Initialize the module + void initialize( const char *module_doc ); + + const std::string m_module_name; + const std::string m_full_module_name; + MethodTable m_method_table; + PyObject *m_module; + + private: + // + // prevent the compiler generating these unwanted functions + // + ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented + void operator=( const ExtensionModuleBase & ); //unimplemented + }; + + // Note: Python calls noargs as varargs buts args==NULL + extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ); + extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ); + extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ); + + extern "C" void do_not_dealloc( void * ); + + template<TEMPLATE_TYPENAME T> + class ExtensionModule : public ExtensionModuleBase + { + public: + ExtensionModule( const char *name ) + : ExtensionModuleBase( name ) + {} + virtual ~ExtensionModule() + {} + + protected: + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + typedef std::map<std::string, MethodDefExt<T> *> method_map_t; + + static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc ); + } + + static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc ); + } + + static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc ); + } + + void initialize( const char *module_doc="" ) + { + ExtensionModuleBase::initialize( module_doc ); + Dict dict( moduleDictionary() ); + + // + // put each of the methods into the modules dictionary + // so that we get called back at the function in T. + // + method_map_t &mm = methods(); + EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin(); + EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); + for ( ; i != i_end; ++i ) + { + MethodDefExt<T> *method_def = (*i).second; + + static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc ); + + Tuple args( 2 ); + args[0] = Object( self, true ); + args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true ); + + assert( m_module != NULL ); + PyObject *func = PyCFunction_NewEx + ( + &method_def->ext_meth_def, + new_reference_to( args ), + m_module + ); + + method_def->py_method = Object( func, true ); + + dict[ (*i).first ] = method_def->py_method; + } + } + + protected: // Tom Malcolmson reports that derived classes need access to these + static method_map_t &methods( void ) + { + static method_map_t *map_of_methods = NULL; + if( map_of_methods == NULL ) + map_of_methods = new method_map_t; + + return *map_of_methods; + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_noargs( void *method_def ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_noargs_function)(); + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_varargs( void *method_def, const Tuple &args ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_varargs_function)( args ); + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_keyword_function)( args, keywords ); + } + + private: + // + // prevent the compiler generating these unwanted functions + // + ExtensionModule( const ExtensionModule<T> & ); //unimplemented + void operator=( const ExtensionModule<T> & ); //unimplemented + }; +} // Namespace Py + + +// End of __CXX_ExtensionModule__h +#endif diff --git a/contrib/libs/pycxx/Python2/ExtensionOldType.hxx b/contrib/libs/pycxx/Python2/ExtensionOldType.hxx new file mode 100755 index 00000000000..570e31f6128 --- /dev/null +++ b/contrib/libs/pycxx/Python2/ExtensionOldType.hxx @@ -0,0 +1,397 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionOldType__h +#define __CXX_ExtensionOldType__h + +namespace Py +{ + template<TEMPLATE_TYPENAME T> class PythonExtension + : public PythonExtensionBase + { + public: + static PyTypeObject *type_object() + { + return behaviors().type_object(); + } + + static bool check( PyObject *p ) + { + // is p like me? + return p->ob_type == type_object(); + } + + static bool check( const Object &ob ) + { + return check( ob.ptr() ); + } + + // + // every object needs getattr implemented + // to support methods + // + virtual Object getattr( const char *name ) + { + return getattr_methods( name ); + } + + PyObject *selfPtr() + { + return this; + } + + Object self() + { + return asObject( this ); + } + + protected: + explicit PythonExtension() + : PythonExtensionBase() + { + PyObject_Init( this, type_object() ); + + // every object must support getattr + behaviors().supportGetattr(); + } + + virtual ~PythonExtension() + {} + + static PythonType &behaviors() + { + static PythonType* p; + if( p == NULL ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + const char *default_name =( typeid( T ) ).name(); +#else + const char *default_name = "unknown"; +#endif + p = new PythonType( sizeof( T ), 0, default_name ); + p->set_tp_dealloc( extension_object_deallocator ); + } + + return *p; + } + + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + typedef std::map<std::string, MethodDefExt<T> *> method_map_t; + + // support the default attributes, __name__, __doc__ and methods + virtual Object getattr_default( const char *_name ) + { + std::string name( _name ); + + if( name == "__name__" && type_object()->tp_name != NULL ) + { + return Py::String( type_object()->tp_name ); + } + + if( name == "__doc__" && type_object()->tp_doc != NULL ) + { + return Py::String( type_object()->tp_doc ); + } + +// trying to fake out being a class for help() +// else if( name == "__bases__" ) +// { +// return Py::Tuple( 0 ); +// } +// else if( name == "__module__" ) +// { +// return Py::Nothing(); +// } +// else if( name == "__dict__" ) +// { +// return Py::Dict(); +// } + + return getattr_methods( _name ); + } + + // turn a name into function object + virtual Object getattr_methods( const char *_name ) + { + std::string name( _name ); + + method_map_t &mm = methods(); + + // see if name exists and get entry with method + EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.find( name ); + if( i == mm.end() ) + { + if( name == "__methods__" ) + { + List methods; + + i = mm.begin(); + EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); + + for( ; i != i_end; ++i ) + methods.append( String( (*i).first ) ); + + return methods; + } + + throw AttributeError( name ); + } + + MethodDefExt<T> *method_def = i->second; + + Tuple self( 2 ); + + self[0] = Object( this ); + self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true ); + + PyObject *func = PyCFunction_NewEx( &method_def->ext_meth_def, self.ptr(), NULL ); + + return Object(func, true); + } + + // check that all methods added are unique + static void check_unique_method_name( const char *name ) + { + method_map_t &mm = methods(); + EXPLICIT_TYPENAME method_map_t::const_iterator i; + i = mm.find( name ); + if( i != mm.end() ) + throw AttributeError( name ); + } + + static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc ); + } + + static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc ); + } + + static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc ); + } + + private: + static method_map_t &methods( void ) + { + static method_map_t *map_of_methods = NULL; + if( map_of_methods == NULL ) + map_of_methods = new method_map_t; + + return *map_of_methods; + } + + // Note: Python calls noargs as varargs buts args==NULL + static PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); + Object result; + + // Adding try & catch in case of STL debug-mode exceptions. + #ifdef _STLP_DEBUG + try + { + result = (self->*meth_def->ext_noargs_function)(); + } + catch( std::__stl_debug_exception ) + { + // throw cxx::RuntimeError( sErrMsg ); + throw RuntimeError( "Error message not set yet." ); + } + #else + result = (self->*meth_def->ext_noargs_function)(); + #endif // _STLP_DEBUG + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); + Tuple args( _args ); + + Object result; + + // Adding try & catch in case of STL debug-mode exceptions. + #ifdef _STLP_DEBUG + try + { + result = (self->*meth_def->ext_varargs_function)( args ); + } + catch( std::__stl_debug_exception ) + { + throw RuntimeError( "Error message not set yet." ); + } + #else + result = (self->*meth_def->ext_varargs_function)( args ); + #endif // _STLP_DEBUG + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); + + Tuple args( _args ); + + // _keywords may be NULL so be careful about the way the dict is created + Dict keywords; + if( _keywords != NULL ) + keywords = Dict( _keywords ); + + Object result( ( self->*meth_def->ext_keyword_function )( args, keywords ) ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static void extension_object_deallocator( PyObject* t ) + { + delete (T *)( t ); + } + + // + // prevent the compiler generating these unwanted functions + // + explicit PythonExtension( const PythonExtension<T> &other ); + void operator=( const PythonExtension<T> &rhs ); + }; + + // + // ExtensionObject<T> is an Object that will accept only T's. + // + template<TEMPLATE_TYPENAME T> + class ExtensionObject: public Object + { + public: + + explicit ExtensionObject( PyObject *pyob ) + : Object( pyob ) + { + validate(); + } + + ExtensionObject( const ExtensionObject<T> &other ) + : Object( *other ) + { + validate(); + } + + ExtensionObject( const Object &other ) + : Object( *other ) + { + validate(); + } + + ExtensionObject &operator=( const Object &rhs ) + { + return( *this = *rhs ); + } + + ExtensionObject &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return( pyob && T::check( pyob ) ); + } + + // + // Obtain a pointer to the PythonExtension object + // + T *extensionObject( void ) + { + return static_cast<T *>( ptr() ); + } + }; +} // Namespace Py + +// End of __CXX_ExtensionOldType__h +#endif diff --git a/contrib/libs/pycxx/Python2/ExtensionType.hxx b/contrib/libs/pycxx/Python2/ExtensionType.hxx new file mode 100755 index 00000000000..7145bd0833d --- /dev/null +++ b/contrib/libs/pycxx/Python2/ExtensionType.hxx @@ -0,0 +1,418 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionClass__h +#define __CXX_ExtensionClass__h + +#define PYCXX_NOARGS_METHOD_NAME( NAME ) _callNoArgsMethod__##NAME +#define PYCXX_VARARGS_METHOD_NAME( NAME ) _callVarArgsMethod__##NAME +#define PYCXX_KEYWORDS_METHOD_NAME( NAME ) _callKeywordsMethod__##NAME + +#define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Object r( (self->NAME)() ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } +#define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Tuple a( _a ); \ + Py::Object r( (self->NAME)( a ) ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } +#define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Tuple a( _a ); \ + Py::Dict k; \ + if( _k != NULL ) \ + k = _k; \ + Py::Object r( (self->NAME)( a, k ) ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } + +// need to support METH_STATIC and METH_CLASS + +#define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs ) +#define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs ) +#define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs ) + +namespace Py +{ + extern PythonExtensionBase *getPythonExtensionBase( PyObject *self ); + + struct PythonClassInstance + { + PyObject_HEAD + PythonExtensionBase *m_pycxx_object; + }; + + class ExtensionClassMethodsTable + { + public: + ExtensionClassMethodsTable() + : m_methods_table( new PyMethodDef[ METHOD_TABLE_SIZE_INCREMENT ] ) + , m_methods_used( 0 ) + , m_methods_size( METHOD_TABLE_SIZE_INCREMENT ) + { + // add the sentinel marking the table end + PyMethodDef *p = &m_methods_table[ 0 ]; + + p->ml_name = NULL; + p->ml_meth = NULL; + p->ml_flags = 0; + p->ml_doc = NULL; + } + + ~ExtensionClassMethodsTable() + { + delete[] m_methods_table; + } + + // check that all methods added are unique + void check_unique_method_name( const char *_name ) + { + std::string name( _name ); + for( int i=0; i<m_methods_used; i++ ) + { + if( name == m_methods_table[i].ml_name ) + { + throw AttributeError( name ); + } + } + } + PyMethodDef *add_method( const char *name, PyCFunction function, int flags, const char *doc ) + { + check_unique_method_name( name ); + + // see if there is enough space for one more method + if( m_methods_used == (m_methods_size-1) ) + { + PyMethodDef *old_mt = m_methods_table; + m_methods_size += METHOD_TABLE_SIZE_INCREMENT; + PyMethodDef *new_mt = new PyMethodDef[ m_methods_size ]; + for( int i=0; i<m_methods_used; i++ ) + { + new_mt[ i ] = old_mt[ i ]; + } + delete[] old_mt; + m_methods_table = new_mt; + } + + // add method into the table + PyMethodDef *p = &m_methods_table[ m_methods_used ]; + p->ml_name = const_cast<char *>( name ); + p->ml_meth = function; + p->ml_flags = flags; + p->ml_doc = const_cast<char *>( doc ); + + m_methods_used++; + p++; + + // add the sentinel marking the table end + p->ml_name = NULL; + p->ml_meth = NULL; + p->ml_flags = 0; + p->ml_doc = NULL; + + return m_methods_table; + } + + private: + enum {METHOD_TABLE_SIZE_INCREMENT = 1}; + PyMethodDef *m_methods_table; + int m_methods_used; + int m_methods_size; + }; + + template<TEMPLATE_TYPENAME T> class PythonClass + : public PythonExtensionBase + { + protected: + explicit PythonClass( PythonClassInstance *self, Tuple &/*args*/, Dict &/*kwds*/ ) + : PythonExtensionBase() + , m_class_instance( self ) + { + } + + virtual ~PythonClass() + {} + + static ExtensionClassMethodsTable &methodTable() + { + static ExtensionClassMethodsTable *method_table; + if( method_table == NULL ) + method_table = new ExtensionClassMethodsTable; + return *method_table; + } + + static void add_method( const char *name, PyCFunction function, int flags, const char *doc=NULL ) + { + behaviors().set_methods( methodTable().add_method( name, function, flags, doc ) ); + } + + static PythonType &behaviors() + { + static PythonType *p; + if( p == NULL ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + const char *default_name = (typeid( T )).name(); +#else + const char *default_name = "unknown"; +#endif + p = new PythonType( sizeof( PythonClassInstance ), 0, default_name ); + p->set_tp_new( extension_object_new ); + p->set_tp_init( extension_object_init ); + p->set_tp_dealloc( extension_object_deallocator ); + // we are a class + p->supportClass(); + + // always support get and set attr + p->supportGetattro(); + p->supportSetattro(); + } + + return *p; + } + + static PyObject *extension_object_new( PyTypeObject *subtype, PyObject * /*args*/, PyObject * /*kwds*/ ) + { +#ifdef PYCXX_DEBUG + std::cout << "extension_object_new()" << std::endl; +#endif + PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( subtype->tp_alloc( subtype, 0 ) ); + if( o == NULL ) + return NULL; + + o->m_pycxx_object = NULL; + + PyObject *self = reinterpret_cast<PyObject *>( o ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_new() => self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << std::endl; +#endif + return self; + } + + static int extension_object_init( PyObject *_self, PyObject *args_, PyObject *kwds_ ) + { + try + { + Py::Tuple args( args_ ); + Py::Dict kwds; + if( kwds_ != NULL ) + kwds = kwds_; + + PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << " )" << std::endl; + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + + if( self->m_pycxx_object == NULL ) + { + self->m_pycxx_object = new T( self, args, kwds ); +#ifdef PYCXX_DEBUG + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + } + else + { +#ifdef PYCXX_DEBUG + std::cout << " reinit - self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + self->m_pycxx_object->reinit( args, kwds ); + } + } + catch( BaseException & ) + { + return -1; + } + return 0; + } + + static void extension_object_deallocator( PyObject *_self ) + { + PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << " )" << std::endl; + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + delete self->m_pycxx_object; + _self->ob_type->tp_free( _self ); + } + + public: + static PyTypeObject *type_object() + { + return behaviors().type_object(); + } + + static Object type() + { + return Object( reinterpret_cast<PyObject *>( behaviors().type_object() ) ); + } + + static bool check( PyObject *p ) + { + // is p a me or a derived me + switch( PyObject_IsInstance( p, reinterpret_cast<PyObject *>( type_object() ) ) ) + { + default: + case -1: + throw Exception(); + case 0: + return false; + case 1: + return true; + } + } + + static bool check( const Object &ob ) + { + return check( ob.ptr() ); + } + + virtual PyObject *selfPtr() + { + return reinterpret_cast<PyObject *>( m_class_instance ); + } + + virtual Object self() + { + return Object( reinterpret_cast<PyObject *>( m_class_instance ) ); + } + + protected: + private: + PythonClassInstance *m_class_instance; + + private: + // + // prevent the compiler generating these unwanted functions + // + explicit PythonClass( const PythonClass<T> &other ); + void operator=( const PythonClass<T> &rhs ); + }; + + // + // ExtensionObject<T> is an Object that will accept only T's. + // + template<TEMPLATE_TYPENAME T> + class PythonClassObject: public Object + { + public: + + explicit PythonClassObject( PyObject *pyob ) + : Object( pyob ) + { + validate(); + } + + PythonClassObject( const PythonClassObject<T> &other ) + : Object( *other ) + { + validate(); + } + + PythonClassObject( const Object &other ) + : Object( *other ) + { + validate(); + } + + PythonClassObject &operator=( const Object &rhs ) + { + *this = *rhs; + return *this; + } + + PythonClassObject &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return( pyob && T::check( pyob ) ); + } + + // + // Obtain a pointer to the PythonExtension object + // + T *getCxxObject( void ) + { + return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) ); + } + }; +} // Namespace Py + +// End of __CXX_ExtensionClass__h +#endif diff --git a/contrib/libs/pycxx/Python2/ExtensionTypeBase.hxx b/contrib/libs/pycxx/Python2/ExtensionTypeBase.hxx new file mode 100755 index 00000000000..237ae786feb --- /dev/null +++ b/contrib/libs/pycxx/Python2/ExtensionTypeBase.hxx @@ -0,0 +1,181 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionTypeBase__h +#define __CXX_ExtensionTypeBase__h + +namespace Py +{ + // Class PythonExtension is what you inherit from to create + // a new Python extension type. You give your class itself + // as the template paramter. + + // There are two ways that extension objects can get destroyed. + // 1. Their reference count goes to zero + // 2. Someone does an explicit delete on a pointer. + // In(1) the problem is to get the destructor called + // We register a special deallocator in the Python type object + // (see behaviors()) to do this. + // In(2) there is no problem, the dtor gets called. + + // PythonExtension does not use the usual Python heap allocator, + // instead using new/delete. We do the setting of the type object + // and reference count, usually done by PyObject_New, in the + // base class ctor. + + // This special deallocator does a delete on the pointer. + + class PythonExtensionBase : public PyObject + { + public: + PythonExtensionBase(); + virtual ~PythonExtensionBase(); + + public: + // object + virtual void reinit( Tuple &args, Dict &kwds ); + + // object basics + virtual int print( FILE *, int ); + virtual Object getattr( const char * ); + virtual int setattr( const char *, const Object & ); + virtual Object getattro( const String & ); + Object genericGetAttro( const String & ); + virtual int setattro( const String &, const Object & ); + int genericSetAttro( const String &, const Object & ); + virtual int compare( const Object & ); + virtual Object rich_compare( const Object &, int ); + virtual Object repr(); + virtual Object str(); + virtual long hash(); + virtual Object call( const Object &, const Object & ); + virtual Object iter(); + virtual PyObject *iternext(); + + // Sequence methods + virtual PyCxx_ssize_t sequence_length(); + virtual Object sequence_concat( const Object & ); + virtual Object sequence_repeat( Py_ssize_t ); + virtual Object sequence_item( Py_ssize_t ); + virtual Object sequence_slice( Py_ssize_t, Py_ssize_t ); + + virtual int sequence_ass_item( Py_ssize_t, const Object & ); + virtual int sequence_ass_slice( Py_ssize_t, Py_ssize_t, const Object & ); + + virtual Object sequence_inplace_concat( const Object & ); + virtual Object sequence_inplace_repeat( Py_ssize_t ); + + virtual int sequence_contains( const Object & ); + + // Mapping + virtual PyCxx_ssize_t mapping_length(); + virtual Object mapping_subscript( const Object & ); + virtual int mapping_ass_subscript( const Object &, const Object & ); + + // Number + virtual int number_nonzero(); + virtual Object number_negative(); + virtual Object number_positive(); + virtual Object number_absolute(); + virtual Object number_invert(); + virtual Object number_int(); + virtual Object number_float(); + virtual Object number_long(); + virtual Object number_oct(); + virtual Object number_hex(); + virtual Object number_add( const Object & ); + virtual Object number_subtract( const Object & ); + virtual Object number_multiply( const Object & ); + virtual Object number_divide( const Object & ); + virtual Object number_remainder( const Object & ); + virtual Object number_divmod( const Object & ); + virtual Object number_lshift( const Object & ); + virtual Object number_rshift( const Object & ); + virtual Object number_and( const Object & ); + virtual Object number_xor( const Object & ); + virtual Object number_or( const Object & ); + virtual Object number_power( const Object &, const Object & ); + + // Buffer + virtual Py_ssize_t buffer_getreadbuffer( Py_ssize_t, void** ); + virtual Py_ssize_t buffer_getwritebuffer( Py_ssize_t, void** ); + virtual Py_ssize_t buffer_getsegcount( Py_ssize_t* ); + + public: + // helper functions to call function fn_name with 0 to 9 args + Object callOnSelf( const std::string &fn_name ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8, const Object &arg9 ); + + public: + virtual PyObject *selfPtr() = 0; + virtual Object self() = 0; + + private: + void missing_method( void ); + static PyObject *method_call_handler( PyObject *self, PyObject *args ); + }; + +} // Namespace Py + +// End of __CXX_ExtensionTypeBase__h +#endif diff --git a/contrib/libs/pycxx/Python2/Extensions.hxx b/contrib/libs/pycxx/Python2/Extensions.hxx new file mode 100755 index 00000000000..42516eb1c64 --- /dev/null +++ b/contrib/libs/pycxx/Python2/Extensions.hxx @@ -0,0 +1,189 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Extensions__h +#define __CXX_Extensions__h + + +#ifdef _MSC_VER +// disable warning C4786: symbol greater than 255 character, +// okay to ignore +#pragma warning( disable: 4786 ) +#endif + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "Config.hxx" +#include "CxxDebug.hxx" +#include "Objects.hxx" + +extern "C" { extern PyObject py_object_initializer; } + +#include <vector> +#include <map> + +// ---------------------------------------------------------------------- + +namespace Py +{ + class ExtensionModuleBase; + + // Make an Exception Type for use in raising custom exceptions + class ExtensionExceptionType : public Object + { + public: + ExtensionExceptionType(); + virtual ~ExtensionExceptionType(); + + // call init to create the type + void init( ExtensionModuleBase &module, const std::string &name, ExtensionExceptionType &parent ); + void init( ExtensionModuleBase &module, const std::string &name ); + }; + + class MethodTable + { + public: + MethodTable(); + virtual ~MethodTable(); + + void add( const char *method_name, PyCFunction f, const char *doc="", int flag=1 ); + PyMethodDef *table(); + + protected: + std::vector<PyMethodDef> t; // accumulator of PyMethodDef's + PyMethodDef *mt; // Actual method table produced when full + + static PyMethodDef method( const char* method_name, PyCFunction f, int flags=1, const char* doc="" ); + + private: + // + // prevent the compiler generating these unwanted functions + // + MethodTable( const MethodTable &m ); //unimplemented + void operator=( const MethodTable &m ); //unimplemented + + }; // end class MethodTable + + // Note: Python calls noargs as varargs buts args==NULL + extern "C" typedef PyObject *(*method_noargs_call_handler_t)( PyObject *_self, PyObject * ); + extern "C" typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args ); + extern "C" typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict ); + + template<class T> + class MethodDefExt + { + public: + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + + // NOARGS + MethodDefExt + ( + const char *_name, + method_noargs_function_t _function, + method_noargs_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_NOARGS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = _function; + ext_varargs_function = NULL; + ext_keyword_function = NULL; + } + + // VARARGS + MethodDefExt + ( + const char *_name, + method_varargs_function_t _function, + method_varargs_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_VARARGS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = NULL; + ext_varargs_function = _function; + ext_keyword_function = NULL; + } + + // VARARGS + KEYWORD + MethodDefExt + ( + const char *_name, + method_keyword_function_t _function, + method_keyword_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = NULL; + ext_varargs_function = NULL; + ext_keyword_function = _function; + } + + ~MethodDefExt() + {} + + PyMethodDef ext_meth_def; + method_noargs_function_t ext_noargs_function; + method_varargs_function_t ext_varargs_function; + method_keyword_function_t ext_keyword_function; + Object py_method; + }; +} // Namespace Py + +#include "ExtensionModule.hxx" +#include "PythonType.hxx" +#include "ExtensionTypeBase.hxx" +#include "ExtensionOldType.hxx" +#include "ExtensionType.hxx" + +// End of CXX_Extensions.h +#endif diff --git a/contrib/libs/pycxx/Python2/IndirectPythonInterface.hxx b/contrib/libs/pycxx/Python2/IndirectPythonInterface.hxx new file mode 100755 index 00000000000..b15bdde7bb8 --- /dev/null +++ b/contrib/libs/pycxx/Python2/IndirectPythonInterface.hxx @@ -0,0 +1,159 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ +#define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ + +#include "../WrapPython.h" + +namespace Py +{ +bool InitialisePythonIndirectInterface(); + +// +// Wrap Exception variables as function calls +// +PyObject * _Exc_BaseException(); + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + PyObject * _Exc_##eclass(); + +#include "cxx_standard_exceptions.hxx" +#undef PYCXX_STANDARD_EXCEPTION + +// +// Wrap Object variables as function calls +// +PyObject * _None(); + +PyObject * _False(); +PyObject * _True(); + +// +// Wrap Type variables as function calls +// +PyTypeObject * _List_Type(); +bool _List_Check( PyObject *o ); + +PyTypeObject * _Buffer_Type(); +bool _Buffer_Check( PyObject *op ); + +PyTypeObject * _Class_Type(); +bool _Class_Check( PyObject *op ); + +PyTypeObject * _Instance_Type(); +bool _Instance_Check( PyObject *op ); + +PyTypeObject * _Method_Type(); +bool _Method_Check( PyObject *op ); + +PyTypeObject * _CObject_Type(); +bool _CObject_Check( PyObject *op ); + +PyTypeObject * _Complex_Type(); +bool _Complex_Check( PyObject *op ); + +PyTypeObject * _Dict_Type(); +bool _Dict_Check( PyObject *op ); + +PyTypeObject * _File_Type(); +bool _File_Check( PyObject *op ); + +PyTypeObject * _Float_Type(); +bool _Float_Check( PyObject *op ); + +PyTypeObject * _Frame_Type(); +bool _Frame_Check( PyObject *op ); + +PyTypeObject * _Function_Type(); +bool _Function_Check( PyObject *op ); + +PyTypeObject * _Bool_Type(); +bool _Boolean_Check( PyObject *op ); + +PyTypeObject * _Int_Type(); +bool _Int_Check( PyObject *op ); + +PyTypeObject * _List_Type(); +bool _List_Check( PyObject *op ); + +PyTypeObject * _Long_Type(); +bool _Long_Check( PyObject *op ); + +PyTypeObject * _CFunction_Type(); +bool _CFunction_Check( PyObject *op ); + +PyTypeObject * _Module_Type(); +bool _Module_Check( PyObject *op ); + +PyTypeObject * _Type_Type(); +bool _Type_Check( PyObject *op ); + +PyTypeObject * _Range_Type(); +bool _Range_Check( PyObject *op ); + +PyTypeObject * _Slice_Type(); +bool _Slice_Check( PyObject *op ); + +PyTypeObject * _String_Type(); +bool _String_Check( PyObject *op ); + +PyTypeObject * _TraceBack_Type(); +bool _TraceBack_Check( PyObject *v ); + +PyTypeObject * _Tuple_Type(); +bool _Tuple_Check( PyObject *op ); + +#if PY_MAJOR_VERSION >= 2 +PyTypeObject * _Unicode_Type(); +bool _Unicode_Check( PyObject *op ); +#endif + +int &_Py_DebugFlag(); +int &_Py_InteractiveFlag(); +int &_Py_OptimizeFlag(); +int &_Py_NoSiteFlag(); +int &_Py_TabcheckFlag(); +int &_Py_VerboseFlag(); + +void _XINCREF( PyObject *op ); +void _XDECREF( PyObject *op ); + +char *__Py_PackageContext(); +} + +#endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ diff --git a/contrib/libs/pycxx/Python2/Objects.hxx b/contrib/libs/pycxx/Python2/Objects.hxx new file mode 100755 index 00000000000..25b61a3c8e4 --- /dev/null +++ b/contrib/libs/pycxx/Python2/Objects.hxx @@ -0,0 +1,3629 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Objects__h +#define __CXX_Objects__h + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "../Config.hxx" +#include "../Exception.hxx" + +#include <iostream> +#include STR_STREAM +#include <string> +#include <iterator> +#include <utility> +#include <typeinfo> +#include <algorithm> + + +namespace Py +{ + void ifPyErrorThrowCxxException(); + + typedef PyCxx_ssize_t sequence_index_type; // type of an index into a sequence + + // Forward declarations + class Object; + class Type; + template<TEMPLATE_TYPENAME T> class SeqBase; + class String; + class List; + template<TEMPLATE_TYPENAME T> class MapBase; + class Tuple; + class Dict; + + // new_reference_to also overloaded below on Object + inline PyObject* new_reference_to(PyObject* p) + { + Py::_XINCREF(p); + return p; + } + + // returning Null() from an extension method triggers a + // Python exception + inline PyObject* Null() + { + return (static_cast<PyObject*>(0)); + } + + //===========================================================================// + // class Object + // The purpose of this class is to serve as the most general kind of + // Python object, for the purpose of writing C++ extensions in Python + // Objects hold a PyObject* which they own. This pointer is always a + // valid pointer to a Python object. In children we must maintain this behavior. + // + // Instructions on how to make your own class MyType descended from Object: + // (0) Pick a base class, either Object or perhaps SeqBase<T> or MapBase<T>. + // This example assumes Object. + + // (1) Write a routine int MyType_Check (PyObject *) modeled after PyInt_Check, + // PyFloat_Check, etc. + + // (2) Add method accepts: + // virtual bool accepts (PyObject *pyob) const { + // return pyob && MyType_Check (pyob); + // } + + // (3) Include the following constructor and copy constructor + // + /* + explicit MyType (PyObject *pyob): Object(pyob) { + validate(); + } + + MyType(const Object& other): Object(other.ptr()) { + validate(); + } + */ + + // Alernate version for the constructor to allow for construction from owned pointers: + /* + explicit MyType (PyObject *pyob) + : Object(pyob) { + validate(); + } + */ + + // You may wish to add other constructors; see the classes below for examples. + // Each constructor must use "set" to set the pointer + // and end by validating the pointer you have created. + + // (4) Each class needs at least these two assignment operators: + /* + MyType& operator= (const Object& rhs) { + return (*this = *rhs); + } + + Mytype& operator= (PyObject* rhsp) { + if(ptr() == rhsp) return *this; + set(rhsp); + return *this; + } + */ + // Note on accepts: constructors call the base class + // version of a virtual when calling the base class constructor, + // so the test has to be done explicitly in a descendent. + + // If you are inheriting from PythonExtension<T> to define an object + // note that it contains PythonExtension<T>::check + // which you can use in accepts when writing a wrapper class. + // See Demo/range.h and Demo/range.cxx for an example. + + class Object + { + private: + // the pointer to the Python object + // Only Object sets this directly. + // The default constructor for Object sets it to Py_None and + // child classes must use "set" to set it + // + PyObject* p; + + protected: + + void set (PyObject* pyob, bool owned = false) + { + release(); + p = pyob; + if (!owned) + { + Py::_XINCREF (p); + } + validate(); + } + + void release () + { + Py::_XDECREF (p); + p = 0; + } + + void validate(); + + public: + // Constructor acquires new ownership of pointer unless explicitly told not to. + explicit Object (PyObject* pyob=Py::_None(), bool owned = false) + : p(pyob) + { + if(!owned) + { + Py::_XINCREF (p); + } + validate(); + } + + // Copy constructor acquires new ownership of pointer + Object (const Object& ob) + : p(ob.p) + { + Py::_XINCREF (p); + validate(); + } + + // Assignment acquires new ownership of pointer + Object& operator= (const Object& rhs) + { + set(rhs.p); + return *this; + } + + Object& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + + // Destructor + virtual ~Object () + { + release (); + } + + // Loaning the pointer to others, retain ownership + PyObject* operator* () const + { + return p; + } + + // Explicit reference_counting changes + void increment_reference_count() + { + Py::_XINCREF(p); + } + + void decrement_reference_count() + { + // not allowed to commit suicide, however + if(reference_count() == 1) + throw RuntimeError("Object::decrement_reference_count error."); + Py::_XDECREF(p); + } + + // Would like to call this pointer() but messes up STL in SeqBase<T> + PyObject* ptr () const + { + return p; + } + + // + // Queries + // + + // Can pyob be used in this object's constructor? + virtual bool accepts (PyObject *) const + { + // allow any object or NULL + return true; + } + + Py_ssize_t reference_count () const + { // the reference count + return p ? p->ob_refcnt : 0; + } + + Type type () const; // the type object associated with this one + + String str () const; // the str() representation + + std::string as_string() const; + + String repr () const; // the repr () representation + + List dir () const; // the dir() list + + bool hasAttr (const std::string& s) const + { + return PyObject_HasAttrString (p, const_cast<char*>(s.c_str())) ? true: false; + } + + Object getAttr (const std::string& s) const + { + return Object (PyObject_GetAttrString (p, const_cast<char*>(s.c_str())), true); + } + + Object callMemberFunction( const std::string& function_name ) const; + Object callMemberFunction( const std::string& function_name, const Tuple &args ) const; + Object callMemberFunction( const std::string& function_name, const Tuple &args, const Dict &kw ) const; + + Object getItem (const Object& key) const + { + return Object (PyObject_GetItem(p, *key), true); + } + + long hashValue () const + { + return PyObject_Hash (p); + } + + // convert to bool + bool as_bool() const + { + return PyObject_IsTrue( ptr() ) != 0; + } + + bool is(PyObject *pother) const + { // identity test + return p == pother; + } + + bool is(const Object& other) const + { // identity test + return p == other.p; + } + + bool isNull() const + { + return p == NULL; + } + + bool isNone() const + { + return p == _None(); + } + + bool isCallable () const + { + return PyCallable_Check (p) != 0; + } + + bool isInstance () const + { + return PyInstance_Check (p) != 0; + } + + bool isDict () const + { + return Py::_Dict_Check (p); + } + + bool isList () const + { + return Py::_List_Check (p); + } + + bool isMapping () const + { + return PyMapping_Check (p) != 0; + } + + bool isNumeric () const + { + return PyNumber_Check (p) != 0; + } + + bool isSequence () const + { + return PySequence_Check (p) != 0; + } + + bool isTrue () const + { + return PyObject_IsTrue (p) != 0; + } + + bool isType (const Type& t) const; + + bool isTuple() const + { + return Py::_Tuple_Check(p); + } + + bool isString() const + { + return Py::_String_Check(p) || Py::_Unicode_Check(p); + } + + bool isUnicode() const + { + return Py::_Unicode_Check( p ); + } + + bool isBoolean() const + { + return Py::_Boolean_Check( p ); + } + + // Commands + void setAttr (const std::string& s, const Object& value) + { + if(PyObject_SetAttrString (p, const_cast<char*>(s.c_str()), *value) == -1) + ifPyErrorThrowCxxException(); + } + + void delAttr (const std::string& s) + { + if(PyObject_DelAttrString (p, const_cast<char*>(s.c_str())) == -1) + ifPyErrorThrowCxxException(); + } + + // PyObject_SetItem is too weird to be using from C++ + // so it is intentionally omitted. + + void delItem (const Object& key) + { + if(PyObject_DelItem(p, *key) == -1) + ifPyErrorThrowCxxException(); + } + + // Equality and comparison use PyObject_RichCompareBool + + bool operator==(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_EQ); + ifPyErrorThrowCxxException(); + return k != 0; + } + + bool operator!=(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_NE); + ifPyErrorThrowCxxException(); + return k != 0; + } + + bool operator>=(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_GE); + ifPyErrorThrowCxxException(); + return k != 0; + } + + bool operator<=(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_LE); + ifPyErrorThrowCxxException(); + return k != 0; + } + + bool operator<(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_LT); + ifPyErrorThrowCxxException(); + return k != 0; + } + + bool operator>(const Object& o2) const + { + int k = PyObject_RichCompareBool (p, *o2, Py_GT); + ifPyErrorThrowCxxException(); + return k != 0; + } + }; + // End of class Object + inline PyObject* new_reference_to(const Object& g) + { + PyObject* p = g.ptr(); + Py::_XINCREF(p); + return p; + } + + // Nothing() is what an extension method returns if + // there is no other return value. + inline Object Nothing() + { + return Object(Py::_None()); + } + + // Python special None value + inline Object None() + { + return Object(Py::_None()); + } + + // Python special Boolean values + inline Object False() + { + return Object(Py::_False()); + } + + inline Object True() + { + return Object(Py::_True()); + } + + // TMM: 31May'01 - Added the #ifndef so I can exlude iostreams. +#ifndef CXX_NO_IOSTREAMS + std::ostream& operator<< (std::ostream& os, const Object& ob); +#endif + + // Class Type + class Type: public Object + { + public: + explicit Type (PyObject* pyob, bool owned = false): Object(pyob, owned) + { + validate(); + } + + Type (const Object& ob): Object(*ob) + { + validate(); + } + + Type(const Type& t): Object(t) + { + validate(); + } + + Type& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Type& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Type_Check (pyob); + } + }; + + + // + // Convert an owned Python pointer into a CXX Object + // + inline Object asObject (PyObject *p) + { + return Object(p, true); + } + + // =============================================== + // class boolean + class Boolean: public Object + { + public: + // Constructor + Boolean (PyObject *pyob, bool owned = false) + : Object (pyob, owned) + { + validate(); + } + + Boolean (const Boolean& ob): Object(*ob) + { + validate(); + } + + // create from bool + Boolean (bool v=false) + { + set(PyBool_FromLong(v ? 1 : 0), true); + validate(); + } + + explicit Boolean (const Object& ob) + : Object( *ob ) + { + validate(); + } + + // Assignment increases reference count on pointer + + Boolean& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Boolean& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && PyObject_IsTrue(pyob) != -1; + } + + // convert to long + operator bool() const + { + return PyObject_IsTrue (ptr()) != 0; + } + + Boolean& operator= (bool v) + { + set (PyBool_FromLong (v ? 1 : 0), true); + return *this; + } + }; + + // =============================================== + // class Int + class Int: public Object + { + public: + // Constructor + Int (PyObject *pyob, bool owned = false): Object (pyob, owned) + { + validate(); + } + + Int (const Int& ob): Object(*ob) + { + validate(); + } + + // create from long + Int (long v = 0L): Object(PyInt_FromLong(v), true) + { + validate(); + } + + // create from int + Int (int v) + { + long w = v; + set(PyInt_FromLong(w), true); + validate(); + } + + // create from bool + Int (bool v) + { + long w = v ? 1 : 0; + set(PyInt_FromLong(w), true); + validate(); + } + + explicit Int (const Object& ob) + { + set(PyNumber_Int(*ob), true); + validate(); + } + + // Assignment acquires new ownership of pointer + + Int& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Int& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (PyNumber_Int(rhsp), true); + return *this; + } + + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Int_Check (pyob); + } + + // convert to long + operator long() const + { + return PyInt_AsLong (ptr()); + } + +#ifdef HAVE_LONG_LONG + // convert to long long + PY_LONG_LONG asLongLong() const + { + return PyLong_AsLongLong (ptr()); + } + // convert to unsigned long long + unsigned PY_LONG_LONG asUnsignedLongLong() const + { + return PyLong_AsUnsignedLongLong (ptr()); + } +#endif + + // assign from an int + Int& operator= (int v) + { + set (PyInt_FromLong (long(v)), true); + return *this; + } + + // assign from long + Int& operator= (long v) + { + set (PyInt_FromLong (v), true); + return *this; + } + +#ifdef HAVE_LONG_LONG + // assign from long long + Int& operator= (PY_LONG_LONG v) + { + set (PyLong_FromLongLong (v), true); + return *this; + } + // assign from unsigned long long + Int& operator= (unsigned PY_LONG_LONG v) + { + set (PyLong_FromUnsignedLongLong (v), true); + return *this; + } +#endif + }; + + // =============================================== + // class Long + class Long: public Object + { + public: + // Constructor + explicit Long (PyObject *pyob, bool owned = false) + : Object (pyob, owned) + { + validate(); + } + + Long (const Long& ob) + : Object(ob.ptr()) + { + validate(); + } + + // try to create from any object + explicit Long (const Object& ob) + : Object(PyNumber_Long(*ob), true) + { + validate(); + } + + // create from long + explicit Long (long v = 0L) + : Object(PyLong_FromLong(v), true) + { + validate(); + } + + // create from unsigned long + explicit Long (unsigned long v) + : Object(PyLong_FromUnsignedLong(v), true) + { + validate(); + } + + // create from int + explicit Long (int v) + : Object(PyLong_FromLong(static_cast<long>(v)), true) + { + validate(); + } + +#ifdef HAVE_LONG_LONG + // create from long long + explicit Long( PY_LONG_LONG v ) + : Object( PyLong_FromLongLong( v ), true ) + { + validate(); + } + + // create from unsigned long long + explicit Long( unsigned PY_LONG_LONG v ) + : Object( PyLong_FromUnsignedLongLong( v ), true ) + { + validate(); + } +#endif + + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Long_Check (pyob); + } + + // Assignment acquires new ownership of pointer + Long& operator= (const Object& rhs) + { + return *this = *rhs; + } + + Long& operator= (PyObject* rhsp) + { + if(ptr() != rhsp) + set (PyNumber_Long(rhsp), true); + return *this; + } + + // assign from an int + Long& operator= (int v) + { + set(PyLong_FromLong (long(v)), true); + return *this; + } + + // assign from long + Long& operator= (long v) + { + set(PyLong_FromLong (v), true); + return *this; + } + + // assign from unsigned long + Long& operator= (unsigned long v) + { + set(PyLong_FromUnsignedLong (v), true); + return *this; + } + +#ifdef HAVE_LONG_LONG + Long &operator=( PY_LONG_LONG v ) + { + set( PyLong_FromLongLong( v ), true ); + return *this; + } + + Long &operator=( unsigned PY_LONG_LONG v ) + { + set( PyLong_FromUnsignedLongLong( v ), true ); + return *this; + } +#endif + + // convert to long + long as_long() const + { + return PyLong_AsLong( ptr() ); + } + + operator long() const + { + return as_long(); + } + + operator int() const + { + return static_cast<int>( as_long() ); + } + + // convert to unsigned + long as_unsigned_long() const + { + return PyLong_AsUnsignedLong( ptr() ); + } + + // convert to unsigned + operator unsigned long() const + { + return as_unsigned_long(); + } + + double as_double() const + { + return PyLong_AsDouble( ptr() ); + } + + operator double() const + { + return as_double(); + } + +#ifdef HAVE_LONG_LONG + PY_LONG_LONG as_long_long() const + { + return PyLong_AsLongLong( ptr() ); + } + + operator PY_LONG_LONG() const + { + return as_long_long(); + } + + unsigned PY_LONG_LONG as_unsigned_long_long() const + { + return PyLong_AsUnsignedLongLong( ptr() ); + } + + operator unsigned PY_LONG_LONG() const + { + return as_unsigned_long_long(); + } +#endif + + // prefix ++ + Long operator++() + { + set( PyNumber_Add( ptr(), *Long( 1 ) ) ); + return *this; + } + + // postfix ++ + Long operator++( int ) + { + Long a = *this; + set( PyNumber_Add( ptr(), *Long( 1 ) ) ); + return a; + } + + // prefix -- + Long operator--() + { + set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); + return *this; + } + + // postfix -- + Long operator--( int ) + { + Long a = *this; + set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); + return a; + } + }; + +#ifdef HAVE_LONG_LONG + // =============================================== + // class LongLong + class LongLong: public Object + { + public: + // Constructor + explicit LongLong (PyObject *pyob, bool owned = false): Object (pyob, owned) + { + validate(); + } + + LongLong (const LongLong& ob): Object(ob.ptr()) + { + validate(); + } + // create from long long + explicit LongLong (PY_LONG_LONG v = 0L) + : Object(PyLong_FromLongLong(v), true) + { + validate(); + } + // create from unsigned long long + explicit LongLong (unsigned PY_LONG_LONG v) + : Object(PyLong_FromUnsignedLongLong(v), true) + { + validate(); + } + // create from long + explicit LongLong (long v) + : Object(PyLong_FromLongLong(v), true) + { + validate(); + } + // create from unsigned long + explicit LongLong (unsigned long v) + : Object(PyLong_FromUnsignedLongLong(v), true) + { + validate(); + } + // create from int + explicit LongLong (int v) + : Object(PyLong_FromLongLong(static_cast<PY_LONG_LONG>(v)), true) + { + validate(); + } + + // try to create from any object + LongLong (const Object& ob) + : Object(PyNumber_Long(*ob), true) + { + validate(); + } + + // Assignment acquires new ownership of pointer + + LongLong& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + LongLong& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (PyNumber_Long(rhsp), true); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Long_Check (pyob); + } + // convert to long long + operator PY_LONG_LONG() const + { + return PyLong_AsLongLong (ptr()); + } + // convert to unsigned long + operator unsigned PY_LONG_LONG() const + { + return PyLong_AsUnsignedLongLong (ptr()); + } + // convert to long + operator long() const + { + return PyLong_AsLong (ptr()); + } + // convert to unsigned + operator unsigned long() const + { + return PyLong_AsUnsignedLong (ptr()); + } + operator double() const + { + return PyLong_AsDouble (ptr()); + } + // assign from an int + LongLong& operator= (int v) + { + set(PyLong_FromLongLong (long(v)), true); + return *this; + } + // assign from long long + LongLong& operator= (PY_LONG_LONG v) + { + set(PyLong_FromLongLong (v), true); + return *this; + } + // assign from unsigned long long + LongLong& operator= (unsigned PY_LONG_LONG v) + { + set(PyLong_FromUnsignedLongLong (v), true); + return *this; + } + // assign from long + LongLong& operator= (long v) + { + set(PyLong_FromLongLong (v), true); + return *this; + } + // assign from unsigned long + LongLong& operator= (unsigned long v) + { + set(PyLong_FromUnsignedLongLong (v), true); + return *this; + } + }; +#endif + + // =============================================== + // class Float + // + class Float: public Object + { + public: + // Constructor + explicit Float (PyObject *pyob, bool owned = false): Object(pyob, owned) + { + validate(); + } + + Float (const Float& f): Object(f) + { + validate(); + } + + // make from double + explicit Float (double v=0.0) + : Object(PyFloat_FromDouble (v), true) + { + validate(); + } + + // try to make from any object + Float (const Object& ob) + : Object(PyNumber_Float(*ob), true) + { + validate(); + } + + Float& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Float& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (PyNumber_Float(rhsp), true); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Float_Check (pyob); + } + // convert to double + operator double () const + { + return PyFloat_AsDouble (ptr()); + } + // assign from a double + Float& operator= (double v) + { + set(PyFloat_FromDouble (v), true); + return *this; + } + // assign from an int + Float& operator= (int v) + { + set(PyFloat_FromDouble (double(v)), true); + return *this; + } + // assign from long + Float& operator= (long v) + { + set(PyFloat_FromDouble (double(v)), true); + return *this; + } + // assign from an Int + Float& operator= (const Int& iob) + { + set(PyFloat_FromDouble (double(long(iob))), true); + return *this; + } + }; + + // =============================================== + // class Complex + class Complex: public Object + { + public: + // Constructor + explicit Complex (PyObject *pyob, bool owned = false): Object(pyob, owned) + { + validate(); + } + + Complex (const Complex& f): Object(f) + { + validate(); + } + + // make from double + explicit Complex (double v=0.0, double w=0.0) + :Object(PyComplex_FromDoubles (v, w), true) + { + validate(); + } + + Complex& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Complex& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Complex_Check (pyob); + } + // convert to Py_complex + operator Py_complex () const + { + return PyComplex_AsCComplex (ptr()); + } + // assign from a Py_complex + Complex& operator= (const Py_complex& v) + { + set(PyComplex_FromCComplex (v), true); + return *this; + } + // assign from a double + Complex& operator= (double v) + { + set(PyComplex_FromDoubles (v, 0.0), true); + return *this; + } + // assign from an int + Complex& operator= (int v) + { + set(PyComplex_FromDoubles (double(v), 0.0), true); + return *this; + } + // assign from long + Complex& operator= (long v) + { + set(PyComplex_FromDoubles (double(v), 0.0), true); + return *this; + } + // assign from an Int + Complex& operator= (const Int& iob) + { + set(PyComplex_FromDoubles (double(long(iob)), 0.0), true); + return *this; + } + + double real() const + { + return PyComplex_RealAsDouble(ptr()); + } + + double imag() const + { + return PyComplex_ImagAsDouble(ptr()); + } + }; + // Sequences + // Sequences are here represented as sequences of items of type T. + // The base class SeqBase<T> represents that. + // In basic Python T is always "Object". + + // seqref<T> is what you get if you get elements from a non-const SeqBase<T>. + // Note: seqref<T> could probably be a nested class in SeqBase<T> but that might stress + // some compilers needlessly. Simlarly for mapref later. + + // While this class is not intended for enduser use, it needs some public + // constructors for the benefit of the STL. + + // See Scott Meyer's More Essential C++ for a description of proxies. + // This application is even more complicated. We are doing an unusual thing + // in having a double proxy. If we want the STL to work + // properly we have to compromise by storing the rvalue inside. The + // entire Object API is repeated so that things like s[i].isList() will + // work properly. + + // Still, once in a while a weird compiler message may occur using expressions like x[i] + // Changing them to Object(x[i]) helps the compiler to understand that the + // conversion of a seqref to an Object is wanted. + + template<TEMPLATE_TYPENAME T> + class seqref + { + protected: + SeqBase<T>& s; // the sequence + sequence_index_type offset; // item number + T the_item; // lvalue + public: + + seqref (SeqBase<T>& seq, sequence_index_type j) + : s(seq), offset(j), the_item (s.getItem(j)) + {} + + seqref (const seqref<T>& range) + : s(range.s), offset(range.offset), the_item(range.the_item) + {} + + // TMM: added this seqref ctor for use with STL algorithms + seqref (Object& obj) + : s(dynamic_cast< SeqBase<T>&>(obj)) + , offset( 0 ) + , the_item(s.getItem(offset)) + {} + ~seqref() + {} + + operator T() const + { // rvalue + return the_item; + } + + seqref<T>& operator=(const seqref<T>& rhs) + { //used as lvalue + the_item = rhs.the_item; + s.setItem(offset, the_item); + return *this; + } + + seqref<T>& operator=(const T& ob) + { // used as lvalue + the_item = ob; + s.setItem(offset, ob); + return *this; + } + + // forward everything else to the item + PyObject* ptr () const + { + return the_item.ptr(); + } + + int reference_count () const + { // the reference count + return the_item.reference_count(); + } + + Type type () const + { + return the_item.type(); + } + + String str () const; + + String repr () const; + + bool hasAttr (const std::string& attr_name) const + { + return the_item.hasAttr(attr_name); + } + + Object getAttr (const std::string& attr_name) const + { + return the_item.getAttr(attr_name); + } + + Object getItem (const Object& key) const + { + return the_item.getItem(key); + } + + long hashValue () const + { + return the_item.hashValue(); + } + + bool isCallable () const + { + return the_item.isCallable(); + } + + bool isInstance () const + { + return the_item.isInstance(); + } + + bool isDict () const + { + return the_item.isDict(); + } + + bool isList () const + { + return the_item.isList(); + } + + bool isMapping () const + { + return the_item.isMapping(); + } + + bool isNumeric () const + { + return the_item.isNumeric(); + } + + bool isSequence () const + { + return the_item.isSequence(); + } + + bool isTrue () const + { + return the_item.isTrue(); + } + + bool isType (const Type& t) const + { + return the_item.isType (t); + } + + bool isTuple() const + { + return the_item.isTuple(); + } + + bool isString() const + { + return the_item.isString(); + } + // Commands + void setAttr (const std::string& attr_name, const Object& value) + { + the_item.setAttr(attr_name, value); + } + + void delAttr (const std::string& attr_name) + { + the_item.delAttr(attr_name); + } + + void delItem (const Object& key) + { + the_item.delItem(key); + } + + bool operator==(const Object& o2) const + { + return the_item == o2; + } + + bool operator!=(const Object& o2) const + { + return the_item != o2; + } + + bool operator>=(const Object& o2) const + { + return the_item >= o2; + } + + bool operator<=(const Object& o2) const + { + return the_item <= o2; + } + + bool operator<(const Object& o2) const + { + return the_item < o2; + } + + bool operator>(const Object& o2) const + { + return the_item > o2; + } + }; // end of seqref + + + // class SeqBase<T> + // ...the base class for all sequence types + + template<TEMPLATE_TYPENAME T> + class SeqBase: public Object + { + public: + // STL definitions + typedef PyCxx_ssize_t size_type; + typedef seqref<T> reference; + typedef T const_reference; + typedef seqref<T>* pointer; + typedef int difference_type; + typedef T value_type; // TMM: 26Jun'01 + + virtual size_type max_size() const + { + return static_cast<size_type>( std::string::npos ); // why this constant - its not from python? + } + + virtual size_type capacity() const + { + return size(); + } + + virtual void swap( SeqBase<T> &c ) + { + SeqBase<T> temp = c; + c = ptr(); + set(temp.ptr()); + } + + virtual size_type size() const + { + return PySequence_Length (ptr()); + } + + explicit SeqBase<T> () + : Object( PyTuple_New( 0 ), true ) + { + validate(); + } + + explicit SeqBase<T> (PyObject* pyob, bool owned=false) + : Object( pyob, owned ) + { + validate(); + } + + SeqBase<T> (const Object& ob): Object(ob) + { + validate(); + } + + // Assignment acquires new ownership of pointer + + SeqBase<T>& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + SeqBase<T>& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + + virtual bool accepts (PyObject *pyob) const + { + return pyob && PySequence_Check (pyob); + } + + Py_ssize_t length () const + { + return PySequence_Length (ptr()); + } + + // Element access + const T operator[](sequence_index_type index) const + { + return getItem(index); + } + + seqref<T> operator[](sequence_index_type index) + { + return seqref<T>(*this, index); + } + + virtual T getItem (sequence_index_type i) const + { + return T(asObject(PySequence_GetItem (ptr(), i))); + } + + virtual void setItem (sequence_index_type i, const T& ob) + { + if (PySequence_SetItem (ptr(), i, *ob) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + SeqBase<T> repeat (int count) const + { + return SeqBase<T> (PySequence_Repeat (ptr(), count), true); + } + + SeqBase<T> concat (const SeqBase<T>& other) const + { + return SeqBase<T> (PySequence_Concat(ptr(), *other), true); + } + + // more STL compatability + const T front () const + { + return getItem(0); + } + + seqref<T> front() + { + return seqref<T>(*this, 0); + } + + const T back() const + { + return getItem(size()-1); + } + + seqref<T> back() + { + return seqref<T>(*this, size()-1); + } + + void verify_length( size_type required_size ) const + { + if (size() != required_size) + throw IndexError ("Unexpected SeqBase<T> length."); + } + + void verify_length( size_type min_size, size_type max_size ) const + { + size_type n = size(); + if (n < min_size || n > max_size) + throw IndexError ("Unexpected SeqBase<T> length."); + } + + class iterator: public random_access_iterator_parent(seqref<T>) + { + protected: + friend class SeqBase<T>; + SeqBase<T>* seq; + sequence_index_type count; + + public: + ~iterator () + {} + + iterator () + : seq( 0 ) + , count( 0 ) + {} + + iterator (SeqBase<T>* s, sequence_index_type where) + : seq( s ) + , count( where ) + {} + + iterator (const iterator& other) + : seq( other.seq ) + , count( other.count ) + {} + + bool eql (const iterator& other) const + { + return (seq->ptr() == other.seq->ptr()) && (count == other.count); + } + + bool neq (const iterator& other) const + { + return (seq->ptr() != other.seq->ptr()) || (count != other.count); + } + + bool lss (const iterator& other) const + { + return (count < other.count); + } + + bool gtr (const iterator& other) const + { + return (count > other.count); + } + + bool leq (const iterator& other) const + { + return (count <= other.count); + } + + bool geq (const iterator& other) const + { + return (count >= other.count); + } + + seqref<T> operator*() + { + return seqref<T>(*seq, count); + } + + seqref<T> operator[] (sequence_index_type i) + { + return seqref<T>(*seq, count + i); + } + + iterator& operator=(const iterator& other) + { + if (this == &other) return *this; + seq = other.seq; + count = other.count; + return *this; + } + + iterator operator+(sequence_index_type n) const + { + return iterator(seq, count + n); + } + + iterator operator-(sequence_index_type n) const + { + return iterator(seq, count - n); + } + + iterator& operator+=(sequence_index_type n) + { + count = count + n; + return *this; + } + + iterator& operator-=(sequence_index_type n) + { + count = count - n; + return *this; + } + + int operator-(const iterator& other) const + { + if (*seq != *other.seq) + throw RuntimeError ("SeqBase<T>::iterator comparison error"); + return count - other.count; + } + + // prefix ++ + iterator& operator++ () + { + count++; + return *this; + } + // postfix ++ + iterator operator++ (int) + { + return iterator(seq, count++); + } + // prefix -- + iterator& operator-- () + { + count--; + return *this; + } + // postfix -- + iterator operator-- (int) + { + return iterator(seq, count--); + } + + std::string diagnose() const + { + std::OSTRSTREAM oss; + oss << "iterator diagnosis " << seq << ", " << count << std::ends; + return std::string(oss.str()); + } + }; // end of class SeqBase<T>::iterator + + iterator begin () + { + return iterator(this, 0); + } + + iterator end () + { + return iterator(this, length()); + } + + class const_iterator + : public random_access_iterator_parent(const Object) + { + protected: + friend class SeqBase<T>; + const SeqBase<T>* seq; + sequence_index_type count; + + private: + const_iterator (const SeqBase<T>* s, sequence_index_type where) + : seq( s ) + , count( where ) + {} + + public: + ~const_iterator () + {} + + const_iterator () + : seq( 0 ) + , count( 0 ) + {} + + const_iterator(const const_iterator& other) + : seq( other.seq ) + , count( other.count ) + {} + + const T operator*() const + { + return seq->getItem(count); + } + + const T operator[] (sequence_index_type i) const + { + return seq->getItem(count + i); + } + + const_iterator& operator=(const const_iterator& other) + { + if (this == &other) return *this; + seq = other.seq; + count = other.count; + return *this; + } + + const_iterator operator+(sequence_index_type n) const + { + return const_iterator(seq, count + n); + } + + bool eql (const const_iterator& other) const + { + return (seq->ptr() == other.seq->ptr()) && (count == other.count); + } + + bool neq (const const_iterator& other) const + { + return (seq->ptr() != other.seq->ptr()) || (count != other.count); + } + + bool lss (const const_iterator& other) const + { + return (count < other.count); + } + + bool gtr (const const_iterator& other) const + { + return (count > other.count); + } + + bool leq (const const_iterator& other) const + { + return (count <= other.count); + } + + bool geq (const const_iterator& other) const + { + return (count >= other.count); + } + + const_iterator operator-(sequence_index_type n) + { + return const_iterator(seq, count - n); + } + + const_iterator& operator+=(sequence_index_type n) + { + count = count + n; + return *this; + } + + const_iterator& operator-=(sequence_index_type n) + { + count = count - n; + return *this; + } + + int operator-(const const_iterator& other) const + { + if (*seq != *other.seq) + throw RuntimeError ("SeqBase<T>::const_iterator::- error"); + return count - other.count; + } + // prefix ++ + const_iterator& operator++ () + { + count++; + return *this; + } + // postfix ++ + const_iterator operator++ (int) + { + return const_iterator(seq, count++); + } + // prefix -- + const_iterator& operator-- () + { + count--; + return *this; + } + // postfix -- + const_iterator operator-- (int) + { + return const_iterator(seq, count--); + } + }; // end of class SeqBase<T>::const_iterator + + const_iterator begin () const + { + return const_iterator(this, 0); + } + + const_iterator end () const + { + return const_iterator(this, length()); + } + }; + + // Here's an important typedef you might miss if reading too fast... + typedef SeqBase<Object> Sequence; + + template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator< (const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator> (const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator<=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator>=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right); + + template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator< (const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator> (const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator<=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator>=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right); + + extern bool operator==(const Sequence::iterator& left, const Sequence::iterator& right); + extern bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right); + extern bool operator< (const Sequence::iterator& left, const Sequence::iterator& right); + extern bool operator> (const Sequence::iterator& left, const Sequence::iterator& right); + extern bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right); + extern bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right); + + extern bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right); + extern bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); + extern bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right); + extern bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right); + extern bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); + extern bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); + + // ================================================== + // class Char + // Python strings return strings as individual elements. + // I'll try having a class Char which is a String of length 1 + // + typedef std::basic_string<Py_UNICODE> unicodestring; + extern Py_UNICODE unicode_null_string[1]; + + class Char: public Object + { + public: + explicit Char (PyObject *pyob, bool owned = false): Object(pyob, owned) + { + validate(); + } + + Char (const Object& ob): Object(ob) + { + validate(); + } + + Char (const std::string& v = "") + :Object(PyString_FromStringAndSize( const_cast<char*>(v.c_str()), 1 ), true) + { + validate(); + } + + Char (char v) + : Object(PyString_FromStringAndSize (&v, 1), true) + { + validate(); + } + + Char (Py_UNICODE v) + : Object(PyUnicode_FromUnicode (&v, 1), true) + { + validate(); + } + // Assignment acquires new ownership of pointer + Char& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Char& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + + // Membership + virtual bool accepts (PyObject *pyob) const + { + return (pyob && + (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)) + && PySequence_Length (pyob) == 1); + } + + // Assignment from C string + Char& operator= (const std::string& v) + { + set(PyString_FromStringAndSize (const_cast<char*>(v.c_str()),1), true); + return *this; + } + + Char& operator= (char v) + { + set(PyString_FromStringAndSize (&v, 1), true); + return *this; + } + + Char& operator= (const unicodestring& v) + { + set(PyUnicode_FromUnicode (const_cast<Py_UNICODE*>(v.data()),1), true); + return *this; + } + + Char& operator= (Py_UNICODE v) + { + set(PyUnicode_FromUnicode (&v, 1), true); + return *this; + } + + long ord() + { + if( Py::_Unicode_Check( ptr() ) ) + { + Py_UNICODE *unicode = PyUnicode_AS_UNICODE( ptr() ); + return static_cast<long>( unicode[0] ); + } + else + { + unsigned char *str = reinterpret_cast<unsigned char *>( PyString_AS_STRING( ptr() ) ); + return static_cast<long>( str[0] ); + } + } + + // Conversion + operator String() const; + + operator std::string () const + { + return std::string(PyString_AsString (ptr())); + } + }; + +#ifdef PYCXX_PYTHON_2TO3 + // String and Bytes compatible with Python3 version in 6.0.0 PyCXX + class Bytes; + + class String: public SeqBase<Char> + { + public: + virtual size_type capacity() const + { + return max_size(); + } + + explicit String( PyObject *pyob, bool owned = false) + : SeqBase<Char>( pyob, owned ) + { + validate(); + } + + String( const Object& ob): SeqBase<Char>(ob) + { + validate(); + } + + String() + : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true ) + { + validate(); + } + + String( const std::string& v ) + : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()), v.length() ), true ) + { + validate(); + } + + String( const Py_UNICODE *s, int length ) + : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true ) + { + validate(); + } + + String( const char *s, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s, strlen( s ), encoding, error ), true ) + { + validate(); + } + + String( const char *s, int len, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s, len, encoding, error ), true ) + { + validate(); + } + + String( const std::string &s, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true ) + { + validate(); + } + + String( const char *v, int vsize ) + : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true ) + { + validate(); + } + + String( const char *v ) + : SeqBase<Char>( PyString_FromString( v ), true ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + String &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + String& operator= (PyObject *rhsp) + { + if( ptr() == rhsp ) + return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)); + } + + // Assignment from C string + String& operator=( const std::string &v ) + { + set( PyString_FromStringAndSize( const_cast<char*>( v.data() ), v.length() ), true ); + return *this; + } + String& operator=( const unicodestring &v ) + { + set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), v.length() ), true ); + return *this; + } + + // Encode + Bytes encode( const char *encoding, const char *error="strict" ) const; + + // Queries + virtual size_type size() const + { + if( isUnicode() ) + { + return PyUnicode_GET_SIZE (ptr()); + } + else + { + return PyString_Size (ptr()); + } + } + + operator std::string() const + { + return as_std_string( "utf-8" ); + } + + std::string as_std_string( const char *encoding, const char *error="strict" ) const; + + unicodestring as_unicodestring() const + { + if( isUnicode() ) + { + return unicodestring( PyUnicode_AS_UNICODE( ptr() ), + PyUnicode_GET_SIZE( ptr() ) ); + } + else + { + throw TypeError("can only return unicodestring from Unicode object"); + } + } + + const Py_UNICODE *unicode_data() const + { + if( isUnicode() ) + { + return PyUnicode_AS_UNICODE( ptr() ); + } + else + { + throw TypeError("can only return unicode_data from Unicode object"); + } + } + }; + class Bytes: public SeqBase<Char> + { + public: + virtual size_type capacity() const + { + return max_size(); + } + + explicit Bytes (PyObject *pyob, bool owned = false) + : SeqBase<Char>(pyob, owned) + { + validate(); + } + + Bytes (const Object& ob): SeqBase<Char>(ob) + { + validate(); + } + + Bytes() + : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true ) + { + validate(); + } + + Bytes( const std::string& v ) + : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()), v.length()), true ) + { + validate(); + } + + Bytes( const char *v, size_type vsize ) + : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true ) + { + validate(); + } + + Bytes( const char *v ) + : SeqBase<Char>( PyString_FromString( v ), true ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + Bytes &operator= ( const Object& rhs ) + { + return *this = *rhs; + } + + Bytes &operator= (PyObject *rhsp) + { + if( ptr() == rhsp ) + return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && (Py::_String_Check( pyob ) || Py::_Unicode_Check( pyob )); + } + + // Assignment from C string + Bytes &operator= (const std::string& v) + { + set( PyString_FromStringAndSize( const_cast<char*>( v.data() ), v.length() ), true ); + return *this; + } + Bytes &operator= (const unicodestring& v) + { + set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), v.length() ), true ); + return *this; + } + + String decode( const char *encoding, const char *error="strict" ) + { + return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true ); + } + + // Queries + virtual size_type size () const + { + if( isUnicode() ) + { + return PyUnicode_GET_SIZE (ptr()); + } + else + { + return PyString_Size (ptr()); + } + } + + operator std::string () const + { + return as_std_string(); + } + + std::string as_std_string() const + { + if( isUnicode() ) + { + throw TypeError("cannot return std::string from Unicode object"); + } + else + { + return std::string( PyString_AsString( ptr() ), static_cast<size_t>( PyString_Size( ptr() ) ) ); + } + } + + unicodestring as_unicodestring() const + { + if( isUnicode() ) + { + return unicodestring( PyUnicode_AS_UNICODE( ptr() ), + static_cast<size_t>( PyUnicode_GET_SIZE( ptr() ) ) ); + } + else + { + throw TypeError("can only return unicodestring from Unicode object"); + } + } + }; + +#else + // original PyCXX 5.4.x version of String + class String: public SeqBase<Char> + { + public: + virtual size_type capacity() const + { + return max_size(); + } + + explicit String (PyObject *pyob, bool owned = false): SeqBase<Char>(pyob, owned) + { + validate(); + } + + String (const Object& ob): SeqBase<Char>(ob) + { + validate(); + } + + String() + : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true ) + { + validate(); + } + + String( const std::string& v ) + : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()), v.length() ), true ) + { + validate(); + } + + String( const char *s, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s, strlen( s ), encoding, error ), true ) + { + validate(); + } + + String( const char *s, size_type len, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s, len, encoding, error ), true ) + { + validate(); + } + + String( const std::string &s, const char *encoding, const char *error="strict" ) + : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true ) + { + validate(); + } + + String( const char *v, size_type vsize ) + : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true ) + { + validate(); + } + + String( const char* v ) + : SeqBase<Char>( PyString_FromString( v ), true ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + String& operator= ( const Object& rhs ) + { + return *this = *rhs; + } + + String& operator= (PyObject* rhsp) + { + if( ptr() == rhsp ) + return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)); + } + + // Assignment from C string + String& operator= (const std::string& v) + { + set( PyString_FromStringAndSize( const_cast<char*>( v.data() ), v.length() ), true ); + return *this; + } + String& operator= (const unicodestring& v) + { + set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), v.length() ), true ); + return *this; + } + + + // Encode + String encode( const char *encoding, const char *error="strict" ) const + { + if( isUnicode() ) + { + return String( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); + } + else + { + return String( PyString_AsEncodedObject( ptr(), encoding, error ), true ); + } + } + + String decode( const char *encoding, const char *error="strict" ) + { + return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true ); + } + + // Queries + virtual size_type size () const + { + if( isUnicode() ) + { + return PyUnicode_GET_SIZE (ptr()); + } + else + { + return PyString_Size (ptr()); + } + } + + operator std::string () const + { + return as_std_string(); + } + + std::string as_std_string() const + { + if( isUnicode() ) + { + throw TypeError("cannot return std::string from Unicode object"); + } + else + { + return std::string( PyString_AsString( ptr() ), static_cast<size_t>( PyString_Size( ptr() ) ) ); + } + } + + std::string as_std_string( const char *encoding, const char *error="strict" ) const; + + unicodestring as_unicodestring() const + { + if( isUnicode() ) + { + return unicodestring( PyUnicode_AS_UNICODE( ptr() ), + static_cast<size_t>( PyUnicode_GET_SIZE( ptr() ) ) ); + } + else + { + throw TypeError("can only return unicodestring from Unicode object"); + } + } + }; +#endif + + // ================================================== + // class Tuple + class Tuple: public Sequence + { + public: + virtual void setItem (sequence_index_type offset, const Object&ob) + { + // note PyTuple_SetItem is a thief... + if(PyTuple_SetItem (ptr(), offset, new_reference_to(ob)) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + // Constructor + explicit Tuple (PyObject *pyob, bool owned = false): Sequence (pyob, owned) + { + validate(); + } + + Tuple (const Object& ob): Sequence(ob) + { + validate(); + } + + // New tuple of a given size + explicit Tuple (int size = 0) + { + set(PyTuple_New (size), true); + validate (); + for (sequence_index_type i=0; i < size; i++) + { + if(PyTuple_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1) + { + ifPyErrorThrowCxxException(); + } + } + } + // Tuple from any sequence + explicit Tuple (const Sequence& s) + { + sequence_index_type limit( sequence_index_type( s.length() ) ); + + set(PyTuple_New (limit), true); + validate(); + + for(sequence_index_type i=0; i < limit; i++) + { + if(PyTuple_SetItem (ptr(), i, new_reference_to(s[i])) == -1) + { + ifPyErrorThrowCxxException(); + } + } + } + // Assignment acquires new ownership of pointer + + Tuple& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Tuple& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Tuple_Check (pyob); + } + + Tuple getSlice (int i, int j) const + { + return Tuple (PySequence_GetSlice (ptr(), i, j), true); + } + + }; + + class TupleN: public Tuple + { + public: + TupleN() + : Tuple( 0 ) + { + } + + TupleN( const Object &obj1 ) + : Tuple( 1 ) + { + setItem( 0, obj1 ); + } + + TupleN( const Object &obj1, const Object &obj2 ) + : Tuple( 2 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3 ) + : Tuple( 3 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4 ) + : Tuple( 4 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5 ) + : Tuple( 5 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6 ) + : Tuple( 6 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7 ) + : Tuple( 7 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7, const Object &obj8 ) + : Tuple( 8 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + setItem( 7, obj8 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7, const Object &obj8, const Object &obj9 ) + : Tuple( 9 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + setItem( 7, obj8 ); + setItem( 8, obj9 ); + } + + virtual ~TupleN() + { } + }; + + + // ================================================== + // class List + + class List: public Sequence + { + public: + // Constructor + explicit List (PyObject *pyob, bool owned = false): Sequence(pyob, owned) + { + validate(); + } + List (const Object& ob): Sequence(ob) + { + validate(); + } + // Creation at a fixed size + List (size_type size = 0) + { + set(PyList_New (size), true); + validate(); + for (sequence_index_type i=0; i < size; i++) + { + if(PyList_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1) + { + ifPyErrorThrowCxxException(); + } + } + } + + // List from a sequence + List (const Sequence& s): Sequence() + { + size_type n = s.length(); + set(PyList_New (n), true); + validate(); + for (sequence_index_type i=0; i < n; i++) + { + if(PyList_SetItem (ptr(), i, new_reference_to(s[i])) == -1) + { + ifPyErrorThrowCxxException(); + } + } + } + + virtual size_type capacity() const + { + return max_size(); + } + // Assignment acquires new ownership of pointer + + List& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + List& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_List_Check (pyob); + } + + List getSlice (int i, int j) const + { + return List (PyList_GetSlice (ptr(), i, j), true); + } + + void setSlice (int i, int j, const Object& v) + { + if(PyList_SetSlice (ptr(), i, j, *v) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void append (const Object& ob) + { + if(PyList_Append (ptr(), *ob) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void insert (int i, const Object& ob) + { + if(PyList_Insert (ptr(), i, *ob) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void sort () + { + if(PyList_Sort(ptr()) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void reverse () + { + if(PyList_Reverse(ptr()) == -1) + { + ifPyErrorThrowCxxException(); + } + } + }; + + + // Mappings + // ================================================== + template<TEMPLATE_TYPENAME T> + class mapref + { + protected: + MapBase<T>& s; // the map + Object key; // item key + T the_item; + + public: + mapref<T> (MapBase<T>& map, const std::string& k) + : s(map), the_item() + { + key = String(k); + if(map.hasKey(key)) the_item = map.getItem(key); + } + + mapref<T> (MapBase<T>& map, const Object& k) + : s(map), key(k), the_item() + { + if(map.hasKey(key)) the_item = map.getItem(key); + } + + virtual ~mapref<T>() + {} + + // MapBase<T> stuff + // lvalue + mapref<T>& operator=(const mapref<T>& other) + { + if(this == &other) return *this; + the_item = other.the_item; + s.setItem(key, other.the_item); + return *this; + } + + mapref<T>& operator= (const T& ob) + { + the_item = ob; + s.setItem (key, ob); + return *this; + } + + // rvalue + operator T() const + { + return the_item; + } + + // forward everything else to the_item + PyObject* ptr () const + { + return the_item.ptr(); + } + + int reference_count () const + { // the mapref count + return the_item.reference_count(); + } + + Type type () const + { + return the_item.type(); + } + + String str () const + { + return the_item.str(); + } + + String repr () const + { + return the_item.repr(); + } + + bool hasAttr (const std::string& attr_name) const + { + return the_item.hasAttr(attr_name); + } + + Object getAttr (const std::string& attr_name) const + { + return the_item.getAttr(attr_name); + } + + Object getItem (const Object& k) const + { + return the_item.getItem(k); + } + + long hashValue () const + { + return the_item.hashValue(); + } + + bool isCallable () const + { + return the_item.isCallable(); + } + + bool isInstance () const + { + return the_item.isInstance(); + } + + bool isList () const + { + return the_item.isList(); + } + + bool isMapping () const + { + return the_item.isMapping(); + } + + bool isNumeric () const + { + return the_item.isNumeric(); + } + + bool isSequence () const + { + return the_item.isSequence(); + } + + bool isTrue () const + { + return the_item.isTrue(); + } + + bool isType (const Type& t) const + { + return the_item.isType (t); + } + + bool isTuple() const + { + return the_item.isTuple(); + } + + bool isString() const + { + return the_item.isString(); + } + + // Commands + void setAttr (const std::string& attr_name, const Object& value) + { + the_item.setAttr(attr_name, value); + } + + void delAttr (const std::string& attr_name) + { + the_item.delAttr(attr_name); + } + + void delItem (const Object& k) + { + the_item.delItem(k); + } + }; // end of mapref + + // TMM: now for mapref<T> + template< class T > + bool operator==(const mapref<T>& /* left */, const mapref<T>& /* right */) + { + return true; // NOT completed. + } + + template< class T > + bool operator!=(const mapref<T>& /* left */, const mapref<T>& /* right */) + { + return true; // not completed. + } + + template<TEMPLATE_TYPENAME T> + class MapBase: public Object + { + protected: + explicit MapBase<T>() + {} + public: + // reference: proxy class for implementing [] + // TMM: 26Jun'01 - the types + // If you assume that Python mapping is a hash_map... + // hash_map::value_type is not assignable, but + // (*it).second = data must be a valid expression + typedef PyCxx_ssize_t size_type; + typedef Object key_type; + typedef mapref<T> data_type; + typedef std::pair< const T, T > value_type; + typedef std::pair< const T, mapref<T> > reference; + typedef const std::pair< const T, const T > const_reference; + typedef std::pair< const T, mapref<T> > pointer; + + // Constructor + explicit MapBase<T> (PyObject *pyob, bool owned = false): Object(pyob, owned) + { + validate(); + } + + // TMM: 02Jul'01 - changed MapBase<T> to Object in next line + MapBase<T> (const Object& ob): Object(ob) + { + validate(); + } + + // Assignment acquires new ownership of pointer + MapBase<T>& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + MapBase<T>& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && PyMapping_Check(pyob); + } + + // Clear -- PyMapping Clear is missing + // + + void clear () + { + List k = keys(); + for(List::iterator i = k.begin(); i != k.end(); i++) + { + delItem(*i); + } + } + + virtual Py_ssize_t size() const + { + return PyMapping_Length (ptr()); + } + + // Element Access + T operator[](const std::string& key) const + { + return getItem(key); + } + + T operator[](const Object& key) const + { + return getItem(key); + } + + mapref<T> operator[](const std::string& key) + { + return mapref<T>(*this, key); + } + + mapref<T> operator[](const Object& key) + { + return mapref<T>(*this, key); + } + + Py_ssize_t length () const + { + return PyMapping_Length (ptr()); + } + + bool hasKey (const std::string& s) const + { + return PyMapping_HasKeyString (ptr(),const_cast<char*>(s.c_str())) != 0; + } + + bool hasKey (const Object& s) const + { + return PyMapping_HasKey (ptr(), s.ptr()) != 0; + } + + T getItem (const std::string& s) const + { + return T( + asObject(PyMapping_GetItemString (ptr(),const_cast<char*>(s.c_str()))) + ); + } + + T getItem (const Object& s) const + { + return T( + asObject(PyObject_GetItem (ptr(), s.ptr())) + ); + } + + virtual void setItem (const char *s, const Object& ob) + { + if (PyMapping_SetItemString (ptr(), const_cast<char*>(s), *ob) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + virtual void setItem (const std::string& s, const Object& ob) + { + if (PyMapping_SetItemString (ptr(), const_cast<char*>(s.c_str()), *ob) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + virtual void setItem (const Object& s, const Object& ob) + { + if (PyObject_SetItem (ptr(), s.ptr(), ob.ptr()) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void delItem (const std::string& s) + { + if (PyMapping_DelItemString (ptr(), const_cast<char*>(s.c_str())) == -1) + { + ifPyErrorThrowCxxException(); + } + } + + void delItem (const Object& s) + { + if (PyMapping_DelItem (ptr(), *s) == -1) + { + ifPyErrorThrowCxxException(); + } + } + // Queries + List keys () const + { + static char keys[] = {'k', 'e', 'y', 's', 0}; + return List(PyObject_CallMethod( ptr(), keys, NULL ), true ); + } + + List values () const + { // each returned item is a (key, value) pair + return List(PyMapping_Values(ptr()), true); + } + + List items () const + { + return List(PyMapping_Items(ptr()), true); + } + + class iterator + { + // : public forward_iterator_parent( std::pair<const T,T> ) { + protected: + typedef std::forward_iterator_tag iterator_category; + typedef std::pair< const T, T > value_type; + typedef int difference_type; + typedef std::pair< const T, mapref<T> > pointer; + typedef std::pair< const T, mapref<T> > reference; + + friend class MapBase<T>; + // + MapBase<T> *map; + List keys; // for iterating over the map + sequence_index_type pos; // index into the keys + + private: + iterator( MapBase<T>* m, List k, sequence_index_type p ) + : map( m ) + , keys( k ) + , pos( p ) + {} + + public: + ~iterator () + {} + + iterator () + : map( 0 ) + , keys() + , pos() + {} + + iterator (MapBase<T>* m, bool end = false ) + : map( m ) + , keys( m->keys() ) + , pos( end ? keys.length() : 0 ) + {} + + iterator (const iterator& other) + : map( other.map ) + , keys( other.keys ) + , pos( other.pos ) + {} + + reference operator*() + { + Object key = keys[ pos ]; + return std::make_pair(key, mapref<T>(*map,key)); + } + + iterator& operator=(const iterator& other) + { + if (this == &other) + return *this; + map = other.map; + keys = other.keys; + pos = other.pos; + return *this; + } + + bool eql(const iterator& right) const + { + return map->ptr() == right.map->ptr() && pos == right.pos; + } + bool neq( const iterator& right ) const + { + return map->ptr() != right.map->ptr() || pos != right.pos; + } + + // pointer operator->() { + // return ; + // } + + // prefix ++ + iterator& operator++ () + { pos++; return *this;} + // postfix ++ + iterator operator++ (int) + { return iterator(map, keys, pos++);} + // prefix -- + iterator& operator-- () + { pos--; return *this;} + // postfix -- + iterator operator-- (int) + { return iterator(map, keys, pos--);} + + std::string diagnose() const + { + std::OSTRSTREAM oss; + oss << "iterator diagnosis " << map << ", " << pos << std::ends; + return std::string(oss.str()); + } + }; // end of class MapBase<T>::iterator + + iterator begin () + { + return iterator(this); + } + + iterator end () + { + return iterator(this, true); + } + + class const_iterator + { + protected: + typedef std::forward_iterator_tag iterator_category; + typedef const std::pair< const T, T > value_type; + typedef int difference_type; + typedef const std::pair< const T, T > pointer; + typedef const std::pair< const T, T > reference; + + friend class MapBase<T>; + const MapBase<T> *map; + List keys; // for iterating over the map + sequence_index_type pos; // index into the keys + + private: + const_iterator( const MapBase<T>* m, List k, int p ) + : map( m ) + , keys( k ) + , pos( p ) + {} + + public: + ~const_iterator () + {} + + const_iterator () + : map( 0 ) + , keys() + , pos() + {} + + const_iterator (const MapBase<T>* m, bool end = false ) + : map( m ) + , keys( m->keys() ) + , pos( end ? keys.length() : 0 ) + {} + + const_iterator(const const_iterator& other) + : map( other.map ) + , keys( other.keys ) + , pos( other.pos ) + {} + + bool eql(const const_iterator& right) const + { + return map->ptr() == right.map->ptr() && pos == right.pos; + } + + bool neq( const const_iterator& right ) const + { + return map->ptr() != right.map->ptr() || pos != right.pos; + } + + const_reference operator*() + { + Object key = keys[ pos ]; + return std::make_pair( key, mapref<T>( *map, key ) ); + } + + const_iterator& operator=(const const_iterator& other) + { + if (this == &other) return *this; + map = other.map; + keys = other.keys; + pos = other.pos; + return *this; + } + + // prefix ++ + const_iterator& operator++ () + { pos++; return *this;} + // postfix ++ + const_iterator operator++ (int) + { return const_iterator(map, keys, pos++);} + // prefix -- + const_iterator& operator-- () + { pos--; return *this;} + // postfix -- + const_iterator operator-- (int) + { return const_iterator(map, keys, pos--);} + }; // end of class MapBase<T>::const_iterator + + const_iterator begin () const + { + return const_iterator(this); + } + + const_iterator end () const + { + return const_iterator(this, true); + } + + }; // end of MapBase<T> + + typedef MapBase<Object> Mapping; + + template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME MapBase<T>::iterator& left, const EXPLICIT_TYPENAME MapBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME MapBase<T>::iterator& left, const EXPLICIT_TYPENAME MapBase<T>::iterator& right); + template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME MapBase<T>::const_iterator& left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator& right); + template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME MapBase<T>::const_iterator& left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator& right); + + extern bool operator==(const Mapping::iterator& left, const Mapping::iterator& right); + extern bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right); + extern bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right); + extern bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right); + + + // ================================================== + // class Dict + class Dict: public Mapping + { + public: + // Constructor + explicit Dict (PyObject *pyob, bool owned=false): Mapping (pyob, owned) + { + validate(); + } + Dict (const Object& ob): Mapping(ob) + { + validate(); + } + // Creation + Dict () + { + set(PyDict_New (), true); + validate(); + } + // Assignment acquires new ownership of pointer + + Dict& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Dict& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set(rhsp); + return *this; + } + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && Py::_Dict_Check (pyob); + } + }; + + class Callable: public Object + { + public: + // Constructor + explicit Callable (): Object() {} + explicit Callable (PyObject *pyob, bool owned = false): Object (pyob, owned) + { + validate(); + } + + Callable (const Object& ob): Object(ob) + { + validate(); + } + + // Assignment acquires new ownership of pointer + + Callable& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Callable& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set (rhsp); + return *this; + } + + // Membership + virtual bool accepts (PyObject *pyob) const + { + return pyob && PyCallable_Check (pyob); + } + + // Call + Object apply(const Tuple& args) const + { + PyObject *result = PyObject_CallObject( ptr(), args.ptr() ); + if( result == NULL ) + { + ifPyErrorThrowCxxException(); + } + return asObject( result ); + } + + // Call with keywords + Object apply(const Tuple& args, const Dict& kw) const + { + PyObject *result = PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ); + if( result == NULL ) + { + ifPyErrorThrowCxxException(); + } + return asObject( result ); + } + + Object apply(PyObject* pargs = 0) const + { + if( pargs == 0 ) + { + return apply( Tuple() ); + } + else + { + return apply( Tuple( pargs ) ); + } + } + }; + + class Module: public Object + { + public: + explicit Module (PyObject* pyob, bool owned = false): Object (pyob, owned) + { + validate(); + } + + // Construct from module name + explicit Module (const std::string&s): Object() + { + PyObject *m = PyImport_AddModule( const_cast<char *>(s.c_str()) ); + set( m, false ); + validate (); + } + + // Copy constructor acquires new ownership of pointer + Module (const Module& ob): Object(*ob) + { + validate(); + } + + Module& operator= (const Object& rhs) + { + return (*this = *rhs); + } + + Module& operator= (PyObject* rhsp) + { + if(ptr() == rhsp) return *this; + set(rhsp); + return *this; + } + + Dict getDict() + { + return Dict(PyModule_GetDict(ptr())); + // Caution -- PyModule_GetDict returns borrowed reference! + } + }; + + // Call function helper + inline Object Object::callMemberFunction( const std::string &function_name ) const + { + Callable target( getAttr( function_name ) ); + Tuple args( 0 ); + return target.apply( args ); + } + + inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const + { + Callable target( getAttr( function_name ) ); + return target.apply( args ); + } + + inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const + { + Callable target( getAttr( function_name ) ); + return target.apply( args, kw ); + } + + // Numeric interface + inline Object operator+ (const Object& a) + { + return asObject(PyNumber_Positive(*a)); + } + inline Object operator- (const Object& a) + { + return asObject(PyNumber_Negative(*a)); + } + + inline Object abs(const Object& a) + { + return asObject(PyNumber_Absolute(*a)); + } + + inline std::pair<Object,Object> coerce(const Object& a, const Object& b) + { + PyObject *p1, *p2; + p1 = *a; + p2 = *b; + if(PyNumber_Coerce(&p1,&p2) == -1) + { + ifPyErrorThrowCxxException(); + } + return std::pair<Object,Object>(asObject(p1), asObject(p2)); + } + + inline Object operator+ (const Object& a, const Object& b) + { + return asObject(PyNumber_Add(*a, *b)); + } + inline Object operator+ (const Object& a, int j) + { + return asObject(PyNumber_Add(*a, *Int(j))); + } + inline Object operator+ (const Object& a, double v) + { + return asObject(PyNumber_Add(*a, *Float(v))); + } + inline Object operator+ (int j, const Object& b) + { + return asObject(PyNumber_Add(*Int(j), *b)); + } + inline Object operator+ (double v, const Object& b) + { + return asObject(PyNumber_Add(*Float(v), *b)); + } + + inline Object operator- (const Object& a, const Object& b) + { + return asObject(PyNumber_Subtract(*a, *b)); + } + inline Object operator- (const Object& a, int j) + { + return asObject(PyNumber_Subtract(*a, *Int(j))); + } + inline Object operator- (const Object& a, double v) + { + return asObject(PyNumber_Subtract(*a, *Float(v))); + } + inline Object operator- (int j, const Object& b) + { + return asObject(PyNumber_Subtract(*Int(j), *b)); + } + inline Object operator- (double v, const Object& b) + { + return asObject(PyNumber_Subtract(*Float(v), *b)); + } + + inline Object operator* (const Object& a, const Object& b) + { + return asObject(PyNumber_Multiply(*a, *b)); + } + inline Object operator* (const Object& a, int j) + { + return asObject(PyNumber_Multiply(*a, *Int(j))); + } + inline Object operator* (const Object& a, double v) + { + return asObject(PyNumber_Multiply(*a, *Float(v))); + } + inline Object operator* (int j, const Object& b) + { + return asObject(PyNumber_Multiply(*Int(j), *b)); + } + inline Object operator* (double v, const Object& b) + { + return asObject(PyNumber_Multiply(*Float(v), *b)); + } + + inline Object operator/ (const Object& a, const Object& b) + { + return asObject(PyNumber_Divide(*a, *b)); + } + inline Object operator/ (const Object& a, int j) + { + return asObject(PyNumber_Divide(*a, *Int(j))); + } + inline Object operator/ (const Object& a, double v) + { + return asObject(PyNumber_Divide(*a, *Float(v))); + } + inline Object operator/ (int j, const Object& b) + { + return asObject(PyNumber_Divide(*Int(j), *b)); + } + inline Object operator/ (double v, const Object& b) + { + return asObject(PyNumber_Divide(*Float(v), *b)); + } + + inline Object operator% (const Object& a, const Object& b) + { + return asObject(PyNumber_Remainder(*a, *b)); + } + inline Object operator% (const Object& a, int j) + { + return asObject(PyNumber_Remainder(*a, *Int(j))); + } + inline Object operator% (const Object& a, double v) + { + return asObject(PyNumber_Remainder(*a, *Float(v))); + } + inline Object operator% (int j, const Object& b) + { + return asObject(PyNumber_Remainder(*Int(j), *b)); + } + inline Object operator% (double v, const Object& b) + { + return asObject(PyNumber_Remainder(*Float(v), *b)); + } + + inline Object type(const BaseException&) // return the type of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch(&ptype, &pvalue, &ptrace); + Object result; + if(ptype) result = ptype; + PyErr_Restore(ptype, pvalue, ptrace); + return result; + } + + inline Object value(const BaseException&) // return the value of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch(&ptype, &pvalue, &ptrace); + Object result; + if(pvalue) result = pvalue; + PyErr_Restore(ptype, pvalue, ptrace); + return result; + } + + inline Object trace(const BaseException&) // return the traceback of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch(&ptype, &pvalue, &ptrace); + Object result; + if(ptrace) result = ptrace; + PyErr_Restore(ptype, pvalue, ptrace); + return result; + } + +template<TEMPLATE_TYPENAME T> +String seqref<T>::str () const +{ + return the_item.str(); +} + +template<TEMPLATE_TYPENAME T> +String seqref<T>::repr () const +{ + return the_item.repr(); +} + +} // namespace Py +#endif // __CXX_Objects__h diff --git a/contrib/libs/pycxx/Python2/PythonType.hxx b/contrib/libs/pycxx/Python2/PythonType.hxx new file mode 100755 index 00000000000..dce6917a5c5 --- /dev/null +++ b/contrib/libs/pycxx/Python2/PythonType.hxx @@ -0,0 +1,209 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_PythonType__h +#define __CXX_PythonType__h + +namespace Py +{ + class PythonType + { + public: +#define B(n) (1<<(n)) + // if you define one sequence method you must define + // all of them except the assigns + + PythonType( size_t base_size, int itemsize, const char *default_name ); + virtual ~PythonType(); + + const char *getName() const; + const char *getDoc() const; + + PyTypeObject *type_object() const; + PythonType &name( const char *nam ); + PythonType &doc( const char *d ); + + PythonType &supportClass( void ); + PythonType &dealloc( void (*f)( PyObject* ) ); +#if defined( PYCXX_PYTHON_2TO3 ) + PythonType &supportPrint( void ); +#endif + PythonType &supportGetattr( void ); + PythonType &supportSetattr( void ); + PythonType &supportGetattro( void ); + PythonType &supportSetattro( void ); +#if defined( PYCXX_PYTHON_2TO3 ) + PythonType &supportCompare( void ); +#endif + PythonType &supportRichCompare( void ); + PythonType &supportRepr( void ); + PythonType &supportStr( void ); + PythonType &supportHash( void ); + PythonType &supportCall( void ); + + enum { + support_iter_iter = B(0), + support_iter_iternext = B(1) + }; + PythonType &supportIter( int methods_to_support= + support_iter_iter | + support_iter_iternext ); + + enum { + support_sequence_length = B(0), + support_sequence_repeat = B(1), + support_sequence_item = B(2), + support_sequence_slice = B(3), + support_sequence_concat = B(4), + support_sequence_ass_item = B(5), + support_sequence_ass_slice = B(6), + support_sequence_inplace_concat = B(7), + support_sequence_inplace_repeat = B(8), + support_sequence_contains = B(9) + }; + PythonType &supportSequenceType( int methods_to_support= + support_sequence_length | + support_sequence_repeat | + support_sequence_item | + support_sequence_slice | + support_sequence_concat + ); + + enum { + support_mapping_length = B(0), + support_mapping_subscript = B(1), + support_mapping_ass_subscript = B(2) + }; + PythonType &supportMappingType( int methods_to_support= + support_mapping_length | + support_mapping_subscript + ); + + enum { + support_number_add = B(0), + support_number_subtract = B(1), + support_number_multiply = B(2), + support_number_divide = B(3), + support_number_remainder = B(4), + support_number_divmod = B(5), + support_number_power = B(6), + support_number_negative = B(7), + support_number_positive = B(8), + support_number_absolute = B(9), + support_number_nonzero = B(10), + support_number_invert = B(11), + support_number_lshift = B(12), + support_number_rshift = B(13), + support_number_and = B(14), + support_number_xor = B(15), + support_number_or = B(16), + support_number_int = B(17), + support_number_long = B(18), + support_number_float = B(19), + support_number_oct = B(20), + support_number_hex = B(21) + }; + PythonType &supportNumberType( int methods_to_support= + support_number_add | + support_number_subtract | + support_number_multiply | + support_number_divide | + support_number_remainder | + support_number_divmod | + support_number_power | + support_number_negative | + support_number_positive | + support_number_absolute | + support_number_nonzero | + support_number_invert | + support_number_lshift | + support_number_rshift | + support_number_and | + support_number_xor | + support_number_or | + support_number_int | + support_number_long | + support_number_float | + support_number_oct | + support_number_hex + ); + + enum { + support_buffer_getreadbuffer = B(0), + support_buffer_getwritebuffer = B(1), + support_buffer_getsegcount = B(2) + }; + PythonType &supportBufferType( int methods_to_support= + support_buffer_getreadbuffer | + support_buffer_getwritebuffer | + support_buffer_getsegcount + ); +#undef B + + PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) ); + PythonType &set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ); + PythonType &set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ); + PythonType &set_methods( PyMethodDef *methods ); + + // call once all support functions have been called to ready the type + bool readyType(); + + protected: + void init_sequence(); + void init_mapping(); + void init_number(); + void init_buffer(); + + PyTypeObject *table; + PySequenceMethods *sequence_table; + PyMappingMethods *mapping_table; + PyNumberMethods *number_table; + PyBufferProcs *buffer_table; + + private: + // + // prevent the compiler generating these unwanted functions + // + PythonType( const PythonType &tb ); // unimplemented + void operator=( const PythonType &t ); // unimplemented + + }; + +} // Namespace Py + +// End of __CXX_PythonType__h +#endif diff --git a/contrib/libs/pycxx/Python2/cxx_exceptions.cxx b/contrib/libs/pycxx/Python2/cxx_exceptions.cxx new file mode 100644 index 00000000000..9dff2753ddd --- /dev/null +++ b/contrib/libs/pycxx/Python2/cxx_exceptions.cxx @@ -0,0 +1,72 @@ +// +// cxx_exceptions.cxx +// +#include "../Exception.hxx" +#include "../Extensions.hxx" + +#include <map> + +namespace Py +{ +typedef void (*throw_exception_func_t)( PyObject* exc ); + +std::map<void *, throw_exception_func_t> py_exc_type_to_exc_func; + +void addPythonException( ExtensionExceptionType &py_exc_type, throw_exception_func_t func ) +{ + py_exc_type_to_exc_func.insert( std::make_pair( py_exc_type.ptr(), func ) ); +} + +void addPythonException( PyObject *py_exc_type, throw_exception_func_t func ) +{ + py_exc_type_to_exc_func.insert( std::make_pair( py_exc_type, func ) ); +} + +void ifPyErrorThrowCxxException() +{ + if( PyErr_Occurred() ) + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch( &ptype, &pvalue, &ptrace ); + PyErr_Restore( ptype, pvalue, ptrace ); + + Object q( ptype ); + + std::map<void *, throw_exception_func_t>::iterator func = py_exc_type_to_exc_func.find( ptype ); + if( func != py_exc_type_to_exc_func.end() ) + { +#ifdef PYCXX_DEBUG + std::cout << "ifPyErrorThrowCxxException found throwFunc: " << q << std::endl; +#endif + (func->second)(pvalue); + } + else + { +#ifdef PYCXX_DEBUG + std::cout << "ifPyErrorThrowCxxException no throwFunc: " << q << std::endl; +#endif + throw Exception(); + } + } +} + +void initExceptions() +{ + static bool init_done = false; + if( init_done ) + { + return; + } + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + addPythonException( eclass::exceptionType(), eclass::throwFuncObj ); + +#include "cxx_standard_exceptions.hxx" + +#undef PYCXX_STANDARD_EXCEPTION + + init_done = true; +} + + +} // end of namespace Py diff --git a/contrib/libs/pycxx/Python2/cxx_extensions.cxx b/contrib/libs/pycxx/Python2/cxx_extensions.cxx new file mode 100644 index 00000000000..dafb08ed141 --- /dev/null +++ b/contrib/libs/pycxx/Python2/cxx_extensions.cxx @@ -0,0 +1,2073 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "../Extensions.hxx" +#include "../Exception.hxx" + +#include <assert.h> + +extern "C" { // sanitizers API. Avoid dependency on util. +#if defined(_asan_enabled_) +void __lsan_ignore_object(const void* p); +#endif +} + +#ifdef PYCXX_DEBUG +// +// Functions useful when debugging PyCXX +// +void bpt( void ) +{ +} + +void printRefCount( PyObject *obj ) +{ + std::cout << "RefCount of 0x" << std::hex << reinterpret_cast< unsigned long >( obj ) << std::dec << " is " << Py_REFCNT( obj ) << std::endl; +} +#endif + +namespace Py +{ +#ifdef PYCXX_PYTHON_2TO3 +std::string String::as_std_string( const char *encoding, const char *error ) const +{ + if( isUnicode() ) + { + Bytes encoded( encode( encoding, error ) ); + return encoded.as_std_string(); + } + else + { + return std::string( PyString_AsString( ptr() ), static_cast<size_type>( PyString_Size( ptr() ) ) ); + } +} + +Bytes String::encode( const char *encoding, const char *error ) const +{ + if( isUnicode() ) + { + return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ) ); + } + else + { + return Bytes( PyString_AsEncodedObject( ptr(), encoding, error ) ); + } +} + +#else +std::string String::as_std_string( const char *encoding, const char *error ) const +{ + if( isUnicode() ) + { + String encoded( encode( encoding, error ) ); + return encoded.as_std_string(); + } + else + { + return std::string( PyString_AsString( ptr() ), static_cast<size_type>( PyString_Size( ptr() ) ) ); + } +} +#endif + +void Object::validate() +{ + // release pointer if not the right type + if( !accepts( p ) ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + std::string s( "PyCXX: Error creating object of type " ); + s += (typeid( *this )).name(); + + if( p != NULL ) + { + String from_repr = repr(); + s += " from "; + s += from_repr.as_std_string( "utf-8" ); + } + else + { + s += " from (nil)"; + } +#endif + release(); + + // Error message already set + ifPyErrorThrowCxxException(); + + // Better error message if RTTI available +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + throw TypeError( s ); +#else + throw TypeError( "PyCXX: type error." ); +#endif + } +} + +//================================================================================ +// +// Implementation of MethodTable +// +//================================================================================ +PyMethodDef MethodTable::method( const char *method_name, PyCFunction f, int flags, const char *doc ) +{ + PyMethodDef m; + m.ml_name = const_cast<char*>( method_name ); + m.ml_meth = f; + m.ml_flags = flags; + m.ml_doc = const_cast<char*>( doc ); + return m; +} + +MethodTable::MethodTable() +{ + t.push_back( method( 0, 0, 0, 0 ) ); + mt = NULL; +} + +MethodTable::~MethodTable() +{ + delete [] mt; +} + +void MethodTable::add( const char *method_name, PyCFunction f, const char *doc, int flag ) +{ + if( !mt ) + { + t.insert( t.end()-1, method( method_name, f, flag, doc ) ); + } + else + { + throw RuntimeError( "Too late to add a module method!" ); + } +} + +PyMethodDef *MethodTable::table() +{ + if( !mt ) + { + Py_ssize_t t1size = t.size(); + mt = new PyMethodDef[ t1size ]; + int j = 0; + for( std::vector<PyMethodDef>::iterator i = t.begin(); i != t.end(); i++ ) + { + mt[ j++ ] = *i; + } + } + return mt; +} + +//================================================================================ +// +// Implementation of ExtensionModule +// +//================================================================================ +ExtensionModuleBase::ExtensionModuleBase( const char *name ) +: m_module_name( name ) +, m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) +, m_method_table() +, m_module( NULL ) +{} + +ExtensionModuleBase::~ExtensionModuleBase() +{} + +const std::string &ExtensionModuleBase::name() const +{ + return m_module_name; +} + +const std::string &ExtensionModuleBase::fullName() const +{ + return m_full_module_name; +} + +class ExtensionModuleBasePtr : public PythonExtension<ExtensionModuleBasePtr> +{ +public: + ExtensionModuleBasePtr( ExtensionModuleBase *_module ) + : module( _module ) + {} + + virtual ~ExtensionModuleBasePtr() + {} + + ExtensionModuleBase *module; +}; + +void initExceptions(); + +void ExtensionModuleBase::initialize( const char *module_doc ) +{ + initExceptions(); + + PyObject *module_ptr = new ExtensionModuleBasePtr( this ); +#if defined(_asan_enabled_) + __lsan_ignore_object(module_ptr); +#endif + m_module = Py_InitModule4 + ( + const_cast<char *>( m_module_name.c_str() ), // name + m_method_table.table(), // methods + const_cast<char *>( module_doc ), // docs + module_ptr, // pass to functions as "self" + PYTHON_API_VERSION // API version + ); +} + +Module ExtensionModuleBase::module( void ) const +{ + return Module( m_full_module_name ); +} + +Dict ExtensionModuleBase::moduleDictionary( void ) const +{ + return module().getDict(); +} + +Object ExtensionModuleBase::moduleObject( void ) const +{ + return Object( m_module ); +} + +//================================================================================ +// +// Implementation of PythonType +// +//================================================================================ +extern "C" +{ + static void standard_dealloc( PyObject *p ); + // + // All the following functions redirect the call from Python + // onto the matching virtual function in PythonExtensionBase + // +#if defined( PYCXX_PYTHON_2TO3 ) + static int print_handler( PyObject *, FILE *, int ); +#endif + static PyObject *getattr_handler( PyObject *, char * ); + static int setattr_handler( PyObject *, char *, PyObject * ); + static PyObject *getattro_handler( PyObject *, PyObject * ); + static int setattro_handler( PyObject *, PyObject *, PyObject * ); +#if defined( PYCXX_PYTHON_2TO3 ) + static int compare_handler( PyObject *, PyObject * ); +#endif + static PyObject *rich_compare_handler( PyObject *, PyObject *, int ); + static PyObject *repr_handler( PyObject * ); + static PyObject *str_handler( PyObject * ); + static long hash_handler( PyObject * ); + static PyObject *call_handler( PyObject *, PyObject *, PyObject * ); + static PyObject *iter_handler( PyObject * ); + static PyObject *iternext_handler( PyObject * ); + + // Sequence methods + static Py_ssize_t sequence_length_handler( PyObject * ); + static PyObject *sequence_concat_handler( PyObject *,PyObject * ); + static PyObject *sequence_repeat_handler( PyObject *, Py_ssize_t ); + static PyObject *sequence_item_handler( PyObject *, Py_ssize_t ); + static PyObject *sequence_slice_handler( PyObject *, Py_ssize_t, Py_ssize_t ); + static int sequence_ass_item_handler( PyObject *, Py_ssize_t, PyObject * ); + static int sequence_ass_slice_handler( PyObject *, Py_ssize_t, Py_ssize_t, PyObject * ); + + static PyObject *sequence_inplace_concat_handler( PyObject *, PyObject * ); + static PyObject *sequence_inplace_repeat_handler( PyObject *, Py_ssize_t ); + + static int sequence_contains_handler( PyObject *, PyObject * ); + + // Mapping + static Py_ssize_t mapping_length_handler( PyObject * ); + static PyObject *mapping_subscript_handler( PyObject *, PyObject * ); + static int mapping_ass_subscript_handler( PyObject *, PyObject *, PyObject * ); + + // Numeric methods + static int number_nonzero_handler( PyObject * ); + static PyObject *number_negative_handler( PyObject * ); + static PyObject *number_positive_handler( PyObject * ); + static PyObject *number_absolute_handler( PyObject * ); + static PyObject *number_invert_handler( PyObject * ); + static PyObject *number_int_handler( PyObject * ); + static PyObject *number_float_handler( PyObject * ); + static PyObject *number_long_handler( PyObject * ); + static PyObject *number_oct_handler( PyObject * ); + static PyObject *number_hex_handler( PyObject * ); + static PyObject *number_add_handler( PyObject *, PyObject * ); + static PyObject *number_subtract_handler( PyObject *, PyObject * ); + static PyObject *number_multiply_handler( PyObject *, PyObject * ); + static PyObject *number_divide_handler( PyObject *, PyObject * ); + static PyObject *number_remainder_handler( PyObject *, PyObject * ); + static PyObject *number_divmod_handler( PyObject *, PyObject * ); + static PyObject *number_lshift_handler( PyObject *, PyObject * ); + static PyObject *number_rshift_handler( PyObject *, PyObject * ); + static PyObject *number_and_handler( PyObject *, PyObject * ); + static PyObject *number_xor_handler( PyObject *, PyObject * ); + static PyObject *number_or_handler( PyObject *, PyObject * ); + static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); + + // Buffer + static Py_ssize_t buffer_getreadbuffer_handler( PyObject *, Py_ssize_t, void ** ); + static Py_ssize_t buffer_getwritebuffer_handler( PyObject *, Py_ssize_t, void ** ); + static Py_ssize_t buffer_getsegcount_handler( PyObject *, Py_ssize_t * ); +} + +extern "C" void standard_dealloc( PyObject *p ) +{ + PyMem_DEL( p ); +} + +bool PythonType::readyType() +{ + return PyType_Ready( table ) >= 0; +} + +PythonType &PythonType::supportSequenceType( int methods_to_support ) +{ + if( !sequence_table ) + { + sequence_table = new PySequenceMethods; + memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0 + table->tp_as_sequence = sequence_table; + if( methods_to_support&support_sequence_length ) + { + sequence_table->sq_length = sequence_length_handler; + } + if( methods_to_support&support_sequence_repeat ) + { + sequence_table->sq_repeat = sequence_repeat_handler; + } + if( methods_to_support&support_sequence_item ) + { + sequence_table->sq_item = sequence_item_handler; + } + if( methods_to_support&support_sequence_slice ) + { + sequence_table->sq_slice = sequence_slice_handler; + } + if( methods_to_support&support_sequence_concat ) + { + sequence_table->sq_concat = sequence_concat_handler; + } + if( methods_to_support&support_sequence_ass_item ) + { + sequence_table->sq_ass_item = sequence_ass_item_handler; + } + if( methods_to_support&support_sequence_ass_slice ) + { + sequence_table->sq_ass_slice = sequence_ass_slice_handler; + } + if( methods_to_support&support_sequence_inplace_concat ) + { + sequence_table->sq_inplace_concat = sequence_inplace_concat_handler; + } + if( methods_to_support&support_sequence_inplace_repeat ) + { + sequence_table->sq_inplace_repeat = sequence_inplace_repeat_handler; + } + if( methods_to_support&support_sequence_contains ) + { + sequence_table->sq_contains = sequence_contains_handler; + } + } + return *this; +} + + +PythonType &PythonType::supportMappingType( int methods_to_support ) +{ + if( !mapping_table ) + { + mapping_table = new PyMappingMethods; + memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0 + table->tp_as_mapping = mapping_table; + + if( methods_to_support&support_mapping_length ) + { + mapping_table->mp_length = mapping_length_handler; + } + if( methods_to_support&support_mapping_subscript ) + { + mapping_table->mp_subscript = mapping_subscript_handler; + } + if( methods_to_support&support_mapping_ass_subscript ) + { + mapping_table->mp_ass_subscript = mapping_ass_subscript_handler; + } + } + return *this; +} + +PythonType &PythonType::supportNumberType( int methods_to_support ) +{ + if( !number_table ) + { + number_table = new PyNumberMethods; + memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0 + table->tp_as_number = number_table; + number_table->nb_coerce = 0; + + if( methods_to_support&support_number_add ) + { + number_table->nb_add = number_add_handler; + } + if( methods_to_support&support_number_subtract ) + { + number_table->nb_subtract = number_subtract_handler; + } + if( methods_to_support&support_number_multiply ) + { + number_table->nb_multiply = number_multiply_handler; + } + if( methods_to_support&support_number_divide ) + { + number_table->nb_divide = number_divide_handler; + } + if( methods_to_support&support_number_remainder ) + { + number_table->nb_remainder = number_remainder_handler; + } + if( methods_to_support&support_number_divmod ) + { + number_table->nb_divmod = number_divmod_handler; + } + if( methods_to_support&support_number_power ) + { + number_table->nb_power = number_power_handler; + } + if( methods_to_support&support_number_negative ) + { + number_table->nb_negative = number_negative_handler; + } + if( methods_to_support&support_number_positive ) + { + number_table->nb_positive = number_positive_handler; + } + if( methods_to_support&support_number_absolute ) + { + number_table->nb_absolute = number_absolute_handler; + } + if( methods_to_support&support_number_nonzero ) + { + number_table->nb_nonzero = number_nonzero_handler; + } + if( methods_to_support&support_number_invert ) + { + number_table->nb_invert = number_invert_handler; + } + if( methods_to_support&support_number_lshift ) + { + number_table->nb_lshift = number_lshift_handler; + } + if( methods_to_support&support_number_rshift ) + { + number_table->nb_rshift = number_rshift_handler; + } + if( methods_to_support&support_number_and ) + { + number_table->nb_and = number_and_handler; + } + if( methods_to_support&support_number_xor ) + { + number_table->nb_xor = number_xor_handler; + } + if( methods_to_support&support_number_or ) + { + number_table->nb_or = number_or_handler; + } + if( methods_to_support&support_number_int ) + { + number_table->nb_int = number_int_handler; + } + if( methods_to_support&support_number_long ) + { + number_table->nb_long = number_long_handler; + } + if( methods_to_support&support_number_float ) + { + number_table->nb_float = number_float_handler; + } + if( methods_to_support&support_number_oct ) + { + number_table->nb_oct = number_oct_handler; + } + if( methods_to_support&support_number_hex ) + { + number_table->nb_hex = number_hex_handler; + } + } + return *this; +} + +PythonType &PythonType::supportBufferType( int methods_to_support ) +{ + if( !buffer_table ) + { + buffer_table = new PyBufferProcs; + memset( buffer_table, 0, sizeof( PyBufferProcs ) ); // ensure new fields are 0 + table->tp_as_buffer = buffer_table; + + if( methods_to_support&support_buffer_getreadbuffer ) + { + buffer_table->bf_getreadbuffer = buffer_getreadbuffer_handler; + } + if( methods_to_support&support_buffer_getwritebuffer ) + { + buffer_table->bf_getwritebuffer = buffer_getwritebuffer_handler; + } + if( methods_to_support&support_buffer_getsegcount ) + { + buffer_table->bf_getsegcount = buffer_getsegcount_handler; + } + } + return *this; +} + +// +// if you define add methods that you hook. Use the hook_XXX to choice what to hook. +// +PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) +: table( new PyTypeObject ) +, sequence_table( NULL ) +, mapping_table( NULL ) +, number_table( NULL ) +, buffer_table( NULL ) +{ + // PyTypeObject is defined in <python-sources>/Include/object.h + + memset( table, 0, sizeof( PyTypeObject ) ); // ensure new fields are 0 + *reinterpret_cast<PyObject *>( table ) = py_object_initializer; + table->ob_type = _Type_Type(); + table->ob_size = 0; + + table->tp_name = const_cast<char *>( default_name ); + table->tp_basicsize = basic_size; + table->tp_itemsize = itemsize; + + // Methods to implement standard operations + table->tp_dealloc = (destructor)standard_dealloc; + table->tp_print = 0; + table->tp_getattr = 0; + table->tp_setattr = 0; + table->tp_compare = 0; + table->tp_repr = 0; + + // Method suites for standard classes + table->tp_as_number = 0; + table->tp_as_sequence = 0; + table->tp_as_mapping = 0; + + // More standard operations (here for binary compatibility) + table->tp_hash = 0; + table->tp_call = 0; + table->tp_str = 0; + table->tp_getattro = 0; + table->tp_setattro = 0; + + // Functions to access object as input/output buffer + table->tp_as_buffer = 0; + + // Flags to define presence of optional/expanded features + table->tp_flags = Py_TPFLAGS_DEFAULT; + + // Documentation string + table->tp_doc = 0; + +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 0) + table->tp_traverse = 0L; + + // delete references to contained objects + table->tp_clear = 0L; +#else + table->tp_xxx5 = 0L; + table->tp_xxx6 = 0L; +#endif +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) + // first defined in 2.1 + table->tp_richcompare = 0L; + // weak reference enabler + table->tp_weaklistoffset = 0L; +#else + table->tp_xxx7 = 0L; + table->tp_xxx8 = 0L; +#endif +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 2) + // first defined in 2.3 + // Iterators + table->tp_iter = 0L; + table->tp_iternext = 0L; +#endif +#ifdef COUNT_ALLOCS + table->tp_alloc = 0; + table->tp_free = 0; + table->tp_maxalloc = 0; + table->tp_next = 0; +#endif +} + +PythonType::~PythonType() +{ + delete table; + delete sequence_table; + delete mapping_table; + delete number_table; + delete buffer_table; +} + +PyTypeObject *PythonType::type_object() const +{ + return table; +} + +PythonType &PythonType::name( const char *nam ) +{ + table->tp_name = const_cast<char *>( nam ); + return *this; +} + +const char *PythonType::getName() const +{ + return table->tp_name; +} + +PythonType &PythonType::doc( const char *d ) +{ + table->tp_doc = const_cast<char *>( d ); + return *this; +} + +const char *PythonType::getDoc() const +{ + return table->tp_doc; +} + +PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) +{ + table->tp_dealloc = tp_dealloc; + return *this; +} + +PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) +{ + table->tp_init = tp_init; + return *this; +} + +PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) +{ + table->tp_new = tp_new; + return *this; +} + +PythonType &PythonType::set_methods( PyMethodDef *methods ) +{ + table->tp_methods = methods; + return *this; +} + +PythonType &PythonType::supportClass() +{ + table->tp_flags |= Py_TPFLAGS_BASETYPE; + return *this; +} + +PythonType &PythonType::dealloc( void( *f )( PyObject * )) +{ + table->tp_dealloc = f; + return *this; +} + +#if defined( PYCXX_PYTHON_2TO3 ) +PythonType &PythonType::supportPrint() +{ + table->tp_print = print_handler; + return *this; +} +#endif + +PythonType &PythonType::supportGetattr() +{ + table->tp_getattr = getattr_handler; + return *this; +} + +PythonType &PythonType::supportSetattr() +{ + table->tp_setattr = setattr_handler; + return *this; +} + +PythonType &PythonType::supportGetattro() +{ + table->tp_getattro = getattro_handler; + return *this; +} + +PythonType &PythonType::supportSetattro() +{ + table->tp_setattro = setattro_handler; + return *this; +} + +#if defined( PYCXX_PYTHON_2TO3 ) +PythonType &PythonType::supportCompare() +{ + table->tp_compare = compare_handler; + return *this; +} +#endif + +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) +PythonType &PythonType::supportRichCompare() +{ + table->tp_richcompare = rich_compare_handler; + return *this; +} +#endif + +PythonType &PythonType::supportRepr() +{ + table->tp_repr = repr_handler; + return *this; +} + +PythonType &PythonType::supportStr() +{ + table->tp_str = str_handler; + return *this; +} + +PythonType &PythonType::supportHash() +{ + table->tp_hash = hash_handler; + return *this; +} + +PythonType &PythonType::supportCall() +{ + table->tp_call = call_handler; + return *this; +} + +PythonType &PythonType::supportIter( int methods_to_support ) +{ + if( methods_to_support&support_iter_iter ) + { + table->tp_iter = iter_handler; + } + if( methods_to_support&support_iter_iternext ) + { + table->tp_iternext = iternext_handler; + } + return *this; +} + +//-------------------------------------------------------------------------------- +// +// Handlers +// +//-------------------------------------------------------------------------------- +PythonExtensionBase *getPythonExtensionBase( PyObject *self ) +{ + if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE ) + { + PythonClassInstance *instance = reinterpret_cast<PythonClassInstance *>( self ); + return instance->m_pycxx_object; + } + else + { + return static_cast<PythonExtensionBase *>( self ); + } +} + + +#if defined( PYCXX_PYTHON_2TO3 ) +extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->print( fp, flags ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} +#endif + +extern "C" PyObject *getattr_handler( PyObject *self, char *name ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->getattr( name ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->setattr( name, Object( value ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *getattro_handler( PyObject *self, PyObject *name ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->getattro( String( name ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->setattro( String( name ), Object( value ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +#if defined( PYCXX_PYTHON_2TO3 ) +extern "C" int compare_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->compare( Object( other ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} +#endif + +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) +extern "C" PyObject *rich_compare_handler( PyObject *self, PyObject *other, int op ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->rich_compare( Object( other ), op ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} +#endif + +extern "C" PyObject *repr_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->repr() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *str_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->str() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" long hash_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->hash(); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + if( kw != NULL ) + return new_reference_to( p->call( Object( args ), Object( kw ) ) ); + else + return new_reference_to( p->call( Object( args ), Object() ) ); + } + + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *iter_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->iter() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *iternext_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->iternext(); // might be a NULL ptr on end of iteration + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +// Sequence methods +extern "C" Py_ssize_t sequence_length_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_length(); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *sequence_concat_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_concat( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_repeat_handler( PyObject *self, Py_ssize_t count ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_repeat( count ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_item_handler( PyObject *self, Py_ssize_t index ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_item( index ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_slice( first, last ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_ass_item( index, Object( value ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" int sequence_ass_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_ass_slice( first, last, Object( value ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *sequence_inplace_concat_handler( PyObject *self, PyObject *o2 ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_inplace_concat( Object( o2 ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_inplace_repeat_handler( PyObject *self, Py_ssize_t count ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_inplace_repeat( count ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int sequence_contains_handler( PyObject *self, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_contains( Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +// Mapping +extern "C" Py_ssize_t mapping_length_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->mapping_length(); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *mapping_subscript_handler( PyObject *self, PyObject *key ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->mapping_subscript( Object( key ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->mapping_ass_subscript( Object( key ), Object( value ) ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +// Number +extern "C" int number_nonzero_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->number_nonzero(); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" PyObject *number_negative_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_negative() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_positive_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_positive() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_absolute_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_absolute() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_invert_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_invert() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_int_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_int() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_float_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_float() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_long_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_long() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_oct_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_oct() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_hex_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_hex() ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_add( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_subtract( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_multiply( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_divide_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_divide( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_remainder( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_divmod( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_lshift( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_rshift( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_and( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_xor( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_or( Object( other ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_power( Object( x1 ), Object( x2 ) ) ); + } + catch( BaseException &) + { + return NULL; // indicate error + } +} + +// Buffer +extern "C" Py_ssize_t buffer_getreadbuffer_handler( PyObject *self, Py_ssize_t index, void **pp ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->buffer_getreadbuffer( index, pp ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" Py_ssize_t buffer_getwritebuffer_handler( PyObject *self, Py_ssize_t index, void **pp ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->buffer_getwritebuffer( index, pp ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +extern "C" Py_ssize_t buffer_getsegcount_handler( PyObject *self, Py_ssize_t *count ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->buffer_getsegcount( count ); + } + catch( BaseException &) + { + return -1; // indicate error + } +} + +//================================================================================ +// +// Implementation of PythonExtensionBase +// +//================================================================================ +#define missing_method( method ) \ + throw RuntimeError( "Extension object missing implement of " #method ); + +PythonExtensionBase::PythonExtensionBase() +{ + ob_refcnt = 0; +} + +PythonExtensionBase::~PythonExtensionBase() +{ + assert( ob_refcnt == 0 ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name ) +{ + TupleN args; + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1 ) +{ + TupleN args( arg1 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2 ) +{ + TupleN args( arg1, arg2 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3 ) +{ + TupleN args( arg1, arg2, arg3 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4 ) +{ + TupleN args( arg1, arg2, arg3, arg4 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8, const Object &arg9 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ); + return self().callMemberFunction( fn_name, args ); +} + +void PythonExtensionBase::reinit( Tuple &/*args*/, Dict &/*kwds*/ ) +{ + throw RuntimeError( "Must not call __init__ twice on this class" ); +} + +Object PythonExtensionBase::genericGetAttro( const String &name ) +{ + return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); +} + +int PythonExtensionBase::genericSetAttro( const String &name, const Object &value ) +{ + return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); +} + +int PythonExtensionBase::print( FILE *, int ) +{ + missing_method( print ); +} + +Object PythonExtensionBase::getattr( const char * ) +{ + missing_method( getattr ); +} + +int PythonExtensionBase::setattr( const char *, const Object &) +{ + missing_method( setattr ); +} + +Object PythonExtensionBase::getattro( const String &name ) +{ + return genericGetAttro( name ); +} + +int PythonExtensionBase::setattro( const String &name, const Object &value ) +{ + return genericSetAttro( name, value ); +} + +int PythonExtensionBase::compare( const Object &) +{ + missing_method( compare ); +} + +#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) +Object PythonExtensionBase::rich_compare( const Object &, int /*op*/ ) +{ + missing_method( rich_compare ); +} + +#endif +Object PythonExtensionBase::repr() +{ + missing_method( repr ); +} + +Object PythonExtensionBase::str() +{ + missing_method( str ); +} + +long PythonExtensionBase::hash() +{ + missing_method( hash ); +} + +Object PythonExtensionBase::call( const Object &, const Object &) +{ + missing_method( call ); +} + +Object PythonExtensionBase::iter() +{ + missing_method( iter ); +} + +PyObject *PythonExtensionBase::iternext() +{ + missing_method( iternext ); +} + +// Sequence methods +PyCxx_ssize_t PythonExtensionBase::sequence_length() +{ + missing_method( sequence_length ); +} + +Object PythonExtensionBase::sequence_concat( const Object &) +{ + missing_method( sequence_concat ); +} + +Object PythonExtensionBase::sequence_repeat( Py_ssize_t ) +{ + missing_method( sequence_repeat ); +} + +Object PythonExtensionBase::sequence_item( Py_ssize_t ) +{ + missing_method( sequence_item ); +} + +Object PythonExtensionBase::sequence_slice( Py_ssize_t, Py_ssize_t ) +{ + missing_method( sequence_slice ); +} + +int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Object &) +{ + missing_method( sequence_ass_item ); +} + +int PythonExtensionBase::sequence_ass_slice( Py_ssize_t, Py_ssize_t, const Object &) +{ + missing_method( sequence_ass_slice ); +} + +Object PythonExtensionBase::sequence_inplace_concat( const Object & ) +{ + missing_method( sequence_inplace_concat ); +} + +Object PythonExtensionBase::sequence_inplace_repeat( Py_ssize_t ) +{ + missing_method( sequence_inplace_repeat ); +} + +int PythonExtensionBase::sequence_contains( const Object & ) +{ + missing_method( sequence_contains ); +} + +// Mapping +Sequence::size_type PythonExtensionBase::mapping_length() +{ + missing_method( mapping_length ); +} + +Object PythonExtensionBase::mapping_subscript( const Object &) +{ + missing_method( mapping_subscript ); +} + +int PythonExtensionBase::mapping_ass_subscript( const Object &, const Object &) +{ + missing_method( mapping_ass_subscript ); +} + +// Number +int PythonExtensionBase::number_nonzero() +{ + missing_method( number_nonzero ); +} + +Object PythonExtensionBase::number_negative() +{ + missing_method( number_negative ); +} + +Object PythonExtensionBase::number_positive() +{ + missing_method( number_positive ); +} + +Object PythonExtensionBase::number_absolute() +{ + missing_method( number_absolute ); +} + +Object PythonExtensionBase::number_invert() +{ + missing_method( number_invert ); +} + +Object PythonExtensionBase::number_int() +{ + missing_method( number_int ); +} + +Object PythonExtensionBase::number_float() +{ + missing_method( number_float ); +} + +Object PythonExtensionBase::number_long() +{ + missing_method( number_long ); +} + +Object PythonExtensionBase::number_oct() +{ + missing_method( number_oct ); +} + +Object PythonExtensionBase::number_hex() +{ + missing_method( number_hex ); +} + +Object PythonExtensionBase::number_add( const Object &) +{ + missing_method( number_add ); +} + +Object PythonExtensionBase::number_subtract( const Object &) +{ + missing_method( number_subtract ); +} + +Object PythonExtensionBase::number_multiply( const Object &) +{ + missing_method( number_multiply ); +} + +Object PythonExtensionBase::number_divide( const Object &) +{ + missing_method( number_divide ); +} + +Object PythonExtensionBase::number_remainder( const Object &) +{ + missing_method( number_remainder ); +} + +Object PythonExtensionBase::number_divmod( const Object &) +{ + missing_method( number_divmod ); +} + +Object PythonExtensionBase::number_lshift( const Object &) +{ + missing_method( number_lshift ); +} + +Object PythonExtensionBase::number_rshift( const Object &) +{ + missing_method( number_rshift ); +} + +Object PythonExtensionBase::number_and( const Object &) +{ + missing_method( number_and ); +} + +Object PythonExtensionBase::number_xor( const Object &) +{ + missing_method( number_xor ); +} + +Object PythonExtensionBase::number_or( const Object &) +{ + missing_method( number_or ); +} + +Object PythonExtensionBase::number_power( const Object &, const Object &) +{ + missing_method( number_power ); +} + +// Buffer +Py_ssize_t PythonExtensionBase::buffer_getreadbuffer( Py_ssize_t, void** ) +{ + missing_method( buffer_getreadbuffer ); +} + +Py_ssize_t PythonExtensionBase::buffer_getwritebuffer( Py_ssize_t, void** ) +{ + missing_method( buffer_getwritebuffer ); +} + +Py_ssize_t PythonExtensionBase::buffer_getsegcount( Py_ssize_t* ) +{ + missing_method( buffer_getsegcount ); +} + +//-------------------------------------------------------------------------------- +// +// Method call handlers for +// PythonExtensionBase +// ExtensionModuleBase +// +//-------------------------------------------------------------------------------- +extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + + Object result( self->invoke_method_noargs( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ) ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } +} + +extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + Tuple args( _args ); + + Object result + ( + self->invoke_method_varargs + ( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), + args + ) + ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } +} + +extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + + Tuple args( _args ); + + if( _keywords == NULL ) + { + Dict keywords; // pass an empty dict + + Object result + ( + self->invoke_method_keyword + ( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), + args, + keywords + ) + ); + + return new_reference_to( result.ptr() ); + } + else + { + Dict keywords( _keywords ); // make dict + + Object result + ( + self->invoke_method_keyword + ( + PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), + args, + keywords + ) + ); + + return new_reference_to( result.ptr() ); + } + } + catch( BaseException & ) + { + return 0; + } +} + + +extern "C" void do_not_dealloc( void * ) +{} + +//-------------------------------------------------------------------------------- +// +// ExtensionExceptionType +// +//-------------------------------------------------------------------------------- +ExtensionExceptionType::ExtensionExceptionType() +: Object() +{ +} + +void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name ) +{ + std::string module_name( module.fullName() ); + module_name += "."; + module_name += name; + set( PyErr_NewException( const_cast<char *>( module_name.c_str() ), NULL, NULL ), true ); +} + +void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name, ExtensionExceptionType &parent) +{ + std::string module_name( module.fullName() ); + module_name += "."; + module_name += name; + set( PyErr_NewException( const_cast<char *>( module_name.c_str() ), parent.ptr(), NULL ), true ); +} + +ExtensionExceptionType::~ExtensionExceptionType() +{ +} + +// ------------------------------------------------------------ +// +// BaseException +// +//------------------------------------------------------------ +BaseException::BaseException( ExtensionExceptionType &exception, const std::string &reason ) + : reasonMessage(reason) +{ + PyErr_SetString( exception.ptr(), reason.c_str() ); +} + +BaseException::BaseException( ExtensionExceptionType &exception, Object &reason ) +{ + if (reason.hasAttr("message")) { + reasonMessage = reason.getAttr("message").str(); + } + PyErr_SetObject( exception.ptr(), reason.ptr() ); +} + +BaseException::BaseException( ExtensionExceptionType &exception, PyObject *reason ) +{ + PyErr_SetObject( exception.ptr(), reason ); +} + +BaseException::BaseException( PyObject *exception, Object &reason ) +{ + if (reason.hasAttr("message")) { + reasonMessage = reason.getAttr("message").str(); + } + PyErr_SetObject( exception, reason.ptr() ); +} + +BaseException::BaseException( PyObject *exception, PyObject *reason ) +{ + PyErr_SetObject( exception, reason ); +} + +BaseException::BaseException( PyObject *exception, const std::string &reason ) + : reasonMessage(reason) +{ + PyErr_SetString( exception, reason.c_str() ); +} + +BaseException::BaseException() +{} + +void BaseException::clear() +{ + PyErr_Clear(); +} + +const char* BaseException::what() const noexcept +{ + return reasonMessage.c_str(); +} + +bool BaseException::matches( ExtensionExceptionType &exc ) +// is the exception this specific exception 'exc' +{ + return PyErr_ExceptionMatches( exc.ptr() ) != 0; +} + +} // end of namespace Py diff --git a/contrib/libs/pycxx/Python2/cxx_standard_exceptions.hxx b/contrib/libs/pycxx/Python2/cxx_standard_exceptions.hxx new file mode 100644 index 00000000000..9065b33d80a --- /dev/null +++ b/contrib/libs/pycxx/Python2/cxx_standard_exceptions.hxx @@ -0,0 +1,46 @@ +#if !defined( PYCXX_STANDARD_EXCEPTION ) +#pragma error( "define PYCXX_STANDARD_EXCEPTION before including" ) +#endif + +PYCXX_STANDARD_EXCEPTION( SystemExit, BaseException ) +PYCXX_STANDARD_EXCEPTION( KeyboardInterrupt,BaseException ) +PYCXX_STANDARD_EXCEPTION( GeneratorExit, BaseException ) +#if !defined( PYCXX_6_2_COMPATIBILITY ) +PYCXX_STANDARD_EXCEPTION( Exception, BaseException ) +#endif +PYCXX_STANDARD_EXCEPTION( StopIteration, Exception ) +PYCXX_STANDARD_EXCEPTION( StandardError, Exception ) +PYCXX_STANDARD_EXCEPTION( BufferError, StandardError ) +PYCXX_STANDARD_EXCEPTION( ArithmeticError, StandardError ) +PYCXX_STANDARD_EXCEPTION( FloatingPointError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( OverflowError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( ZeroDivisionError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( AssertionError, StandardError ) +PYCXX_STANDARD_EXCEPTION( AttributeError, StandardError ) +PYCXX_STANDARD_EXCEPTION( EnvironmentError, StandardError ) +PYCXX_STANDARD_EXCEPTION( IOError, EnvironmentError ) +PYCXX_STANDARD_EXCEPTION( OSError, EnvironmentError ) +#ifdef MS_WINDOWS +PYCXX_STANDARD_EXCEPTION( WindowsError, OSError ) +#endif +PYCXX_STANDARD_EXCEPTION( EOFError, StandardError ) +PYCXX_STANDARD_EXCEPTION( ImportError, StandardError ) +PYCXX_STANDARD_EXCEPTION( LookupError, StandardError ) +PYCXX_STANDARD_EXCEPTION( IndexError, LookupError ) +PYCXX_STANDARD_EXCEPTION( KeyError, LookupError ) +PYCXX_STANDARD_EXCEPTION( MemoryError, StandardError ) +PYCXX_STANDARD_EXCEPTION( NameError, StandardError ) +PYCXX_STANDARD_EXCEPTION( UnboundLocalError,NameError ) +PYCXX_STANDARD_EXCEPTION( ReferenceError, StandardError ) +PYCXX_STANDARD_EXCEPTION( RuntimeError, StandardError ) +PYCXX_STANDARD_EXCEPTION( NotImplementedError, RuntimeError ) +PYCXX_STANDARD_EXCEPTION( SyntaxError, StandardError ) +PYCXX_STANDARD_EXCEPTION( IndentationError, SyntaxError ) +PYCXX_STANDARD_EXCEPTION( TabError, IndentationError ) +PYCXX_STANDARD_EXCEPTION( SystemError, StandardError ) +PYCXX_STANDARD_EXCEPTION( TypeError, StandardError ) +PYCXX_STANDARD_EXCEPTION( ValueError, StandardError ) +PYCXX_STANDARD_EXCEPTION( UnicodeError, ValueError ) +PYCXX_STANDARD_EXCEPTION( UnicodeDecodeError, UnicodeError ) +PYCXX_STANDARD_EXCEPTION( UnicodeEncodeError, UnicodeError ) +PYCXX_STANDARD_EXCEPTION( UnicodeTranslateError,UnicodeError ) diff --git a/contrib/libs/pycxx/Python2/cxxextensions.c b/contrib/libs/pycxx/Python2/cxxextensions.c new file mode 100644 index 00000000000..20278664840 --- /dev/null +++ b/contrib/libs/pycxx/Python2/cxxextensions.c @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//---------------------------------------------------------------------------*/ + +#include "../WrapPython.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +PyObject py_object_initializer = {PyObject_HEAD_INIT(0)}; + +#ifdef __cplusplus +} +#endif diff --git a/contrib/libs/pycxx/Python2/cxxsupport.cxx b/contrib/libs/pycxx/Python2/cxxsupport.cxx new file mode 100644 index 00000000000..96891564b75 --- /dev/null +++ b/contrib/libs/pycxx/Python2/cxxsupport.cxx @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#include "../Objects.hxx" +namespace Py { + +Py_UNICODE unicode_null_string[1] = { 0 }; + +Type Object::type () const +{ + return Type (PyObject_Type (p), true); +} + +String Object::str () const +{ + return String (PyObject_Str (p), true); +} + +String Object::repr () const +{ + return String (PyObject_Repr (p), true); +} + +std::string Object::as_string() const +{ + return static_cast<std::string>(str()); +} + +List Object::dir () const + { + return List (PyObject_Dir (p), true); + } + +bool Object::isType (const Type& t) const +{ + return type ().ptr() == t.ptr(); +} + +Char::operator String() const +{ + return String(ptr()); +} + +// TMM: non-member operaters for iterators - see above +// I've also made a bug fix in respect to the cxx code +// (dereffed the left.seq and right.seq comparison) +bool operator==(const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.eql( right ); +} + +bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.neq( right ); +} + +bool operator< (const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.lss( right ); +} + +bool operator> (const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.gtr( right ); +} + +bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.leq( right ); +} + +bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right) +{ + return left.geq( right ); +} + +// now for const_iterator +bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.eql( right ); +} + +bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.neq( right ); +} + +bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.lss( right ); +} + +bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.gtr( right ); +} + +bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.leq( right ); +} + +bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) +{ + return left.geq( right ); +} + +// For mappings: +bool operator==(const Mapping::iterator& left, const Mapping::iterator& right) +{ + return left.eql( right ); +} + +bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right) +{ + return left.neq( right ); +} + +// now for const_iterator +bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right) +{ + return left.eql( right ); +} + +bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right) +{ + return left.neq( right ); +} + +// TMM: 31May'01 - Added the #ifndef so I can exclude iostreams. +#ifndef CXX_NO_IOSTREAMS +// output + +std::ostream& operator<< (std::ostream& os, const Object& ob) +{ + return (os << static_cast<std::string>(ob.str())); +} +#endif + +} // Py diff --git a/contrib/libs/pycxx/Python3/Config.hxx b/contrib/libs/pycxx/Python3/Config.hxx new file mode 100755 index 00000000000..10c611fb535 --- /dev/null +++ b/contrib/libs/pycxx/Python3/Config.hxx @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __PyCXX_config_hh__ +#define __PyCXX_config_hh__ + +// +// Microsoft VC++ 6.0 has no traits +// +#if defined( _MSC_VER ) + +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 + +#elif defined( __GNUC__ ) +# if __GNUC__ >= 3 +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 +# else +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 0 +#endif + +// +// Assume all other compilers do +// +#else + +// Macros to deal with deficiencies in compilers +# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 +#endif + +#if STANDARD_LIBRARY_HAS_ITERATOR_TRAITS +# define random_access_iterator_parent(itemtype) std::iterator<std::random_access_iterator_tag,itemtype,int> +#else +# define random_access_iterator_parent(itemtype) std::random_access_iterator<itemtype, int> +#endif + +// +// Which C++ standard is in use? +// +#if defined( _MSC_VER ) +# if _MSC_VER <= 1200 +// MSVC++ 6.0 +# define PYCXX_ISO_CPP_LIB 0 +# define STR_STREAM <strstream> +# define TEMPLATE_TYPENAME class +# else +# define PYCXX_ISO_CPP_LIB 1 +# define STR_STREAM <sstream> +# define TEMPLATE_TYPENAME typename +# endif +#elif defined( __GNUC__ ) +# if __GNUC__ >= 3 +# define PYCXX_ISO_CPP_LIB 1 +# define STR_STREAM <sstream> +# define TEMPLATE_TYPENAME typename +# else +# define PYCXX_ISO_CPP_LIB 0 +# define STR_STREAM <strstream> +# define TEMPLATE_TYPENAME class +# endif +#endif + +#if PYCXX_ISO_CPP_LIB +# define STR_STREAM <sstream> +# define OSTRSTREAM ostringstream +# define EXPLICIT_TYPENAME typename +# define EXPLICIT_CLASS class +# define TEMPLATE_TYPENAME typename +#else +# define STR_STREAM <strstream> +# define OSTRSTREAM ostrstream +# define EXPLICIT_TYPENAME +# define EXPLICIT_CLASS +# define TEMPLATE_TYPENAME class +#endif + +// before 3.2 Py_hash_t was missing +#ifndef PY_MAJOR_VERSION +#error not defined PY_MAJOR_VERSION +#endif +#if PY_MINOR_VERSION < 2 +typedef long int Py_hash_t; +#endif +#endif // __PyCXX_config_hh__ diff --git a/contrib/libs/pycxx/Python3/CxxDebug.hxx b/contrib/libs/pycxx/Python3/CxxDebug.hxx new file mode 100755 index 00000000000..b646ffdd9af --- /dev/null +++ b/contrib/libs/pycxx/Python3/CxxDebug.hxx @@ -0,0 +1,17 @@ +// +// CxxDebug.hxx +// +// Copyright (c) 2008 Barry A. Scott +// +#ifndef __CXX_Debug_hxx +#define __CXX_Debug_hxx + +// +// Functions useful when debugging PyCXX +// +#ifdef PYCXX_DEBUG +extern void bpt(); +extern void printRefCount( PyObject *obj ); +#endif + +#endif diff --git a/contrib/libs/pycxx/Python3/Exception.hxx b/contrib/libs/pycxx/Python3/Exception.hxx new file mode 100755 index 00000000000..269e5ac97e1 --- /dev/null +++ b/contrib/libs/pycxx/Python3/Exception.hxx @@ -0,0 +1,207 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Exception_h +#define __CXX_Exception_h + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "../Config.hxx" +#include "../CxxDebug.hxx" +#include "../IndirectPythonInterface.hxx" + +#include <string> +#include <iostream> + +// This mimics the Python structure, in order to minimize confusion +namespace Py +{ + class ExtensionExceptionType; + + class Object; + + class BaseException + { + public: + BaseException( ExtensionExceptionType &exception, const std::string &reason ); + BaseException( ExtensionExceptionType &exception, Object &reason ); + BaseException( ExtensionExceptionType &exception, PyObject *reason ); + BaseException( PyObject *exception, Object &reason ); + BaseException( PyObject *exception, PyObject *reason ); + BaseException( PyObject *exception, const std::string &reason ); + explicit BaseException(); + + void clear(); // clear the error + + virtual const char* what() const noexcept; + + // is the exception this specific exception 'exc' + bool matches( ExtensionExceptionType &exc ); + + private: + std::string reasonMessage; + }; + + // for user defined exceptions to be made know to pycxx + typedef void (*throw_exception_func_t)( PyObject* exc ); + void addPythonException( ExtensionExceptionType &py_exc_type, throw_exception_func_t throw_func ); + +#if defined( PYCXX_6_2_COMPATIBILITY ) + class Exception : public BaseException + { + public: + Exception( ExtensionExceptionType &exception, const std::string &reason ) + : BaseException( exception, reason ) + {} + + Exception( ExtensionExceptionType &exception, Object &reason ) + : BaseException( exception, reason ) + {} + + Exception( ExtensionExceptionType &exception, PyObject *reason ) + : BaseException( exception, reason ) + {} + + Exception( PyObject *exception, Object &reason ) + : BaseException ( exception, reason ) + {} + + Exception( PyObject *exception, PyObject *reason ) + : BaseException ( exception, reason ) + {} + + Exception( PyObject *exception, const std::string &reason ) + : BaseException( exception, reason ) + {} + + explicit Exception() + : BaseException() + {} + }; +#endif + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + class eclass : public bclass \ + { \ + public: \ + eclass( const std::string &reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( const char *reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + { } \ + eclass( PyObject *, const std::string &reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *, const char *reason ) \ + : bclass( _Exc_##eclass(), reason ) \ + , reason(reason) \ + { } \ + eclass( PyObject *exception, PyObject *reason ) \ + : bclass( exception, reason ) \ + { } \ + eclass() : bclass() {} \ + static void throwFunc(const std::string &reason) { throw eclass(reason); } \ + static void throwFuncObj(PyObject *exception) { throw eclass(exception); } \ + static PyObject *exceptionType() { return _Exc_##eclass(); } \ + ~eclass() {} \ + private: \ + std::string reason; \ + }; + +#include "cxx_standard_exceptions.hxx" + +#undef PYCXX_STANDARD_EXCEPTION + +#define PYCXX_USER_EXCEPTION_STR_ARG( uclass ) \ +class uclass : public Py::BaseException \ +{ \ +public: \ + uclass( const std::string &reason ) \ + : Py::BaseException( m_error, reason ) \ + { } \ + ~uclass() {} \ + static void init( Py::ExtensionModuleBase &module ) \ + { \ + m_error.init( module, #uclass ); \ + Py::addPythonException( m_error, throwFunc ); \ + Py::Dict d( module.moduleDictionary() ); \ + d[#uclass] = m_error; \ + } \ +private: \ + uclass() : Py::BaseException() {} \ + static void throwFunc() \ + { \ + throw uclass(); \ + } \ + static Py::ExtensionExceptionType m_error; \ +}; \ +Py::ExtensionExceptionType uclass::m_error; + +#define PYCXX_USER_EXCEPTION_NO_ARG( uclass ) \ +class uclass : public Py::BaseException \ +{ \ +public: \ + uclass() \ + : Py::BaseException() \ + { } \ + ~uclass() {} \ + static void init( Py::ExtensionModuleBase &module ) \ + { \ + m_error.init( module, #uclass ); \ + Py::addPythonException( m_error, throwFunc ); \ + Py::Dict d( module.moduleDictionary() ); \ + d[#uclass] = m_error; \ + } \ +private: \ + static void throwFunc() \ + { \ + throw uclass(); \ + } \ + static Py::ExtensionExceptionType m_error; \ +}; \ +Py::ExtensionExceptionType uclass::m_error; + +}// Py + +#endif diff --git a/contrib/libs/pycxx/Python3/ExtensionModule.hxx b/contrib/libs/pycxx/Python3/ExtensionModule.hxx new file mode 100755 index 00000000000..3274d939145 --- /dev/null +++ b/contrib/libs/pycxx/Python3/ExtensionModule.hxx @@ -0,0 +1,206 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionModule__h +#define __CXX_ExtensionModule__h + +namespace Py +{ + class ExtensionModuleBase + { + public: + ExtensionModuleBase( const char *name ); + virtual ~ExtensionModuleBase(); + + Module module( void ) const; // only valid after initialize() has been called + Dict moduleDictionary( void ) const; // only valid after initialize() has been called + + virtual Object invoke_method_noargs( void *method_def ) = 0; + virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0; + virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0; + + const std::string &name() const; + const std::string &fullName() const; + + // what is returned from PyInit_<module> function + Object moduleObject( void ) const; + + protected: + // Initialize the module + void initialize( const char *module_doc ); + + const std::string m_module_name; + const std::string m_full_module_name; + MethodTable m_method_table; + PyModuleDef m_module_def; + PyObject *m_module; + + private: + // + // prevent the compiler generating these unwanted functions + // + ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented + void operator=( const ExtensionModuleBase & ); //unimplemented + }; + + // Note: Python calls noargs as varargs buts args==NULL + extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ); + extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ); + extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ); + + template<TEMPLATE_TYPENAME T> + class ExtensionModule : public ExtensionModuleBase + { + public: + ExtensionModule( const char *name ) + : ExtensionModuleBase( name ) + {} + virtual ~ExtensionModule() + {} + + protected: + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + typedef std::map<std::string, MethodDefExt<T> *> method_map_t; + + static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc ); + } + + static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc ); + } + + static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) + { + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc ); + } + + void initialize( const char *module_doc="" ) + { + ExtensionModuleBase::initialize( module_doc ); + Dict dict( moduleDictionary() ); + + // + // put each of the methods into the modules dictionary + // so that we get called back at the function in T. + // + method_map_t &mm = methods(); + EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin(); + EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); + for ( ; i != i_end; ++i ) + { + MethodDefExt<T> *method_def = (*i).second; + + static PyObject *self = PyCapsule_New( this, NULL, NULL ); + + Tuple args( 2 ); + args[0] = Object( self, true ); + args[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true ); + + assert( m_module != NULL ); + PyObject *func = PyCFunction_NewEx + ( + &method_def->ext_meth_def, + new_reference_to( args ), + m_module + ); + + method_def->py_method = Object( func, true ); + + dict[ (*i).first ] = method_def->py_method; + } + } + + protected: // Tom Malcolmson reports that derived classes need access to these + static method_map_t &methods( void ) + { + static method_map_t *map_of_methods = NULL; + if( map_of_methods == NULL ) + map_of_methods = new method_map_t; + + return *map_of_methods; + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_noargs( void *method_def ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_noargs_function)(); + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_varargs( void *method_def, const Tuple &args ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_varargs_function)( args ); + } + + // this invoke function must be called from within a try catch block + virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords ) + { + // cast up to the derived class, method_def and call + T *self = static_cast<T *>( this ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( method_def ); + + return (self->*meth_def->ext_keyword_function)( args, keywords ); + } + + private: + // + // prevent the compiler generating these unwanted functions + // + ExtensionModule( const ExtensionModule<T> & ); //unimplemented + void operator=( const ExtensionModule<T> & ); //unimplemented + }; +} // Namespace Py + + +// End of __CXX_ExtensionModule__h +#endif diff --git a/contrib/libs/pycxx/Python3/ExtensionOldType.hxx b/contrib/libs/pycxx/Python3/ExtensionOldType.hxx new file mode 100755 index 00000000000..0fa0ebe6c43 --- /dev/null +++ b/contrib/libs/pycxx/Python3/ExtensionOldType.hxx @@ -0,0 +1,402 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionOldType__h +#define __CXX_ExtensionOldType__h + +namespace Py +{ + template<TEMPLATE_TYPENAME T> class PythonExtension + : public PythonExtensionBase + { + public: + static PyTypeObject *type_object() + { + return behaviors().type_object(); + } + + static bool check( PyObject *p ) + { + // is p like me? + return p->ob_type == type_object(); + } + + static bool check( const Object &ob ) + { + return check( ob.ptr() ); + } + + // + // every object needs getattr implemented + // to support methods + // + virtual Object getattr( const char *name ) + { + return getattr_methods( name ); + } + + PyObject *selfPtr() + { + return this; + } + + Object self() + { + return asObject( this ); + } + + protected: + explicit PythonExtension() + : PythonExtensionBase() + { + // every object must support getattr + behaviors().supportGetattr(); + +#ifdef Py_LIMITED_API + behaviors().readyType(); +#endif + + PyObject_Init( this, type_object() ); + } + + virtual ~PythonExtension() + {} + + static PythonType &behaviors() + { + static PythonType* p; + if( p == NULL ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + const char *default_name =( typeid( T ) ).name(); +#else + const char *default_name = "unknown"; +#endif + p = new PythonType( sizeof( T ), 0, default_name ); + p->set_tp_dealloc( extension_object_deallocator ); + } + + return *p; + } + + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + typedef std::map<std::string, MethodDefExt<T> *> method_map_t; + + // support the default attributes, __name__, __doc__ and methods + virtual Object getattr_default( const char *_name ) + { + std::string name( _name ); +#ifndef Py_LIMITED_API + if( name == "__name__" && type_object()->tp_name != NULL ) + { + return Py::String( type_object()->tp_name ); + } + + if( name == "__doc__" && type_object()->tp_doc != NULL ) + { + return Py::String( type_object()->tp_doc ); + } +#endif +// trying to fake out being a class for help() +// else if( name == "__bases__" ) +// { +// return Py::Tuple( 0 ); +// } +// else if( name == "__module__" ) +// { +// return Py::Nothing(); +// } +// else if( name == "__dict__" ) +// { +// return Py::Dict(); +// } + + return getattr_methods( _name ); + } + + // turn a name into function object + virtual Object getattr_methods( const char *_name ) + { + std::string name( _name ); + + method_map_t &mm = methods(); + + // see if name exists and get entry with method + EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.find( name ); + if( i == mm.end() ) + { + if( name == "__methods__" ) + { + List methods; + + i = mm.begin(); + EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); + + for( ; i != i_end; ++i ) + methods.append( String( (*i).first ) ); + + return methods; + } + + throw AttributeError( name ); + } + + MethodDefExt<T> *method_def = i->second; + + Tuple self( 2 ); + + self[0] = Object( this ); + self[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true ); + + PyObject *func = PyCFunction_NewEx( &method_def->ext_meth_def, self.ptr(), NULL ); + + return Object(func, true); + } + + // check that all methods added are unique + static void check_unique_method_name( const char *name ) + { + method_map_t &mm = methods(); + EXPLICIT_TYPENAME method_map_t::const_iterator i; + i = mm.find( name ); + if( i != mm.end() ) + throw AttributeError( name ); + } + + static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc ); + } + + static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc ); + } + + static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) + { + check_unique_method_name( name ); + method_map_t &mm = methods(); + mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc ); + } + + private: + static method_map_t &methods( void ) + { + static method_map_t *map_of_methods = NULL; + if( map_of_methods == NULL ) + map_of_methods = new method_map_t; + + return *map_of_methods; + } + + // Note: Python calls noargs as varargs buts args==NULL + static PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); + + Object result; + + // Adding try & catch in case of STL debug-mode exceptions. + #ifdef _STLP_DEBUG + try + { + result = (self->*meth_def->ext_noargs_function)(); + } + catch( std::__stl_debug_exception ) + { + // throw cxx::RuntimeError( sErrMsg ); + throw RuntimeError( "Error message not set yet." ); + } + #else + result = (self->*meth_def->ext_noargs_function)(); + #endif // _STLP_DEBUG + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); + + Tuple args( _args ); + + Object result; + + // Adding try & catch in case of STL debug-mode exceptions. + #ifdef _STLP_DEBUG + try + { + result = (self->*meth_def->ext_varargs_function)( args ); + } + catch( std::__stl_debug_exception ) + { + throw RuntimeError( "Error message not set yet." ); + } + #else + result = (self->*meth_def->ext_varargs_function)( args ); + #endif // _STLP_DEBUG + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) + { + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + T *self = static_cast<T *>( self_in_cobject ); + MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); + + Tuple args( _args ); + + // _keywords may be NULL so be careful about the way the dict is created + Dict keywords; + if( _keywords != NULL ) + keywords = Dict( _keywords ); + + Object result( ( self->*meth_def->ext_keyword_function )( args, keywords ) ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } + } + + static void extension_object_deallocator( PyObject* t ) + { + delete (T *)( t ); + } + + // + // prevent the compiler generating these unwanted functions + // + explicit PythonExtension( const PythonExtension<T> &other ); + void operator=( const PythonExtension<T> &rhs ); + }; + + // + // ExtensionObject<T> is an Object that will accept only T's. + // + template<TEMPLATE_TYPENAME T> + class ExtensionObject: public Object + { + public: + + explicit ExtensionObject( PyObject *pyob ) + : Object( pyob ) + { + validate(); + } + + ExtensionObject( const ExtensionObject<T> &other ) + : Object( *other ) + { + validate(); + } + + ExtensionObject( const Object &other ) + : Object( *other ) + { + validate(); + } + + ExtensionObject &operator=( const Object &rhs ) + { + return( *this = *rhs ); + } + + ExtensionObject &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return( pyob && T::check( pyob ) ); + } + + // + // Obtain a pointer to the PythonExtension object + // + T *extensionObject( void ) + { + return static_cast<T *>( ptr() ); + } + }; +} // Namespace Py + +// End of __CXX_ExtensionOldType__h +#endif diff --git a/contrib/libs/pycxx/Python3/ExtensionType.hxx b/contrib/libs/pycxx/Python3/ExtensionType.hxx new file mode 100755 index 00000000000..5eea3bb4d44 --- /dev/null +++ b/contrib/libs/pycxx/Python3/ExtensionType.hxx @@ -0,0 +1,428 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionClass__h +#define __CXX_ExtensionClass__h + +#define PYCXX_NOARGS_METHOD_NAME( NAME ) _callNoArgsMethod__##NAME +#define PYCXX_VARARGS_METHOD_NAME( NAME ) _callVarArgsMethod__##NAME +#define PYCXX_KEYWORDS_METHOD_NAME( NAME ) _callKeywordsMethod__##NAME + +#define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Object r( (self->NAME)() ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } +#define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Tuple a( _a ); \ + Py::Object r( (self->NAME)( a ) ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } +#define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \ + static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \ + { \ + try \ + { \ + Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ + CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ + Py::Tuple a( _a ); \ + Py::Dict k; \ + if( _k != NULL ) \ + k = _k; \ + Py::Object r( (self->NAME)( a, k ) ); \ + return Py::new_reference_to( r.ptr() ); \ + } \ + catch( Py::BaseException & ) \ + { \ + return 0; \ + } \ + } + +// need to support METH_STATIC and METH_CLASS + +#define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs ) +#define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs ) +#define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \ + add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs ) + +namespace Py +{ + extern PythonExtensionBase *getPythonExtensionBase( PyObject *self ); + struct PythonClassInstance + { + PyObject_HEAD + PythonExtensionBase *m_pycxx_object; + }; + + class ExtensionClassMethodsTable + { + public: + ExtensionClassMethodsTable() + : m_methods_table( new PyMethodDef[ METHOD_TABLE_SIZE_INCREMENT ] ) + , m_methods_used( 0 ) + , m_methods_size( METHOD_TABLE_SIZE_INCREMENT ) + { + // add the sentinel marking the table end + PyMethodDef *p = &m_methods_table[ 0 ]; + + p->ml_name = NULL; + p->ml_meth = NULL; + p->ml_flags = 0; + p->ml_doc = NULL; + } + + ~ExtensionClassMethodsTable() + { + delete[] m_methods_table; + } + + // check that all methods added are unique + void check_unique_method_name( const char *_name ) + { + std::string name( _name ); + for( int i=0; i<m_methods_used; i++ ) + { + if( name == m_methods_table[i].ml_name ) + { + throw AttributeError( name ); + } + } + } + PyMethodDef *add_method( const char *name, PyCFunction function, int flags, const char *doc ) + { + check_unique_method_name( name ); + + // see if there is enough space for one more method + if( m_methods_used == (m_methods_size-1) ) + { + PyMethodDef *old_mt = m_methods_table; + m_methods_size += METHOD_TABLE_SIZE_INCREMENT; + PyMethodDef *new_mt = new PyMethodDef[ m_methods_size ]; + for( int i=0; i<m_methods_used; i++ ) + { + new_mt[ i ] = old_mt[ i ]; + } + delete[] old_mt; + m_methods_table = new_mt; + } + + // add method into the table + PyMethodDef *p = &m_methods_table[ m_methods_used ]; + p->ml_name = name; + p->ml_meth = function; + p->ml_flags = flags; + p->ml_doc = doc; + + m_methods_used++; + p++; + + // add the sentinel marking the table end + p->ml_name = NULL; + p->ml_meth = NULL; + p->ml_flags = 0; + p->ml_doc = NULL; + + return m_methods_table; + } + + private: + enum {METHOD_TABLE_SIZE_INCREMENT = 1}; + PyMethodDef *m_methods_table; + int m_methods_used; + int m_methods_size; + }; + + template<TEMPLATE_TYPENAME T> class PythonClass + : public PythonExtensionBase + { + protected: + explicit PythonClass( PythonClassInstance *self, Tuple &/*args*/, Dict &/*kwds*/ ) + : PythonExtensionBase() + , m_class_instance( self ) + { + } + + virtual ~PythonClass() + {} + + static ExtensionClassMethodsTable &methodTable() + { + static ExtensionClassMethodsTable *method_table; + if( method_table == NULL ) + method_table = new ExtensionClassMethodsTable; + return *method_table; + } + + static void add_method( const char *name, PyCFunction function, int flags, const char *doc=NULL ) + { + behaviors().set_methods( methodTable().add_method( name, function, flags, doc ) ); + } + + static PythonType &behaviors() + { + static PythonType *p; + if( p == NULL ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + const char *default_name = (typeid( T )).name(); +#else + const char *default_name = "unknown"; +#endif + p = new PythonType( sizeof( PythonClassInstance ), 0, default_name ); + p->set_tp_new( extension_object_new ); + p->set_tp_init( extension_object_init ); + p->set_tp_dealloc( extension_object_deallocator ); + + // we are a class + p->supportClass(); + + // always support get and set attr + p->supportGetattro(); + p->supportSetattro(); + } + + return *p; + } + + static PyObject *extension_object_new( PyTypeObject *subtype, PyObject * /*args*/, PyObject * /*kwds*/ ) + { +#ifdef PYCXX_DEBUG + std::cout << "extension_object_new()" << std::endl; +#endif + PyObject *object; +#ifdef Py_LIMITED_API + object = ( (allocfunc)PyType_GetSlot( subtype, Py_tp_alloc ) )( subtype, 0 ); +#else + object = subtype->tp_alloc( subtype, 0 ); +#endif + PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( object ); + if( o == NULL ) + return NULL; + + o->m_pycxx_object = NULL; + + PyObject *self = reinterpret_cast<PyObject *>( o ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_new() => self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << std::endl; +#endif + return self; + } + + static int extension_object_init( PyObject *_self, PyObject *args_, PyObject *kwds_ ) + { + try + { + Py::Tuple args( args_ ); + Py::Dict kwds; + if( kwds_ != NULL ) + kwds = kwds_; + + PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << " )" << std::endl; + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + + if( self->m_pycxx_object == NULL ) + { + self->m_pycxx_object = new T( self, args, kwds ); +#ifdef PYCXX_DEBUG + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + } + else + { +#ifdef PYCXX_DEBUG + std::cout << " reinit - self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + self->m_pycxx_object->reinit( args, kwds ); + } + } + catch( BaseException & ) + { + return -1; + } + return 0; + } + + static void extension_object_deallocator( PyObject *_self ) + { + PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self ); +#ifdef PYCXX_DEBUG + std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned long >( self ) << std::dec << " )" << std::endl; + std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( self->m_pycxx_object ) << std::dec << std::endl; +#endif + delete self->m_pycxx_object; +#ifdef Py_LIMITED_API + ((freefunc)PyType_GetSlot( _self->ob_type, Py_tp_free ))( _self ); +#else + _self->ob_type->tp_free( _self ); +#endif + } + + public: + static PyTypeObject *type_object() + { + return behaviors().type_object(); + } + + static Object type() + { + return Object( reinterpret_cast<PyObject *>( behaviors().type_object() ) ); + } + + static bool check( PyObject *p ) + { + // is p a me or a derived me + switch( PyObject_IsInstance( p, reinterpret_cast<PyObject *>( type_object() ) ) ) + { + default: + case -1: + throw Exception(); + case 0: + return false; + case 1: + return true; + } + } + + static bool check( const Object &ob ) + { + return check( ob.ptr() ); + } + + virtual PyObject *selfPtr() + { + return reinterpret_cast<PyObject *>( m_class_instance ); + } + + virtual Object self() + { + return Object( reinterpret_cast<PyObject *>( m_class_instance ) ); + } + + protected: + private: + PythonClassInstance *m_class_instance; + + private: + // + // prevent the compiler generating these unwanted functions + // + explicit PythonClass( const PythonClass<T> &other ); + void operator=( const PythonClass<T> &rhs ); + }; + + // + // ExtensionObject<T> is an Object that will accept only T's. + // + template<TEMPLATE_TYPENAME T> + class PythonClassObject: public Object + { + public: + + explicit PythonClassObject( PyObject *pyob ) + : Object( pyob ) + { + validate(); + } + + PythonClassObject( const PythonClassObject<T> &other ) + : Object( *other ) + { + validate(); + } + + PythonClassObject( const Object &other ) + : Object( *other ) + { + validate(); + } + + PythonClassObject &operator=( const Object &rhs ) + { + *this = *rhs; + return *this; + } + + PythonClassObject &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return( pyob && T::check( pyob ) ); + } + + // + // Obtain a pointer to the PythonExtension object + // + T *getCxxObject( void ) + { + return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) ); + } + }; +} // Namespace Py + +// End of __CXX_ExtensionClass__h +#endif diff --git a/contrib/libs/pycxx/Python3/ExtensionTypeBase.hxx b/contrib/libs/pycxx/Python3/ExtensionTypeBase.hxx new file mode 100755 index 00000000000..38ee37f3294 --- /dev/null +++ b/contrib/libs/pycxx/Python3/ExtensionTypeBase.hxx @@ -0,0 +1,179 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_ExtensionTypeBase__h +#define __CXX_ExtensionTypeBase__h + +namespace Py +{ + // Class PythonExtension is what you inherit from to create + // a new Python extension type. You give your class itself + // as the template paramter. + + // There are two ways that extension objects can get destroyed. + // 1. Their reference count goes to zero + // 2. Someone does an explicit delete on a pointer. + // In(1) the problem is to get the destructor called + // We register a special deallocator in the Python type object + // (see behaviors()) to do this. + // In(2) there is no problem, the dtor gets called. + + // PythonExtension does not use the usual Python heap allocator, + // instead using new/delete. We do the setting of the type object + // and reference count, usually done by PyObject_New, in the + // base class ctor. + + // This special deallocator does a delete on the pointer. + + class PythonExtensionBase : public PyObject + { + public: + PythonExtensionBase(); + virtual ~PythonExtensionBase(); + + public: + // object + virtual void reinit( Tuple &args, Dict &kwds ); + + // object basics +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) + virtual int print( FILE *, int ); +#endif + virtual Object getattr( const char * ); + virtual int setattr( const char *, const Object & ); + virtual Object getattro( const String & ); + Object genericGetAttro( const String & ); + virtual int setattro( const String &, const Object & ); + int genericSetAttro( const String &, const Object & ); + virtual int compare( const Object & ); + virtual Object rich_compare( const Object &, int ); + virtual Object repr(); + virtual Object str(); + virtual long hash(); + virtual Object call( const Object &, const Object & ); + virtual Object iter(); + virtual PyObject *iternext(); + + // Sequence methods + virtual PyCxx_ssize_t sequence_length(); + virtual Object sequence_concat( const Object & ); + virtual Object sequence_repeat( Py_ssize_t ); + virtual Object sequence_item( Py_ssize_t ); + + virtual int sequence_ass_item( Py_ssize_t, const Object & ); + + virtual Object sequence_inplace_concat( const Object & ); + virtual Object sequence_inplace_repeat( Py_ssize_t ); + + virtual int sequence_contains( const Object & ); + + // Mapping + virtual PyCxx_ssize_t mapping_length(); + virtual Object mapping_subscript( const Object & ); + + virtual int mapping_ass_subscript( const Object &, const Object & ); + + // Number + virtual Object number_negative(); + virtual Object number_positive(); + virtual Object number_absolute(); + virtual Object number_invert(); + virtual Object number_int(); + virtual Object number_float(); + virtual Object number_long(); + virtual Object number_add( const Object & ); + virtual Object number_subtract( const Object & ); + virtual Object number_multiply( const Object & ); + virtual Object number_remainder( const Object & ); + virtual Object number_divmod( const Object & ); + virtual Object number_lshift( const Object & ); + virtual Object number_rshift( const Object & ); + virtual Object number_and( const Object & ); + virtual Object number_xor( const Object & ); + virtual Object number_or( const Object & ); + virtual Object number_power( const Object &, const Object & ); + + // Buffer +#ifndef Py_LIMITED_API + virtual int buffer_get( Py_buffer *, int flags ); + virtual int buffer_release( Py_buffer *buf ); +#endif + + public: + // helper functions to call function fn_name with 0 to 9 args + Object callOnSelf( const std::string &fn_name ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8 ); + Object callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8, const Object &arg9 ); + + public: + virtual PyObject *selfPtr() = 0; + virtual Object self() = 0; + + private: + void missing_method( void ); + static PyObject *method_call_handler( PyObject *self, PyObject *args ); + }; + +} // Namespace Py + +// End of __CXX_ExtensionTypeBase__h +#endif diff --git a/contrib/libs/pycxx/Python3/Extensions.hxx b/contrib/libs/pycxx/Python3/Extensions.hxx new file mode 100755 index 00000000000..42516eb1c64 --- /dev/null +++ b/contrib/libs/pycxx/Python3/Extensions.hxx @@ -0,0 +1,189 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Extensions__h +#define __CXX_Extensions__h + + +#ifdef _MSC_VER +// disable warning C4786: symbol greater than 255 character, +// okay to ignore +#pragma warning( disable: 4786 ) +#endif + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "Config.hxx" +#include "CxxDebug.hxx" +#include "Objects.hxx" + +extern "C" { extern PyObject py_object_initializer; } + +#include <vector> +#include <map> + +// ---------------------------------------------------------------------- + +namespace Py +{ + class ExtensionModuleBase; + + // Make an Exception Type for use in raising custom exceptions + class ExtensionExceptionType : public Object + { + public: + ExtensionExceptionType(); + virtual ~ExtensionExceptionType(); + + // call init to create the type + void init( ExtensionModuleBase &module, const std::string &name, ExtensionExceptionType &parent ); + void init( ExtensionModuleBase &module, const std::string &name ); + }; + + class MethodTable + { + public: + MethodTable(); + virtual ~MethodTable(); + + void add( const char *method_name, PyCFunction f, const char *doc="", int flag=1 ); + PyMethodDef *table(); + + protected: + std::vector<PyMethodDef> t; // accumulator of PyMethodDef's + PyMethodDef *mt; // Actual method table produced when full + + static PyMethodDef method( const char* method_name, PyCFunction f, int flags=1, const char* doc="" ); + + private: + // + // prevent the compiler generating these unwanted functions + // + MethodTable( const MethodTable &m ); //unimplemented + void operator=( const MethodTable &m ); //unimplemented + + }; // end class MethodTable + + // Note: Python calls noargs as varargs buts args==NULL + extern "C" typedef PyObject *(*method_noargs_call_handler_t)( PyObject *_self, PyObject * ); + extern "C" typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args ); + extern "C" typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict ); + + template<class T> + class MethodDefExt + { + public: + typedef Object (T::*method_noargs_function_t)(); + typedef Object (T::*method_varargs_function_t)( const Tuple &args ); + typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); + + // NOARGS + MethodDefExt + ( + const char *_name, + method_noargs_function_t _function, + method_noargs_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_NOARGS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = _function; + ext_varargs_function = NULL; + ext_keyword_function = NULL; + } + + // VARARGS + MethodDefExt + ( + const char *_name, + method_varargs_function_t _function, + method_varargs_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_VARARGS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = NULL; + ext_varargs_function = _function; + ext_keyword_function = NULL; + } + + // VARARGS + KEYWORD + MethodDefExt + ( + const char *_name, + method_keyword_function_t _function, + method_keyword_call_handler_t _handler, + const char *_doc + ) + { + ext_meth_def.ml_name = const_cast<char *>( _name ); + ext_meth_def.ml_meth = reinterpret_cast<method_varargs_call_handler_t>( _handler ); + ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS; + ext_meth_def.ml_doc = const_cast<char *>( _doc ); + + ext_noargs_function = NULL; + ext_varargs_function = NULL; + ext_keyword_function = _function; + } + + ~MethodDefExt() + {} + + PyMethodDef ext_meth_def; + method_noargs_function_t ext_noargs_function; + method_varargs_function_t ext_varargs_function; + method_keyword_function_t ext_keyword_function; + Object py_method; + }; +} // Namespace Py + +#include "ExtensionModule.hxx" +#include "PythonType.hxx" +#include "ExtensionTypeBase.hxx" +#include "ExtensionOldType.hxx" +#include "ExtensionType.hxx" + +// End of CXX_Extensions.h +#endif diff --git a/contrib/libs/pycxx/Python3/IndirectPythonInterface.hxx b/contrib/libs/pycxx/Python3/IndirectPythonInterface.hxx new file mode 100755 index 00000000000..e77944c5e6d --- /dev/null +++ b/contrib/libs/pycxx/Python3/IndirectPythonInterface.hxx @@ -0,0 +1,163 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ +#define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ + +#include "../WrapPython.h" + +namespace Py +{ +bool InitialisePythonIndirectInterface(); + +// +// Wrap Exception variables as function calls +// +PyObject * _Exc_BaseException(); + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + PyObject * _Exc_##eclass(); + +#include "cxx_standard_exceptions.hxx" +#undef PYCXX_STANDARD_EXCEPTION + +// +// Wrap Object variables as function calls +// +PyObject * _None(); + +PyObject * _False(); +PyObject * _True(); + +// +// Wrap Type variables as function calls +// +PyTypeObject * _List_Type(); +bool _List_Check( PyObject *o ); + +PyTypeObject * _Buffer_Type(); +bool _Buffer_Check( PyObject *op ); + +PyTypeObject * _Class_Type(); +bool _Class_Check( PyObject *op ); + +PyTypeObject * _Instance_Type(); +bool _Instance_Check( PyObject *op ); + +#ifndef Py_LIMITED_API +PyTypeObject * _Method_Type(); +bool _Method_Check( PyObject *op ); +#endif + +PyTypeObject * _Complex_Type(); +bool _Complex_Check( PyObject *op ); + +PyTypeObject * _Dict_Type(); +bool _Dict_Check( PyObject *op ); + +PyTypeObject * _File_Type(); +bool _File_Check( PyObject *op ); + +PyTypeObject * _Float_Type(); +bool _Float_Check( PyObject *op ); + +PyTypeObject * _Frame_Type(); +bool _Frame_Check( PyObject *op ); + +#ifndef Py_LIMITED_API +PyTypeObject * _Function_Type(); +bool _Function_Check( PyObject *op ); +#endif + +PyTypeObject * _Bool_Type(); +bool _Boolean_Check( PyObject *op ); + +PyTypeObject * _Int_Type(); +bool _Int_Check( PyObject *op ); + +PyTypeObject * _List_Type(); +bool _List_Check( PyObject *op ); + +PyTypeObject * _Long_Type(); +bool _Long_Check( PyObject *op ); + +PyTypeObject * _CFunction_Type(); +bool _CFunction_Check( PyObject *op ); + +PyTypeObject * _Module_Type(); +bool _Module_Check( PyObject *op ); + +PyTypeObject * _Type_Type(); +bool _Type_Check( PyObject *op ); + +PyTypeObject * _Range_Type(); +bool _Range_Check( PyObject *op ); + +PyTypeObject * _Slice_Type(); +bool _Slice_Check( PyObject *op ); + +PyTypeObject * _Unicode_Type(); +bool _Unicode_Check( PyObject *op ); + +PyTypeObject * _Bytes_Type(); +bool _Bytes_Check( PyObject *op ); + +PyTypeObject * _TraceBack_Type(); +bool _TraceBack_Check( PyObject *v ); + +PyTypeObject * _Tuple_Type(); +bool _Tuple_Check( PyObject *op ); + +#ifndef Py_LIMITED_API +int &_Py_DebugFlag(); +int &_Py_InteractiveFlag(); +int &_Py_OptimizeFlag(); +int &_Py_NoSiteFlag(); +int &_Py_TabcheckFlag(); +int &_Py_VerboseFlag(); +int &_Py_UnicodeFlag(); +#endif + +void _XINCREF( PyObject *op ); +void _XDECREF( PyObject *op ); + +#ifndef Py_LIMITED_API +char *__Py_PackageContext(); +#endif +}; + +#endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ diff --git a/contrib/libs/pycxx/Python3/Objects.hxx b/contrib/libs/pycxx/Python3/Objects.hxx new file mode 100755 index 00000000000..0eea51d8239 --- /dev/null +++ b/contrib/libs/pycxx/Python3/Objects.hxx @@ -0,0 +1,3578 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_Objects__h +#define __CXX_Objects__h + +#include "../WrapPython.h" +#include "../Version.hxx" +#include "Config.hxx" +#include "CxxDebug.hxx" +#include "Exception.hxx" + +#include <iostream> +#include STR_STREAM +#include <string> +#include <iterator> +#include <utility> +#include <typeinfo> +#include <algorithm> + +namespace Py +{ + void ifPyErrorThrowCxxException(); + + typedef Py_ssize_t sequence_index_type; // type of an index into a sequence + + // Forward declarations + class Object; + class Type; + template<TEMPLATE_TYPENAME T> class SeqBase; + class Bytes; + class String; + class List; + template<TEMPLATE_TYPENAME T> class MapBase; + class Tuple; + class Dict; + + //===========================================================================// + // class Object + // The purpose of this class is to serve as the most general kind of + // Python object, for the purpose of writing C++ extensions in Python + // Objects hold a PyObject* which they own. This pointer is always a + // valid pointer to a Python object. In children we must maintain this behavior. + // + // Instructions on how to make your own class MyType descended from Object: + // (0) Pick a base class, either Object or perhaps SeqBase<T> or MapBase<T>. + // This example assumes Object. + + // (1) Write a routine int MyType_Check( PyObject * ) modeled after PyInt_Check, + // PyFloat_Check, etc. + + // (2) Add method accepts: + // virtual bool accepts( PyObject *pyob ) const { + // return pyob && MyType_Check( pyob ); + // } + + // (3) Include the following constructor and copy constructor + // + /* + explicit MyType( PyObject *pyob ): Object( pyob ) + { + validate(); + } + + MyType( const Object &other ): Object( other.ptr() ) + { + validate(); + } + */ + + // Alernate version for the constructor to allow for construction from owned pointers: + /* + explicit MyType( PyObject *pyob ): Object( pyob ) + { + validate(); + } + */ + + // You may wish to add other constructors; see the classes below for examples. + // Each constructor must use "set" to set the pointer + // and end by validating the pointer you have created. + + //( 4 ) Each class needs at least these two assignment operators: + /* + MyType &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Mytype &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + */ + // Note on accepts: constructors call the base class + // version of a virtual when calling the base class constructor, + // so the test has to be done explicitly in a descendent. + + // If you are inheriting from PythonExtension<T> to define an object + // note that it contains PythonExtension<T>::check + // which you can use in accepts when writing a wrapper class. + // See Demo/range.h and Demo/range.cxx for an example. + + class Object + { + private: + // the pointer to the Python object + // Only Object sets this directly. + // The default constructor for Object sets it to Py_None and + // child classes must use "set" to set it + // + PyObject *p; + + protected: + void set( PyObject *pyob, bool owned = false ) + { + release(); + p = pyob; + if( !owned ) + { + Py::_XINCREF( p ); + } + validate(); + } + + void release() + { + Py::_XDECREF( p ); + p = NULL; + } + + void validate(); + + public: + // Constructor acquires new ownership of pointer unless explicitly told not to. + explicit Object( PyObject *pyob=Py::_None(), bool owned = false ) + : p( pyob ) + { + if( !owned ) + { + Py::_XINCREF( p ); + } + validate(); + } + + // Copy constructor acquires new ownership of pointer + Object( const Object &ob ) + : p( ob.p ) + { + Py::_XINCREF( p ); + validate(); + } + + // Assignment acquires new ownership of pointer + Object &operator=( const Object &rhs ) + { + set( rhs.p ); + return *this; + } + + Object &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + + return *this; + } + + // Destructor + virtual ~Object() + { + release(); + } + + // Loaning the pointer to others, retain ownership + PyObject *operator*() const + { + return p; + } + + // Explicit reference_counting changes + void increment_reference_count() + { + Py::_XINCREF( p ); + } + + void decrement_reference_count() + { + // not allowed to commit suicide, however + if( reference_count() == 1 ) + { + throw RuntimeError( "Object::decrement_reference_count error." ); + } + Py::_XDECREF( p ); + } + + // Would like to call this pointer() but messes up STL in SeqBase<T> + PyObject *ptr() const + { + return p; + } + + // + // Queries + // + + // Can pyob be used in this object's constructor? + virtual bool accepts( PyObject * ) const + { + // allow any object or NULL + return true; + } + + Py_ssize_t reference_count() const + { // the reference count + return p ? p->ob_refcnt : 0; + } + + Type type() const; // the type object associated with this one + + String str() const; // the str() representation + + std::string as_string() const; + + String repr() const; // the repr() representation + + List dir() const; // the dir() list + + bool hasAttr( const std::string &s ) const + { + return PyObject_HasAttrString( p, const_cast<char*>( s.c_str() ) ) ? true: false; + } + + Object getAttr( const std::string &s ) const + { + return Object( PyObject_GetAttrString( p, const_cast<char*>( s.c_str() ) ), true ); + } + + Object callMemberFunction( const std::string &function_name ) const; + Object callMemberFunction( const std::string &function_name, const Tuple &args ) const; + Object callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const; + + Object getItem( const Object &key ) const + { + return Object( PyObject_GetItem( p, *key ), true ); + } + + Py_hash_t hashValue() const + { + return PyObject_Hash( p ); + } + + // convert to bool + bool as_bool() const + { + return PyObject_IsTrue( ptr() ) != 0; + } + + bool is( PyObject *pother ) const + { // identity test + return p == pother; + } + + bool is( const Object &other ) const + { // identity test + return p == other.p; + } + + bool isNull() const + { + return p == NULL; + } + + bool isNone() const + { + return p == _None(); + } + + bool isCallable() const + { + return PyCallable_Check( p ) != 0; + } + + bool isDict() const + { + return Py::_Dict_Check( p ); + } + + bool isList() const + { + return Py::_List_Check( p ); + } + + bool isMapping() const + { + return PyMapping_Check( p ) != 0; + } + + bool isNumeric() const + { + return PyNumber_Check( p ) != 0; + } + + bool isSequence() const + { + return PySequence_Check( p ) != 0; + } + + bool isTrue() const + { + return PyObject_IsTrue( p ) != 0; + } + + bool isType( const Type &t ) const; + + bool isTuple() const + { + return Py::_Tuple_Check( p ); + } + + bool isString() const + { + return Py::_Unicode_Check( p ); + } + + bool isBytes() const + { + return Py::_Bytes_Check( p ); + } + + bool isBoolean() const + { + return Py::_Boolean_Check( p ); + } + + // Commands + void setAttr( const std::string &s, const Object &value ) + { + if( PyObject_SetAttrString( p, const_cast<char*>( s.c_str() ), *value ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void delAttr( const std::string &s ) + { + if( PyObject_DelAttrString( p, const_cast<char*>( s.c_str() ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + // PyObject_SetItem is too weird to be using from C++ + // so it is intentionally omitted. + + void delItem( const Object &key ) + { + if( PyObject_DelItem( p, *key ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + // Equality and comparison use PyObject_Compare + + }; + // End of class Object + + // Null can be return from when it is require to return NULL to Python from a method + class Null: public Object + { + public: + Null() + : Object( NULL ) + { + } + virtual ~Null() + { + } + + virtual bool accepts( PyObject *pyob ) const + { + return pyob == NULL; + } + }; + + //------------------------------------------------------------ + bool operator==( const Object &o1, const Object &o2 ); + bool operator!=( const Object &o1, const Object &o2 ); + bool operator>=( const Object &o1, const Object &o2 ); + bool operator<=( const Object &o1, const Object &o2 ); + bool operator<( const Object &o1, const Object &o2 ); + bool operator>( const Object &o1, const Object &o2 ); + + //------------------------------------------------------------ + + + // + // Convert an owned Python pointer into a PyCXX Object + // + inline Object asObject( PyObject *p ) + { + return Object( p, true ); + } + + // new_reference_to also overloaded below on Object + inline PyObject *new_reference_to( PyObject *p ) + { + Py::_XINCREF( p ); + return p; + } + + inline PyObject *new_reference_to( const Object &g ) + { + PyObject *p = g.ptr(); + Py::_XINCREF( p ); + return p; + } + + // Python special None value + inline Object None() + { + return Object( Py::_None() ); + } + + // Python special Boolean values + inline Object False() + { + return Object( Py::_False() ); + } + + inline Object True() + { + return Object( Py::_True() ); + } + + // TMM: 31May'01 - Added the #ifndef so I can exlude iostreams. +#ifndef CXX_NO_IOSTREAMS + std::ostream &operator<<( std::ostream &os, const Object &ob ); +#endif + + // Class Type + class Type: public Object + { + public: + explicit Type( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Type( const Object &ob ) + : Object( *ob ) + { + validate(); + } + + Type( const Type &t ) + : Object( t ) + { + validate(); + } + + Type &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Type &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Type_Check( pyob ); + } + }; + + // =============================================== + // class boolean + class Boolean: public Object + { + public: + // Constructor + Boolean( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Boolean( const Boolean &ob ) + : Object( *ob ) + { + validate(); + } + + // create from bool + Boolean( bool v=false ) + { + set( PyBool_FromLong( v ? 1 : 0 ), true ); + validate(); + } + + explicit Boolean( const Object &ob ) + : Object( *ob ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + Boolean &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Boolean &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + // accepts any object that can be converted to a boolean + return pyob && PyObject_IsTrue( pyob ) != -1; + } + + Boolean &operator=( bool v ) + { + set( PyBool_FromLong( v ? 1 : 0 ), true ); + return *this; + } + + operator bool() const + { + return as_bool(); + } + }; + + // =============================================== + // class Long + class Long: public Object + { + public: + // Constructor + explicit Long( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Long( const Long &ob ) + : Object( ob.ptr() ) + { + validate(); + } + + // try to create from any object + explicit Long( const Object &ob ) + : Object( PyNumber_Long( *ob ), true ) + { + validate(); + } + + // create from long + explicit Long( long v = 0L ) + : Object( PyLong_FromLong( v ), true ) + { + validate(); + } + + // create from unsigned long + explicit Long( unsigned long v ) + : Object( PyLong_FromUnsignedLong( v ), true ) + { + validate(); + } + + // create from int + explicit Long( int v ) + : Object( PyLong_FromLong( static_cast<long>( v ) ), true ) + { + validate(); + } + +#ifdef HAVE_LONG_LONG + // create from long long + explicit Long( PY_LONG_LONG v ) + : Object( PyLong_FromLongLong( v ), true ) + { + validate(); + } + + // create from unsigned long long + explicit Long( unsigned PY_LONG_LONG v ) + : Object( PyLong_FromUnsignedLongLong( v ), true ) + { + validate(); + } +#endif + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Long_Check( pyob ); + } + + // Assignment acquires new ownership of pointer + Long &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Long &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( PyNumber_Long( rhsp ), true ); + return *this; + } + + // assign from an int + Long &operator=( int v ) + { + set( PyLong_FromLong( long( v ) ), true ); + return *this; + } + + // assign from long + Long &operator=( long v ) + { + set( PyLong_FromLong( v ), true ); + return *this; + } + + // assign from unsigned long + Long &operator=( unsigned long v ) + { + set( PyLong_FromUnsignedLong( v ), true ); + return *this; + } + +#ifdef HAVE_LONG_LONG + Long &operator=( PY_LONG_LONG v ) + { + set( PyLong_FromLongLong( v ), true ); + return *this; + } + + Long &operator=( unsigned PY_LONG_LONG v ) + { + set( PyLong_FromUnsignedLongLong( v ), true ); + return *this; + } +#endif + + // convert to long + long as_long() const + { + return PyLong_AsLong( ptr() ); + } + + operator long() const + { + return as_long(); + } + + operator int() const + { + return static_cast<int>( as_long() ); + } + + // convert to unsigned + long as_unsigned_long() const + { + return PyLong_AsUnsignedLong( ptr() ); + } + + // convert to unsigned + operator unsigned long() const + { + return as_unsigned_long(); + } + + double as_double() const + { + return PyLong_AsDouble( ptr() ); + } + + operator double() const + { + return as_double(); + } + +#ifdef HAVE_LONG_LONG + PY_LONG_LONG as_long_long() const + { + return PyLong_AsLongLong( ptr() ); + } + + operator PY_LONG_LONG() const + { + return as_long_long(); + } + + unsigned PY_LONG_LONG as_unsigned_long_long() const + { + return PyLong_AsUnsignedLongLong( ptr() ); + } + + operator unsigned PY_LONG_LONG() const + { + return as_unsigned_long_long(); + } +#endif + + // prefix ++ + Long operator++() + { + set( PyNumber_Add( ptr(), *Long( 1 ) ) ); + return *this; + } + + // postfix ++ + Long operator++( int ) + { + Long a = *this; + set( PyNumber_Add( ptr(), *Long( 1 ) ) ); + return a; + } + + // prefix -- + Long operator--() + { + set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); + return *this; + } + + // postfix -- + Long operator--( int ) + { + Long a = *this; + set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); + return a; + } + }; + +#ifdef PYCXX_PYTHON_2TO3 + // PyCXX for Python2 had an Int and LongLong classes + typedef Long Int; +#ifdef HAVE_LONG_LONG + typedef Long LongLong; +#endif +#endif + +#if 1 + //------------------------------------------------------------ + // compare operators + bool operator!=( const Long &a, const Long &b ); + bool operator!=( const Long &a, int b ); + bool operator!=( const Long &a, long b ); + bool operator!=( int a, const Long &b ); + bool operator!=( long a, const Long &b ); + //------------------------------ + bool operator==( const Long &a, const Long &b ); + bool operator==( const Long &a, int b ); + bool operator==( const Long &a, long b ); + bool operator==( int a, const Long &b ); + bool operator==( long a, const Long &b ); + //------------------------------ + bool operator>( const Long &a, const Long &b ); + bool operator>( const Long &a, int b ); + bool operator>( const Long &a, long b ); + bool operator>( int a, const Long &b ); + bool operator>( long a, const Long &b ); + //------------------------------ + bool operator>=( const Long &a, const Long &b ); + bool operator>=( const Long &a, int b ); + bool operator>=( const Long &a, long b ); + bool operator>=( int a, const Long &b ); + bool operator>=( long a, const Long &b ); + //------------------------------ + bool operator<( const Long &a, const Long &b ); + bool operator<( const Long &a, int b ); + bool operator<( const Long &a, long b ); + bool operator<( int a, const Long &b ); + bool operator<( long a, const Long &b ); + //------------------------------ + bool operator<=( const Long &a, const Long &b ); + bool operator<=( int a, const Long &b ); + bool operator<=( long a, const Long &b ); + bool operator<=( const Long &a, int b ); + bool operator<=( const Long &a, long b ); + +#ifdef HAVE_LONG_LONG + //------------------------------ + bool operator!=( const Long &a, PY_LONG_LONG b ); + bool operator!=( PY_LONG_LONG a, const Long &b ); + //------------------------------ + bool operator==( const Long &a, PY_LONG_LONG b ); + bool operator==( PY_LONG_LONG a, const Long &b ); + //------------------------------ + bool operator>( const Long &a, PY_LONG_LONG b ); + bool operator>( PY_LONG_LONG a, const Long &b ); + //------------------------------ + bool operator>=( const Long &a, PY_LONG_LONG b ); + bool operator>=( PY_LONG_LONG a, const Long &b ); + //------------------------------ + bool operator<( const Long &a, PY_LONG_LONG b ); + bool operator<( PY_LONG_LONG a, const Long &b ); + //------------------------------ + bool operator<=( const Long &a, PY_LONG_LONG b ); + bool operator<=( PY_LONG_LONG a, const Long &b ); +#endif +#endif + + // =============================================== + // class Float + // + class Float: public Object + { + public: + // Constructor + explicit Float( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Float( const Float &f ) + : Object( f ) + { + validate(); + } + + // make from double + explicit Float( double v=0.0 ) + : Object( PyFloat_FromDouble( v ), true ) + { + validate(); + } + + // try to make from any object + Float( const Object &ob ) + : Object( PyNumber_Float( *ob ), true ) + { + validate(); + } + + Float &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Float &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( PyNumber_Float( rhsp ), true ); + return *this; + } + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Float_Check( pyob ); + } + + double as_double() const + { + return PyFloat_AsDouble( ptr() ); + } + + // convert to double + operator double() const + { + return as_double(); + } + + // assign from a double + Float &operator=( double v ) + { + set( PyFloat_FromDouble( v ), true ); + return *this; + } + // assign from an int + Float &operator=( int v ) + { + set( PyFloat_FromDouble( double( v ) ), true ); + return *this; + } + // assign from long + Float &operator=( long v ) + { + set( PyFloat_FromDouble( double( v ) ), true ); + return *this; + } + // assign from an Long + Float &operator=( const Long &iob ) + { + set( PyFloat_FromDouble( double( iob.as_long() ) ), true ); + return *this; + } + }; + + //------------------------------------------------------------ + // compare operators + bool operator!=( const Float &a, const Float &b ); + bool operator!=( const Float &a, double b ); + bool operator!=( double a, const Float &b ); + //------------------------------ + bool operator==( const Float &a, const Float &b ); + bool operator==( const Float &a, double b ); + bool operator==( double a, const Float &b ); + //------------------------------ + bool operator>( const Float &a, const Float &b ); + bool operator>( const Float &a, double b ); + bool operator>( double a, const Float &b ); + //------------------------------ + bool operator>=( const Float &a, const Float &b ); + bool operator>=( const Float &a, double b ); + bool operator>=( double a, const Float &b ); + //------------------------------ + bool operator<( const Float &a, const Float &b ); + bool operator<( const Float &a, double b ); + bool operator<( double a, const Float &b ); + //------------------------------ + bool operator<=( const Float &a, const Float &b ); + bool operator<=( double a, const Float &b ); + bool operator<=( const Float &a, double b ); + + // =============================================== + // class Complex + class Complex: public Object + { + public: + // Constructor + explicit Complex( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Complex( const Complex &f ) + : Object( f ) + { + validate(); + } + + // make from double + explicit Complex( double v=0.0, double w=0.0 ) + :Object( PyComplex_FromDoubles( v, w ), true ) + { + validate(); + } + + Complex &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Complex &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Complex_Check( pyob ); + } + // convert to Py_complex +#ifndef Py_LIMITED_API + operator Py_complex() const + { + return PyComplex_AsCComplex( ptr() ); + } + // assign from a Py_complex + Complex &operator=( const Py_complex &v ) + { + set( PyComplex_FromCComplex( v ), true ); + return *this; + } +#endif + // assign from a double + Complex &operator=( double v ) + { + set( PyComplex_FromDoubles( v, 0.0 ), true ); + return *this; + } + // assign from an int + Complex &operator=( int v ) + { + set( PyComplex_FromDoubles( double( v ), 0.0 ), true ); + return *this; + } + // assign from long + Complex &operator=( long v ) + { + set( PyComplex_FromDoubles( double( v ), 0.0 ), true ); + return *this; + } + // assign from an Long + Complex &operator=( const Long &iob ) + { + set( PyComplex_FromDoubles( double( iob.as_long() ), 0.0 ), true ); + return *this; + } + + double real() const + { + return PyComplex_RealAsDouble( ptr() ); + } + + double imag() const + { + return PyComplex_ImagAsDouble( ptr() ); + } + }; + // Sequences + // Sequences are here represented as sequences of items of type T. + // The base class SeqBase<T> represents that. + // In basic Python T is always "Object". + + // seqref<T> is what you get if you get elements from a non-const SeqBase<T>. + // Note: seqref<T> could probably be a nested class in SeqBase<T> but that might stress + // some compilers needlessly. Simlarly for mapref later. + + // While this class is not intended for enduser use, it needs some public + // constructors for the benefit of the STL. + + // See Scott Meyer's More Essential C++ for a description of proxies. + // This application is even more complicated. We are doing an unusual thing + // in having a double proxy. If we want the STL to work + // properly we have to compromise by storing the rvalue inside. The + // entire Object API is repeated so that things like s[i].isList() will + // work properly. + + // Still, once in a while a weird compiler message may occur using expressions like x[i] + // Changing them to Object( x[i] ) helps the compiler to understand that the + // conversion of a seqref to an Object is wanted. + + template<TEMPLATE_TYPENAME T> + class seqref + { + protected: + SeqBase<T> &s; // the sequence + sequence_index_type offset; // item number + T the_item; // lvalue + + public: + seqref( SeqBase<T> &seq, sequence_index_type j ) + : s( seq ) + , offset( j ) + , the_item( s.getItem( j ) ) + {} + + seqref( const seqref<T> &range ) + : s( range.s ) + , offset( range.offset ) + , the_item( range.the_item ) + {} + + // TMM: added this seqref ctor for use with STL algorithms + seqref( Object &obj ) + : s( dynamic_cast< SeqBase<T>&>( obj ) ) + , offset( 0 ) + , the_item( s.getItem( offset ) ) + {} + + ~seqref() + {} + + operator T() const + { // rvalue + return the_item; + } + + seqref<T> &operator=( const seqref<T> &rhs ) + { //used as lvalue + the_item = rhs.the_item; + s.setItem( offset, the_item ); + return *this; + } + + seqref<T> &operator=( const T &ob ) + { // used as lvalue + the_item = ob; + s.setItem( offset, ob ); + return *this; + } + + // forward everything else to the item + PyObject *ptr() const + { + return the_item.ptr(); + } + + int reference_count() const + { // the reference count + return the_item.reference_count(); + } + + Type type() const + { + return the_item.type(); + } + + String str() const; + String repr() const; + + bool hasAttr( const std::string &attr_name ) const + { + return the_item.hasAttr( attr_name ); + } + + Object getAttr( const std::string &attr_name ) const + { + return the_item.getAttr( attr_name ); + } + + Object getItem( const Object &key ) const + { + return the_item.getItem( key ); + } + + long hashValue() const + { + return the_item.hashValue(); + } + + bool isCallable() const + { + return the_item.isCallable(); + } + + bool isInstance() const + { + return the_item.isInstance(); + } + + bool isDict() const + { + return the_item.isDict(); + } + + bool isList() const + { + return the_item.isList(); + } + + bool isMapping() const + { + return the_item.isMapping(); + } + + bool isNumeric() const + { + return the_item.isNumeric(); + } + + bool isSequence() const + { + return the_item.isSequence(); + } + + bool isTrue() const + { + return the_item.isTrue(); + } + + bool isType( const Type &t ) const + { + return the_item.isType( t ); + } + + bool isTuple() const + { + return the_item.isTuple(); + } + + bool isString() const + { + return the_item.isString(); + } + // Commands + void setAttr( const std::string &attr_name, const Object &value ) + { + the_item.setAttr( attr_name, value ); + } + + void delAttr( const std::string &attr_name ) + { + the_item.delAttr( attr_name ); + } + + void delItem( const Object &key ) + { + the_item.delItem( key ); + } + + bool operator==( const Object &o2 ) const + { + return the_item == o2; + } + + bool operator!=( const Object &o2 ) const + { + return the_item != o2; + } + + bool operator>=( const Object &o2 ) const + { + return the_item >= o2; + } + + bool operator<=( const Object &o2 ) const + { + return the_item <= o2; + } + + bool operator<( const Object &o2 ) const + { + return the_item < o2; + } + + bool operator>( const Object &o2 ) const + { + return the_item > o2; + } + }; // end of seqref + + + // class SeqBase<T> + // ...the base class for all sequence types + + template<TEMPLATE_TYPENAME T> + class SeqBase: public Object + { + public: + // STL definitions + typedef PyCxx_ssize_t size_type; + typedef seqref<T> reference; + typedef T const_reference; + typedef seqref<T> *pointer; + typedef int difference_type; + typedef T value_type; // TMM: 26Jun'01 + + virtual size_type max_size() const + { + return static_cast<size_type>( std::string::npos ); // why this constant its not from python + } + + virtual size_type capacity() const + { + return size(); + } + + virtual void swap( SeqBase<T> &c ) + { + SeqBase<T> temp = c; + c = ptr(); + set( temp.ptr() ); + } + + virtual size_type size() const + { + return PySequence_Length( ptr() ); + } + + explicit SeqBase<T>() + :Object( PyTuple_New( 0 ), true ) + { + validate(); + } + + explicit SeqBase<T>( PyObject *pyob, bool owned=false ) + : Object( pyob, owned ) + { + validate(); + } + + SeqBase<T>( const Object &ob ) + : Object( ob ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + SeqBase<T> &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + SeqBase<T> &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + virtual bool accepts( PyObject *pyob ) const + { + return pyob && PySequence_Check( pyob ); + } + + size_type length() const + { + return PySequence_Length( ptr() ); + } + + // Element access + const T operator[]( sequence_index_type index ) const + { + return getItem( index ); + } + + seqref<T> operator[]( sequence_index_type index ) + { + return seqref<T>( *this, index ); + } + + virtual T getItem( sequence_index_type i ) const + { + return T( asObject( PySequence_GetItem( ptr(), i ) ) ); + } + + virtual void setItem( sequence_index_type i, const T &ob ) + { + if( PySequence_SetItem( ptr(), i, *ob ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + SeqBase<T> repeat( int count ) const + { + return SeqBase<T>( PySequence_Repeat( ptr(), count ), true ); + } + + SeqBase<T> concat( const SeqBase<T> &other ) const + { + return SeqBase<T>( PySequence_Concat( ptr(), *other ), true ); + } + + // more STL compatability + const T front() const + { + return getItem( 0 ); + } + + seqref<T> front() + { + return seqref<T>( *this, 0 ); + } + + const T back() const + { + return getItem( size()-1 ); + } + + seqref<T> back() + { + return seqref<T>( *this, size()-1 ); + } + + void verify_length( size_type required_size ) const + { + if( size() != required_size ) + { + throw IndexError( "Unexpected SeqBase<T> length." ); + } + } + + void verify_length( size_type min_size, size_type max_size ) const + { + size_type n = size(); + if( n < min_size || n > max_size ) + { + throw IndexError( "Unexpected SeqBase<T> length." ); + } + } + + class iterator: public random_access_iterator_parent( seqref<T> ) + { + protected: + friend class SeqBase<T>; + SeqBase<T> *seq; + sequence_index_type count; + + public: + ~iterator() + {} + + iterator() + : seq( 0 ) + , count( 0 ) + {} + + iterator( SeqBase<T> *s, Py_ssize_t where ) + : seq( s ) + , count( where ) + {} + + iterator( const iterator &other ) + : seq( other.seq ) + , count( other.count ) + {} + + bool eql( const iterator &other ) const + { + return seq->ptr() == other.seq->ptr() && count == other.count; + } + + bool neq( const iterator &other ) const + { + return seq->ptr() != other.seq->ptr() || count != other.count; + } + + bool lss( const iterator &other ) const + { + return count < other.count; + } + + bool gtr( const iterator &other ) const + { + return count > other.count; + } + + bool leq( const iterator &other ) const + { + return count <= other.count; + } + + bool geq( const iterator &other ) const + { + return count >= other.count; + } + + seqref<T> operator*() + { + return seqref<T>( *seq, count ); + } + + seqref<T> operator[]( sequence_index_type i ) + { + return seqref<T>( *seq, count + i ); + } + + iterator &operator=( const iterator &other ) + { + if( this != &other ) + { + seq = other.seq; + count = other.count; + } + return *this; + } + + iterator operator+( sequence_index_type n ) const + { + return iterator( seq, count + n ); + } + + iterator operator-( sequence_index_type n ) const + { + return iterator( seq, count - n ); + } + + iterator &operator+=( sequence_index_type n ) + { + count = count + n; + return *this; + } + + iterator &operator-=( sequence_index_type n ) + { + count = count - n; + return *this; + } + + sequence_index_type operator-( const iterator &other ) const + { + if( seq->ptr() != other.seq->ptr() ) + { + throw RuntimeError( "SeqBase<T>::iterator comparison error" ); + } + return count - other.count; + } + + // prefix ++ + iterator &operator++() + { + count++; + return *this; + } + + // postfix ++ + iterator operator++( int ) + { + return iterator( seq, count++ ); + } + + // prefix -- + iterator &operator--() + { + count--; + return *this; + } + + // postfix -- + iterator operator--( int ) + { + return iterator( seq, count-- ); + } + + std::string diagnose() const + { + std::OSTRSTREAM oss; + oss << "iterator diagnosis " << seq << ", " << count << std::ends; + return std::string( oss.str() ); + } + + }; // end of class SeqBase<T>::iterator + + iterator begin() + { + return iterator( this, 0 ); + } + + iterator end() + { + return iterator( this, length() ); + } + + class const_iterator + : public random_access_iterator_parent( const Object ) + { + protected: + friend class SeqBase<T>; + const SeqBase<T> *seq; + sequence_index_type count; + + public: + ~const_iterator() + {} + + const_iterator() + : seq( 0 ) + , count( 0 ) + {} + + const_iterator( const SeqBase<T> *s, sequence_index_type where ) + : seq( s ) + , count( where ) + {} + + const_iterator( const const_iterator &other ) + : seq( other.seq ) + , count( other.count ) + {} + + const T operator*() const + { + return seq->getItem( count ); + } + + const T operator[]( sequence_index_type i ) const + { + return seq->getItem( count + i ); + } + + const_iterator &operator=( const const_iterator &other ) + { + if( this != &other ) + { + seq = other.seq; + count = other.count; + } + return *this; + } + + const_iterator operator+( sequence_index_type n ) const + { + return const_iterator( seq, count + n ); + } + + bool eql( const const_iterator &other ) const + { + return seq->ptr() == other.seq->ptr() && count == other.count; + } + + bool neq( const const_iterator &other ) const + { + return seq->ptr() != other.seq->ptr() || count != other.count; + } + + bool lss( const const_iterator &other ) const + { + return count < other.count; + } + + bool gtr( const const_iterator &other ) const + { + return count > other.count; + } + + bool leq( const const_iterator &other ) const + { + return count <= other.count; + } + + bool geq( const const_iterator &other ) const + { + return count >= other.count; + } + + const_iterator operator-( sequence_index_type n ) + { + return const_iterator( seq, count - n ); + } + + const_iterator &operator+=( sequence_index_type n ) + { + count = count + n; + return *this; + } + + const_iterator &operator-=( sequence_index_type n ) + { + count = count - n; + return *this; + } + + int operator-( const const_iterator &other ) const + { + if( *seq != *other.seq ) + { + throw RuntimeError( "SeqBase<T>::const_iterator::- error" ); + } + return count - other.count; + } + + // prefix ++ + const_iterator &operator++() + { + count++; + return *this; + } + + // postfix ++ + const_iterator operator++( int ) + { + return const_iterator( seq, count++ ); + } + + // prefix -- + const_iterator &operator--() + { + count--; + return *this; + } + + // postfix -- + const_iterator operator--( int ) + { + return const_iterator( seq, count-- ); + } + + }; // end of class SeqBase<T>::const_iterator + + const_iterator begin() const + { + return const_iterator( this, 0 ); + } + + const_iterator end() const + { + return const_iterator( this, length() ); + } + }; + + // Here's an important typedef you might miss if reading too fast... + typedef SeqBase<Object> Sequence; + + template <TEMPLATE_TYPENAME T> bool operator==( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator!=( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator< ( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator> ( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator<=( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator>=( const EXPLICIT_TYPENAME SeqBase<T>::iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::iterator &right ); + + template <TEMPLATE_TYPENAME T> bool operator==( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator!=( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator< ( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator> ( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator<=( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator>=( const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator &right ); + + + extern bool operator==( const Sequence::iterator &left, const Sequence::iterator &right ); + extern bool operator!=( const Sequence::iterator &left, const Sequence::iterator &right ); + extern bool operator< ( const Sequence::iterator &left, const Sequence::iterator &right ); + extern bool operator> ( const Sequence::iterator &left, const Sequence::iterator &right ); + extern bool operator<=( const Sequence::iterator &left, const Sequence::iterator &right ); + extern bool operator>=( const Sequence::iterator &left, const Sequence::iterator &right ); + + extern bool operator==( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + extern bool operator!=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + extern bool operator< ( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + extern bool operator> ( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + extern bool operator<=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + extern bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); + + // ================================================== + // class Char + // Python strings return strings as individual elements. + // I'll try having a class Char which is a String of length 1 + // +#ifndef Py_LIMITED_API + // This types are not available in stable ABI since Py_UNICODE and Py_UCS4 are not available as a typedefs. + // Applications that need to access the contents of a Unicode string can convert it to wchar_t. + typedef std::basic_string<Py_UNICODE> unicodestring; + typedef std::basic_string<Py_UCS4> ucs4string; + + extern Py_UNICODE unicode_null_string[1]; +#endif + + class Byte: public Object + { + public: + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob != NULL + && Py::_Bytes_Check( pyob ) + && PySequence_Length( pyob ) == 1; + } + + explicit Byte( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Byte( const Object &ob ) + : Object( ob ) + { + validate(); + } + + Byte( const std::string &v = "" ) + : Object( PyBytes_FromStringAndSize( const_cast<char*>( v.c_str() ), 1 ), true ) + { + validate(); + } + + Byte( char v ) + : Object( PyBytes_FromStringAndSize( &v, 1 ), true ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + Byte &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Byte &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + // Assignment from C string + Byte &operator=( const std::string &v ) + { + set( PyBytes_FromStringAndSize( const_cast<char*>( v.c_str() ), 1 ), true ); + return *this; + } + + Byte &operator=( char v ) + { + set( PyUnicode_FromStringAndSize( &v, 1 ), true ); + return *this; + } + + // Conversion + operator Bytes() const; + }; + + class Bytes: public SeqBase<Byte> + { + public: + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob != NULL && Py::_Bytes_Check( pyob ); + } + + virtual size_type capacity() const + { + return max_size(); + } + + explicit Bytes( PyObject *pyob, bool owned = false ) + : SeqBase<Byte>( pyob, owned ) + { + validate(); + } + + Bytes( const Object &ob ) + : SeqBase<Byte>( ob ) + { + validate(); + } + + Bytes() + : SeqBase<Byte>( PyBytes_FromStringAndSize( "", 0 ), true ) + { + validate(); + } + + Bytes( const std::string &v ) + : SeqBase<Byte>( PyBytes_FromStringAndSize( const_cast<char*>( v.data() ), v.length() ), true ) + { + validate(); + } + + Bytes( const std::string &v, Py_ssize_t vsize ) + : SeqBase<Byte>( PyBytes_FromStringAndSize( const_cast<char*>( v.data() ), vsize ), true ) + { + validate(); + } + + Bytes( const char *v ) + : SeqBase<Byte>( PyBytes_FromString( v ), true ) + { + validate(); + } + + Bytes( const char *v, Py_ssize_t vsize ) + : SeqBase<Byte>( PyBytes_FromStringAndSize( const_cast<char*>( v ), vsize ), true ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + Bytes &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Bytes &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + // Assignment from C string + Bytes &operator=( const std::string &v ) + { + set( PyBytes_FromStringAndSize( const_cast<char*>( v.data() ), v.length() ), true ); + return *this; + } + + String decode( const char *encoding, const char *error="strict" ); + + // Queries + virtual size_type size() const + { + return PyBytes_Size( ptr() ); + } + + operator std::string() const + { + return as_std_string(); + } + + std::string as_std_string() const + { + return std::string( PyBytes_AsString( ptr() ), static_cast<size_t>( PyBytes_Size( ptr() ) ) ); + } + }; + + class Char: public Object + { + public: + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return (pyob != 0 && + Py::_Unicode_Check( pyob ) && + PySequence_Length( pyob ) == 1); + } + + explicit Char( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Char( const Object &ob ) + : Object( ob ) + { + validate(); + } + + Char( int v ) + : Object( PyUnicode_FromOrdinal( v ), true ) + { + validate(); + } + +#ifndef Py_LIMITED_API + Char( Py_UNICODE v ) + : Object( PyUnicode_FromOrdinal( v ), true ) + { + validate(); + } +#endif + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + Char( const std::basic_string<wchar_t> &v ) + : Object( PyUnicode_FromWideChar( const_cast<wchar_t*>( v.data() ), 1 ), true ) + { + validate(); + } +#endif + +#ifndef Py_LIMITED_API + Char( const unicodestring &v ) + : Object( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true ) + { + validate(); + } +#endif + + // Assignment acquires new ownership of pointer + Char &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Char &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + Char &operator=( const std::basic_string<wchar_t> &v ) + { + set( PyUnicode_FromWideChar( const_cast<wchar_t*>( v.data() ), 1 ), true ); + return *this; + } +#endif + +#ifndef Py_LIMITED_API + Char &operator=( const unicodestring &v ) + { + set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true ); + return *this; + } +#endif + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + Char &operator=( int v_ ) + { + wchar_t v( static_cast<wchar_t>( v_ ) ); + set( PyUnicode_FromWideChar( &v, 1 ), true ); + return *this; + } +#endif + +#ifndef Py_LIMITED_API + Char &operator=( int v_ ) + { + Py_UNICODE v( static_cast<Py_UNICODE>( v_ ) ); + set( PyUnicode_FromUnicode( &v, 1 ), true ); + return *this; + } +#endif + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + Char &operator=( wchar_t v ) + { + set( PyUnicode_FromWideChar( &v, 1 ), true ); + return *this; + } +#endif + +#ifndef Py_LIMITED_API + Char &operator=( Py_UNICODE v ) + { + set( PyUnicode_FromUnicode( &v, 1 ), true ); + return *this; + } +#endif + + long ord() + { +#ifndef Py_LIMITED_API + if( PyUnicode_READY( ptr() ) == -1 ) + { + throw RuntimeError( "Char::ord() PyUnicode_READY() failed." ); + } + return static_cast<long>( PyUnicode_READ_CHAR( ptr(), 0 ) ); +#else + return static_cast<long>( PyUnicode_ReadChar( ptr(), 0 ) ); +#endif + } + + // Conversion + operator String() const; + }; + + class String: public SeqBase<Char> + { + public: + virtual size_type capacity() const + { + return max_size(); + } + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob != NULL && Py::_Unicode_Check( pyob ); + } + + explicit String( PyObject *pyob, bool owned = false ) + : SeqBase<Char>( pyob, owned ) + { + validate(); + } + + String( const Object &ob ) + : SeqBase<Char>( ob ) + { + validate(); + } + + String() + : SeqBase<Char>( PyUnicode_FromString( "" ), true ) + { + validate(); + } + + String( const char *latin1 ) + : SeqBase<Char>( PyUnicode_FromString( latin1 ), true ) + { + validate(); + } + + String( const std::string &latin1 ) + : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ), true ) + { + validate(); + } + + String( const char *latin1, Py_ssize_t size ) + : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ), true ) + { + validate(); + } + + /* [Taken from Pythons's unicode.h] + + Many of these APIs take two arguments encoding and errors. These + parameters encoding and errors have the same semantics as the ones + of the builtin unicode() API. + + Setting encoding to NULL causes the default encoding to be used. + + Error handling is set by errors which may also be set to NULL + meaning to use the default handling defined for the codec. Default + error handling for all builtin codecs is "strict" (ValueErrors are + raised). + + The codecs all use a similar interface. Only deviation from the + generic ones are documented. + + */ + String( const std::string &s, const char *encoding, const char *errors=NULL ) + : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.size(), encoding, errors ), true ) + { + validate(); + } + + String( const char *s, const char *encoding, const char *errors=NULL ) + : SeqBase<Char>( PyUnicode_Decode( s, strlen(s), encoding, errors ), true ) + { + validate(); + } + + String( const char *s, Py_ssize_t size, const char *encoding, const char *errors=NULL ) + : SeqBase<Char>( PyUnicode_Decode( s, size, encoding, errors ), true ) + { + validate(); + } +#if !defined( Py_UNICODE_WIDE ) && !defined( Py_LIMITED_API ) + // Need these c'tors becuase Py_UNICODE is 2 bytes + // User may use "int" or "unsigned int" as the unicode type + String( const unsigned int *s, int length ) + : SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( s ), length ), true ) + { + validate(); + } + + String( const int *s, int length ) + : SeqBase<Char>( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( s ), length ), true ) + { + validate(); + } +#endif + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + String( const wchar_t *s, int length ) + : SeqBase<Char>( PyUnicode_FromWideChar( s, length ), true ) + { + validate(); + } +#endif + +#ifndef Py_LIMITED_API + String( const Py_UNICODE *s, int length ) + : SeqBase<Char>( PyUnicode_FromUnicode( s, length ), true ) + { + validate(); + } +#endif + // Assignment acquires new ownership of pointer + String &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + String &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + String &operator=( const std::basic_string<wchar_t> &v ) + { + set( PyUnicode_FromWideChar( const_cast<wchar_t *>( v.data() ), v.length() ), true ); + return *this; + } +#endif + +#ifndef Py_LIMITED_API + String &operator=( const unicodestring &v ) + { + set( PyUnicode_FromUnicode( const_cast<Py_UNICODE *>( v.data() ), v.length() ), true ); + return *this; + } +#endif + +#if !defined( Py_UNICODE_WIDE ) && !defined( Py_LIMITED_API ) + String &operator=( const ucs4string &v ) + { + set( PyUnicode_FromKindAndData( PyUnicode_4BYTE_KIND, reinterpret_cast<const Py_UCS4 *>( v.data() ), v.length() ), true ); + return *this; + } +#endif + // Encode + Bytes encode( const char *encoding, const char *error="strict" ) const + { + return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); + } + + // Queries + virtual size_type size() const + { + return PyUnicode_GetLength( ptr() ); + } + +#if defined( Py_LIMITED_API ) && defined( HAVE_WCHAR_H ) + const wchar_t *as_wchar_string() const + { + return PyUnicode_AsWideCharString( ptr(), NULL ); + } +#endif + +#ifndef Py_LIMITED_API + const Py_UNICODE *unicode_data() const + { + return PyUnicode_AS_UNICODE( ptr() ); + } +#endif + +#ifndef Py_LIMITED_API + unicodestring as_unicodestring() const + { + return unicodestring( unicode_data(), PyUnicode_GET_SIZE( ptr() ) ); + } + + ucs4string as_ucs4string() const + { + Py_UCS4 *buf = new Py_UCS4[ size() ]; + if( PyUnicode_AsUCS4( ptr(), buf, size(), 0 ) == NULL ) + { + ifPyErrorThrowCxxException(); + } + ucs4string ucs4( buf, size() ); + delete[] buf; + + return ucs4; + } +#endif + + operator std::string() const + { + // use the default encoding + return as_std_string( NULL ); + } + + std::string as_std_string( const char *encoding=NULL, const char *error="strict" ) const + { + Bytes b( encode( encoding, error ) ); + return b.as_std_string(); + } + }; + + // ================================================== + // class Tuple + class Tuple: public Sequence + { + public: + virtual void setItem( sequence_index_type offset, const Object&ob ) + { + // note PyTuple_SetItem is a thief... + if( PyTuple_SetItem( ptr(), offset, new_reference_to( ob ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + // Constructor + explicit Tuple( PyObject *pyob, bool owned = false ) + : Sequence( pyob, owned ) + { + validate(); + } + + Tuple( const Object &ob ) + : Sequence( ob ) + { + validate(); + } + + // New tuple of a given size + explicit Tuple( int size=0 ) + { + set( PyTuple_New( size ), true ); + validate(); + for( sequence_index_type i=0; i < size; i++ ) + { + if( PyTuple_SetItem( ptr(), i, new_reference_to( Py::_None() ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + } + // Tuple from any sequence + explicit Tuple( const Sequence &s ) + { + sequence_index_type limit( sequence_index_type( s.length() ) ); + + set( PyTuple_New( limit ), true ); + validate(); + + for( sequence_index_type i=0; i < limit; i++ ) + { + if( PyTuple_SetItem( ptr(), i, new_reference_to( s[i] ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + } + + // Assignment acquires new ownership of pointer + Tuple &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Tuple &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Tuple_Check( pyob ); + } + + Tuple getSlice( int i, int j ) const + { + return Tuple( PySequence_GetSlice( ptr(), i, j ), true ); + } + + }; + + class TupleN: public Tuple + { + public: + TupleN() + : Tuple( 0 ) + { + } + + TupleN( const Object &obj1 ) + : Tuple( 1 ) + { + setItem( 0, obj1 ); + } + + TupleN( const Object &obj1, const Object &obj2 ) + : Tuple( 2 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3 ) + : Tuple( 3 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4 ) + : Tuple( 4 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5 ) + : Tuple( 5 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6 ) + : Tuple( 6 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7 ) + : Tuple( 7 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7, const Object &obj8 ) + : Tuple( 8 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + setItem( 7, obj8 ); + } + + TupleN( const Object &obj1, const Object &obj2, const Object &obj3, + const Object &obj4, const Object &obj5, const Object &obj6, + const Object &obj7, const Object &obj8, const Object &obj9 ) + : Tuple( 9 ) + { + setItem( 0, obj1 ); + setItem( 1, obj2 ); + setItem( 2, obj3 ); + setItem( 3, obj4 ); + setItem( 4, obj5 ); + setItem( 5, obj6 ); + setItem( 6, obj7 ); + setItem( 7, obj8 ); + setItem( 8, obj9 ); + } + + virtual ~TupleN() + { } + }; + + // ================================================== + // class List + + class List: public Sequence + { + public: + // Constructor + explicit List( PyObject *pyob, bool owned = false ) + : Sequence( pyob, owned ) + { + validate(); + } + List( const Object &ob ) + : Sequence( ob ) + { + validate(); + } + // Creation at a fixed size + List( size_type size = 0 ) + { + set( PyList_New( size ), true ); + validate(); + for( sequence_index_type i=0; i < size; i++ ) + { + if( PyList_SetItem( ptr(), i, new_reference_to( Py::_None() ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + } + + // List from a sequence + List( const Sequence &s ) + : Sequence() + { + size_type n = s.length(); + set( PyList_New( n ), true ); + validate(); + for( sequence_index_type i=0; i < n; i++ ) + { + if( PyList_SetItem( ptr(), i, new_reference_to( s[i] ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + } + + virtual size_type capacity() const + { + return max_size(); + } + + // Assignment acquires new ownership of pointer + List &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + List &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_List_Check( pyob ); + } + + List getSlice( int i, int j ) const + { + return List( PyList_GetSlice( ptr(), i, j ), true ); + } + + void setSlice( Py_ssize_t i, Py_ssize_t j, const Object &v ) + { + if( PyList_SetSlice( ptr(), i, j, *v ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void append( const Object &ob ) + { + if( PyList_Append( ptr(), *ob ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void extend( const Object &ob ) + { + setSlice( size(), size(), ob ); + } + + void insert( int i, const Object &ob ) + { + if( PyList_Insert( ptr(), i, *ob ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void sort() + { + if( PyList_Sort( ptr() ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void reverse() + { + if( PyList_Reverse( ptr() ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + }; + + + // Mappings + // ================================================== + template<TEMPLATE_TYPENAME T> + class mapref + { + protected: + MapBase<T> &s; // the map + Object key; // item key + T the_item; + + public: + mapref<T>( MapBase<T> &map, const std::string &k ) + : s( map ), the_item() + { + key = String( k ); + if( map.hasKey( key ) ) the_item = map.getItem( key ); + } + + mapref<T>( MapBase<T> &map, const Object &k ) + : s( map ), key( k ), the_item() + { + if( map.hasKey( key ) ) the_item = map.getItem( key ); + } + + virtual ~mapref<T>() + {} + + // MapBase<T> stuff + // lvalue + mapref<T> &operator=( const mapref<T> &other ) + { + if( this != &other ) + { + the_item = other.the_item; + s.setItem( key, other.the_item ); + } + return *this; + } + + mapref<T> &operator=( const T &ob ) + { + the_item = ob; + s.setItem( key, ob ); + return *this; + } + + // rvalue + operator T() const + { + return the_item; + } + + // forward everything else to the_item + PyObject *ptr() const + { + return the_item.ptr(); + } + + int reference_count() const + { // the mapref count + return the_item.reference_count(); + } + + Type type() const + { + return the_item.type(); + } + + String str() const + { + return the_item.str(); + } + + String repr() const + { + return the_item.repr(); + } + + bool hasAttr( const std::string &attr_name ) const + { + return the_item.hasAttr( attr_name ); + } + + Object getAttr( const std::string &attr_name ) const + { + return the_item.getAttr( attr_name ); + } + + Object getItem( const Object &k ) const + { + return the_item.getItem( k ); + } + + long hashValue() const + { + return the_item.hashValue(); + } + + bool isCallable() const + { + return the_item.isCallable(); + } + + bool isInstance() const + { + return the_item.isInstance(); + } + + bool isList() const + { + return the_item.isList(); + } + + bool isMapping() const + { + return the_item.isMapping(); + } + + bool isNumeric() const + { + return the_item.isNumeric(); + } + + bool isSequence() const + { + return the_item.isSequence(); + } + + bool isTrue() const + { + return the_item.isTrue(); + } + + bool isType( const Type &t ) const + { + return the_item.isType( t ); + } + + bool isTuple() const + { + return the_item.isTuple(); + } + + bool isString() const + { + return the_item.isString(); + } + + // Commands + void setAttr( const std::string &attr_name, const Object &value ) + { + the_item.setAttr( attr_name, value ); + } + + void delAttr( const std::string &attr_name ) + { + the_item.delAttr( attr_name ); + } + + void delItem( const Object &k ) + { + the_item.delItem( k ); + } + }; // end of mapref + +#if 0 + // TMM: now for mapref<T> + template< class T > + bool operator==( const mapref<T> &left, const mapref<T> &right ) + { + return true; // NOT completed. + } + + template< class T > + bool operator!=( const mapref<T> &left, const mapref<T> &right ) + { + return true; // not completed. + } +#endif + + template<TEMPLATE_TYPENAME T> + class MapBase: public Object + { + protected: + explicit MapBase<T>() + {} + public: + // reference: proxy class for implementing [] + // TMM: 26Jun'01 - the types + // If you assume that Python mapping is a hash_map... + // hash_map::value_type is not assignable, but + //( *it ).second = data must be a valid expression + typedef PyCxx_ssize_t size_type; + typedef Object key_type; + typedef mapref<T> data_type; + typedef std::pair< const T, T > value_type; + typedef std::pair< const T, mapref<T> > reference; + typedef const std::pair< const T, const T > const_reference; + typedef std::pair< const T, mapref<T> > pointer; + + // Constructor + explicit MapBase<T>( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + // TMM: 02Jul'01 - changed MapBase<T> to Object in next line + MapBase<T>( const Object &ob ) + : Object( ob ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + MapBase<T> &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + MapBase<T> &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && PyMapping_Check( pyob ); + } + + // Clear -- PyMapping Clear is missing + // + + void clear() + { + List k = keys(); + for( List::iterator i = k.begin(); i != k.end(); i++ ) + { + delItem( *i ); + } + } + + virtual Py_ssize_t size() const + { + return PyMapping_Length( ptr() ); + } + + // Element Access + T operator[]( const std::string &key ) const + { + return getItem( key ); + } + + T operator[]( const Object &key ) const + { + return getItem( key ); + } + + mapref<T> operator[]( const char *key ) + { + return mapref<T>( *this, key ); + } + + mapref<T> operator[]( const std::string &key ) + { + return mapref<T>( *this, key ); + } + + mapref<T> operator[]( const Object &key ) + { + return mapref<T>( *this, key ); + } + + Py_ssize_t length() const + { + return PyMapping_Length( ptr() ); + } + + bool hasKey( const std::string &s ) const + { + return PyMapping_HasKeyString( ptr(),const_cast<char*>( s.c_str() ) ) != 0; + } + + bool hasKey( const Object &s ) const + { + return PyMapping_HasKey( ptr(), s.ptr() ) != 0; + } + + T getItem( const std::string &s ) const + { + return T( asObject( PyMapping_GetItemString( ptr(),const_cast<char*>( s.c_str() ) ) ) ); + } + + T getItem( const Object &s ) const + { + return T( asObject( PyObject_GetItem( ptr(), s.ptr() ) ) ); + } + + virtual void setItem( const char *s, const Object &ob ) + { + if( PyMapping_SetItemString( ptr(), const_cast<char*>( s ), *ob ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + virtual void setItem( const std::string &s, const Object &ob ) + { + if( PyMapping_SetItemString( ptr(), const_cast<char*>( s.c_str() ), *ob ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + virtual void setItem( const Object &s, const Object &ob ) + { + if( PyObject_SetItem( ptr(), s.ptr(), ob.ptr() ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void delItem( const std::string &s ) + { + if( PyMapping_DelItemString( ptr(), const_cast<char*>( s.c_str() ) ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + void delItem( const Object &s ) + { + if( PyMapping_DelItem( ptr(), *s ) == -1 ) + { + ifPyErrorThrowCxxException(); + } + } + + // Queries + List keys() const + { + return List( PyMapping_Keys( ptr() ), true ); + } + + List values() const + { + // each returned item is a (key, value) pair + return List( PyMapping_Values( ptr() ), true ); + } + + List items() const + { + return List( PyMapping_Items( ptr() ), true ); + } + + class iterator + { + // : public forward_iterator_parent( std::pair<const T,T> ) { + protected: + typedef std::forward_iterator_tag iterator_category; + typedef std::pair< const T, T > value_type; + typedef int difference_type; + typedef std::pair< const T, mapref<T> > pointer; + typedef std::pair< const T, mapref<T> > reference; + + friend class MapBase<T>; + // + MapBase<T> *map; + List keys; // for iterating over the map + sequence_index_type pos; // index into the keys + + public: + ~iterator() + {} + + iterator() + : map( 0 ) + , keys() + , pos( 0 ) + {} + + iterator( MapBase<T> *m, bool end = false ) + : map( m ) + , keys( m->keys() ) + , pos( end ? keys.length() : 0 ) + {} + + iterator( const iterator &other ) + : map( other.map ) + , keys( other.keys ) + , pos( other.pos ) + {} + + iterator( MapBase<T> *map_, List keys_, int pos_ ) + : map( map_ ) + , keys( keys_ ) + , pos( pos_ ) + {} + + reference operator*() + { + Object key = keys[ pos ]; + return std::make_pair( key, mapref<T>( *map, key ) ); + } + + iterator &operator=( const iterator &other ) + { + if( this != &other ) + { + map = other.map; + keys = other.keys; + pos = other.pos; + } + return *this; + } + + bool eql( const iterator &other ) const + { + return map->ptr() == other.map->ptr() && pos == other.pos; + } + + bool neq( const iterator &other ) const + { + return map->ptr() != other.map->ptr() || pos != other.pos; + } + + // pointer operator->() { + // return ; + // } + + // prefix ++ + iterator &operator++() + { + pos++; + return *this; + } + + // postfix ++ + iterator operator++( int ) + { + return iterator( map, keys, pos++ ); + } + + // prefix -- + iterator &operator--() + { + pos--; + return *this; + } + + // postfix -- + iterator operator--( int ) + { + return iterator( map, keys, pos-- ); + } + + std::string diagnose() const + { + std::OSTRSTREAM oss; + oss << "iterator diagnosis " << map << ", " << pos << std::ends; + return std::string( oss.str() ); + } + }; // end of class MapBase<T>::iterator + + iterator begin() + { + return iterator( this, false ); + } + + iterator end() + { + return iterator( this, true ); + } + + class const_iterator + { + protected: + typedef std::forward_iterator_tag iterator_category; + typedef const std::pair< const T, T > value_type; + typedef int difference_type; + typedef const std::pair< const T, T > pointer; + typedef const std::pair< const T, T > reference; + + friend class MapBase<T>; + const MapBase<T> *map; + List keys; // for iterating over the map + Py_ssize_t pos; // index into the keys + + public: + ~const_iterator() + {} + + const_iterator() + : map( 0 ) + , keys() + , pos() + {} + + const_iterator( const MapBase<T> *m, List k, Py_ssize_t p ) + : map( m ) + , keys( k ) + , pos( p ) + {} + + const_iterator( const const_iterator &other ) + : map( other.map ) + , keys( other.keys ) + , pos( other.pos ) + {} + + bool eql( const const_iterator &other ) const + { + return map->ptr() == other.map->ptr() && pos == other.pos; + } + + bool neq( const const_iterator &other ) const + { + return map->ptr() != other.map->ptr() || pos != other.pos; + } + + + // const_reference operator*() { + // Object key = *pos; + // return std::make_pair( key, map->[key] ); + // GCC < 3 barfes on this line at the '['. + // } + + const_reference operator*() + { + Object key = keys[ pos ]; + return std::make_pair( key, mapref<T>( *map, key ) ); + } + + const_iterator &operator=( const const_iterator &other ) + { + if( this != &other ) + { + map = other.map; + keys = other.keys; + pos = other.pos; + } + return *this; + } + + // prefix ++ + const_iterator &operator++() + { + pos++; + return *this; + } + + // postfix ++ + const_iterator operator++( int ) + { + return const_iterator( map, keys, pos++ ); + } + + // prefix -- + const_iterator &operator--() + { + pos--; + return *this; + } + + // postfix -- + const_iterator operator--( int ) + { + return const_iterator( map, keys, pos-- ); + } + }; // end of class MapBase<T>::const_iterator + + const_iterator begin() const + { + return const_iterator( this, keys(), 0 ); + } + + const_iterator end() const + { + return const_iterator( this, keys(), length() ); + } + + }; // end of MapBase<T> + + typedef MapBase<Object> Mapping; + + template <TEMPLATE_TYPENAME T> bool operator==( const EXPLICIT_TYPENAME MapBase<T>::iterator &left, const EXPLICIT_TYPENAME MapBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator!=( const EXPLICIT_TYPENAME MapBase<T>::iterator &left, const EXPLICIT_TYPENAME MapBase<T>::iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator==( const EXPLICIT_TYPENAME MapBase<T>::const_iterator &left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator &right ); + template <TEMPLATE_TYPENAME T> bool operator!=( const EXPLICIT_TYPENAME MapBase<T>::const_iterator &left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator &right ); + + extern bool operator==( const Mapping::iterator &left, const Mapping::iterator &right ); + extern bool operator!=( const Mapping::iterator &left, const Mapping::iterator &right ); + extern bool operator==( const Mapping::const_iterator &left, const Mapping::const_iterator &right ); + extern bool operator!=( const Mapping::const_iterator &left, const Mapping::const_iterator &right ); + + + // ================================================== + // class Dict + class Dict: public Mapping + { + public: + // Constructor + explicit Dict( PyObject *pyob, bool owned=false ) + : Mapping( pyob, owned ) + { + validate(); + } + + Dict( const Object &ob ) + : Mapping( ob ) + { + validate(); + } + + // Creation + Dict() + { + set( PyDict_New(), true ); + validate(); + } + + // Assignment acquires new ownership of pointer + Dict &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Dict &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && Py::_Dict_Check( pyob ); + } + }; + + class Callable: public Object + { + public: + // Constructor + explicit Callable() + : Object() + {} + + explicit Callable( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + Callable( const Object &ob ) + : Object( ob ) + { + validate(); + } + + // Assignment acquires new ownership of pointer + Callable &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Callable &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + { + set( rhsp ); + } + return *this; + } + + // Membership + virtual bool accepts( PyObject *pyob ) const + { + return pyob && PyCallable_Check( pyob ); + } + + // Call + Object apply( const Tuple &args ) const + { + PyObject *result = PyObject_CallObject( ptr(), args.ptr() ); + if( result == NULL ) + { + ifPyErrorThrowCxxException(); + } + return asObject( result ); + } + + // Call with keywords + Object apply( const Tuple &args, const Dict &kw ) const + { + PyObject *result = PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ); + if( result == NULL ) + { + ifPyErrorThrowCxxException(); + } + return asObject( result ); + } + + Object apply( PyObject *pargs = 0 ) const + { + if( pargs == 0 ) + { + return apply( Tuple() ); + } + else + { + return apply( Tuple( pargs ) ); + } + } + }; + + class Module: public Object + { + public: + explicit Module( PyObject *pyob, bool owned = false ) + : Object( pyob, owned ) + { + validate(); + } + + // Construct from module name + explicit Module( const std::string &s ) + : Object() + { + PyObject *m = PyImport_AddModule( const_cast<char *>( s.c_str() ) ); + set( m, false ); + validate(); + } + + // Copy constructor acquires new ownership of pointer + Module( const Module &ob ) + : Object( *ob ) + { + validate(); + } + + Module &operator=( const Object &rhs ) + { + return *this = *rhs; + } + + Module &operator=( PyObject *rhsp ) + { + if( ptr() != rhsp ) + set( rhsp ); + return *this; + } + + Dict getDict() const + { + return Dict( PyModule_GetDict( ptr() ) ); + // Caution -- PyModule_GetDict returns borrowed reference! + } + }; + + // Call function helper + inline Object Object::callMemberFunction( const std::string &function_name ) const + { + Callable target( getAttr( function_name ) ); + Tuple args( 0 ); + return target.apply( args ); + } + + inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const + { + Callable target( getAttr( function_name ) ); + return target.apply( args ); + } + + inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const + { + Callable target( getAttr( function_name ) ); + return target.apply( args, kw ); + } + + // Numeric interface + inline Object operator+( const Object &a ) + { + return asObject( PyNumber_Positive( *a ) ); + } + + inline Object operator-( const Object &a ) + { + return asObject( PyNumber_Negative( *a ) ); + } + + inline Object abs( const Object &a ) + { + return asObject( PyNumber_Absolute( *a ) ); + } + + //------------------------------------------------------------ + // operator + + inline Object operator+( const Object &a, const Object &b ) + { + return asObject( PyNumber_Add( *a, *b ) ); + } + + inline Object operator+( const Object &a, int j ) + { + return asObject( PyNumber_Add( *a, *Long( j ) ) ); + } + + inline Object operator+( const Object &a, long j ) + { + return asObject( PyNumber_Add( *a, *Long( j ) ) ); + } + + inline Object operator+( const Object &a, double v ) + { + return asObject( PyNumber_Add( *a, *Float( v ) ) ); + } + + inline Object operator+( int j, const Object &b ) + { + return asObject( PyNumber_Add( *Long( j ), *b ) ); + } + + inline Object operator+( long j, const Object &b ) + { + return asObject( PyNumber_Add( *Long( j ), *b ) ); + } + + inline Object operator+( double v, const Object &b ) + { + return asObject( PyNumber_Add( *Float( v ), *b ) ); + } + + //------------------------------------------------------------ + // operator - + inline Object operator-( const Object &a, const Object &b ) + { + return asObject( PyNumber_Subtract( *a, *b ) ); + } + + inline Object operator-( const Object &a, int j ) + { + return asObject( PyNumber_Subtract( *a, *Long( j ) ) ); + } + + inline Object operator-( const Object &a, double v ) + { + return asObject( PyNumber_Subtract( *a, *Float( v ) ) ); + } + + inline Object operator-( int j, const Object &b ) + { + return asObject( PyNumber_Subtract( *Long( j ), *b ) ); + } + + inline Object operator-( double v, const Object &b ) + { + return asObject( PyNumber_Subtract( *Float( v ), *b ) ); + } + + //------------------------------------------------------------ + // operator * + inline Object operator*( const Object &a, const Object &b ) + { + return asObject( PyNumber_Multiply( *a, *b ) ); + } + + inline Object operator*( const Object &a, int j ) + { + return asObject( PyNumber_Multiply( *a, *Long( j ) ) ); + } + + inline Object operator*( const Object &a, double v ) + { + return asObject( PyNumber_Multiply( *a, *Float( v ) ) ); + } + + inline Object operator*( int j, const Object &b ) + { + return asObject( PyNumber_Multiply( *Long( j ), *b ) ); + } + + inline Object operator*( double v, const Object &b ) + { + return asObject( PyNumber_Multiply( *Float( v ), *b ) ); + } + + //------------------------------------------------------------ + // operator / + inline Object operator/( const Object &a, const Object &b ) + { + return asObject( PyNumber_TrueDivide( *a, *b ) ); + } + + inline Object operator/( const Object &a, int j ) + { + return asObject( PyNumber_TrueDivide( *a, *Long( j ) ) ); + } + + inline Object operator/( const Object &a, double v ) + { + return asObject( PyNumber_TrueDivide( *a, *Float( v ) ) ); + } + + inline Object operator/( int j, const Object &b ) + { + return asObject( PyNumber_TrueDivide( *Long( j ), *b ) ); + } + + inline Object operator/( double v, const Object &b ) + { + return asObject( PyNumber_TrueDivide( *Float( v ), *b ) ); + } + + //------------------------------------------------------------ + // operator % + inline Object operator%( const Object &a, const Object &b ) + { + return asObject( PyNumber_Remainder( *a, *b ) ); + } + + inline Object operator%( const Object &a, int j ) + { + return asObject( PyNumber_Remainder( *a, *Long( j ) ) ); + } + + inline Object operator%( const Object &a, double v ) + { + return asObject( PyNumber_Remainder( *a, *Float( v ) ) ); + } + + inline Object operator%( int j, const Object &b ) + { + return asObject( PyNumber_Remainder( *Long( j ), *b ) ); + } + + inline Object operator%( double v, const Object &b ) + { + return asObject( PyNumber_Remainder( *Float( v ), *b ) ); + } + + //------------------------------------------------------------ + // type + inline Object type( const BaseException & ) // return the type of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch( &ptype, &pvalue, &ptrace ); + Object result; + if( ptype ) + result = ptype; + PyErr_Restore( ptype, pvalue, ptrace ); + return result; + } + + inline Object value( const BaseException & ) // return the value of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch( &ptype, &pvalue, &ptrace ); + Object result; + if( pvalue ) + result = pvalue; + PyErr_Restore( ptype, pvalue, ptrace ); + return result; + } + + inline Object trace( const BaseException & ) // return the traceback of the error + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch( &ptype, &pvalue, &ptrace ); + Object result; + if( ptrace ) + result = ptrace; + PyErr_Restore( ptype, pvalue, ptrace ); + return result; + } + + template<TEMPLATE_TYPENAME T> + String seqref<T>::str() const + { + return the_item.str(); + } + + template<TEMPLATE_TYPENAME T> + String seqref<T>::repr() const + { + return the_item.repr(); + } + +} // namespace Py +#endif // __CXX_Objects__h diff --git a/contrib/libs/pycxx/Python3/PythonType.hxx b/contrib/libs/pycxx/Python3/PythonType.hxx new file mode 100755 index 00000000000..6a9087b6964 --- /dev/null +++ b/contrib/libs/pycxx/Python3/PythonType.hxx @@ -0,0 +1,207 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __CXX_PythonType__h +#define __CXX_PythonType__h + +#include <unordered_map> + +namespace Py +{ + class PythonType + { + public: + // if you define one sequence method you must define + // all of them except the assigns + + PythonType( size_t base_size, int itemsize, const char *default_name ); + virtual ~PythonType(); + + const char *getName() const; + const char *getDoc() const; + + PyTypeObject *type_object() const; + PythonType &name( const char *nam ); + PythonType &doc( const char *d ); + + PythonType &supportClass( void ); +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) + PythonType &supportPrint( void ); +#endif + PythonType &supportGetattr( void ); + PythonType &supportSetattr( void ); + PythonType &supportGetattro( void ); + PythonType &supportSetattro( void ); +#ifdef PYCXX_PYTHON_2TO3 + PythonType &supportCompare( void ); +#endif + PythonType &supportRichCompare( void ); + PythonType &supportRepr( void ); + PythonType &supportStr( void ); + PythonType &supportHash( void ); + PythonType &supportCall( void ); + +#define B( n ) (1<<(n)) + enum { + support_iter_iter = B(0), + support_iter_iternext = B(1) + }; + PythonType &supportIter( int methods_to_support= + support_iter_iter | + support_iter_iternext ); + + enum { + support_sequence_length = B(0), + support_sequence_repeat = B(1), + support_sequence_item = B(2), + support_sequence_slice = B(3), + support_sequence_concat = B(4), + support_sequence_ass_item = B(5), + support_sequence_ass_slice = B(6), + support_sequence_inplace_concat = B(7), + support_sequence_inplace_repeat = B(8), + support_sequence_contains = B(9) + }; + PythonType &supportSequenceType( int methods_to_support= + support_sequence_length | + support_sequence_repeat | + support_sequence_item | + support_sequence_slice | + support_sequence_concat + ); + + enum { + support_mapping_length = B(0), + support_mapping_subscript = B(1), + support_mapping_ass_subscript = B(2) + }; + PythonType &supportMappingType( int methods_to_support= + support_mapping_length | + support_mapping_subscript + ); + + enum { + support_number_add = B(0), + support_number_subtract = B(1), + support_number_multiply = B(2), + support_number_remainder = B(3), + support_number_divmod = B(4), + support_number_power = B(5), + support_number_negative = B(6), + support_number_positive = B(7), + support_number_absolute = B(8), + support_number_invert = B(9), + support_number_lshift = B(10), + support_number_rshift = B(11), + support_number_and = B(12), + support_number_xor = B(13), + support_number_or = B(14), + support_number_int = B(15), + support_number_float= B(16) + }; + PythonType &supportNumberType( int methods_to_support= + support_number_add | + support_number_subtract | + support_number_multiply | + support_number_remainder | + support_number_divmod | + support_number_power | + support_number_negative | + support_number_positive | + support_number_absolute | + support_number_invert | + support_number_lshift | + support_number_rshift | + support_number_and | + support_number_xor | + support_number_or | + support_number_int | + support_number_float + ); +#ifndef Py_LIMITED_API + enum { + support_buffer_getbuffer = B(0), + support_buffer_releasebuffer = B(1) + }; + PythonType &supportBufferType( int methods_to_support= + support_buffer_getbuffer | + support_buffer_releasebuffer + ); +#endif +#undef B + + PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) ); + PythonType &set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ); + PythonType &set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ); + PythonType &set_methods( PyMethodDef *methods ); + + // call once all support functions have been called to ready the type + bool readyType(); + + protected: + void init_sequence(); + void init_mapping(); + void init_number(); +#ifndef Py_LIMITED_API + void init_buffer(); +#endif + +#ifdef Py_LIMITED_API + std::unordered_map<int, void*> slots; + PyType_Spec *spec; + PyTypeObject *tp_object; +#else + PyTypeObject *table; + PySequenceMethods *sequence_table; + PyMappingMethods *mapping_table; + PyNumberMethods *number_table; + PyBufferProcs *buffer_table; +#endif + + private: + // + // prevent the compiler generating these unwanted functions + // + PythonType( const PythonType &tb ); // unimplemented + void operator=( const PythonType &t ); // unimplemented + + }; + +} // Namespace Py + +// End of __CXX_PythonType__h +#endif diff --git a/contrib/libs/pycxx/Python3/cxx_exceptions.cxx b/contrib/libs/pycxx/Python3/cxx_exceptions.cxx new file mode 100644 index 00000000000..9dff2753ddd --- /dev/null +++ b/contrib/libs/pycxx/Python3/cxx_exceptions.cxx @@ -0,0 +1,72 @@ +// +// cxx_exceptions.cxx +// +#include "../Exception.hxx" +#include "../Extensions.hxx" + +#include <map> + +namespace Py +{ +typedef void (*throw_exception_func_t)( PyObject* exc ); + +std::map<void *, throw_exception_func_t> py_exc_type_to_exc_func; + +void addPythonException( ExtensionExceptionType &py_exc_type, throw_exception_func_t func ) +{ + py_exc_type_to_exc_func.insert( std::make_pair( py_exc_type.ptr(), func ) ); +} + +void addPythonException( PyObject *py_exc_type, throw_exception_func_t func ) +{ + py_exc_type_to_exc_func.insert( std::make_pair( py_exc_type, func ) ); +} + +void ifPyErrorThrowCxxException() +{ + if( PyErr_Occurred() ) + { + PyObject *ptype, *pvalue, *ptrace; + PyErr_Fetch( &ptype, &pvalue, &ptrace ); + PyErr_Restore( ptype, pvalue, ptrace ); + + Object q( ptype ); + + std::map<void *, throw_exception_func_t>::iterator func = py_exc_type_to_exc_func.find( ptype ); + if( func != py_exc_type_to_exc_func.end() ) + { +#ifdef PYCXX_DEBUG + std::cout << "ifPyErrorThrowCxxException found throwFunc: " << q << std::endl; +#endif + (func->second)(pvalue); + } + else + { +#ifdef PYCXX_DEBUG + std::cout << "ifPyErrorThrowCxxException no throwFunc: " << q << std::endl; +#endif + throw Exception(); + } + } +} + +void initExceptions() +{ + static bool init_done = false; + if( init_done ) + { + return; + } + +#define PYCXX_STANDARD_EXCEPTION( eclass, bclass ) \ + addPythonException( eclass::exceptionType(), eclass::throwFuncObj ); + +#include "cxx_standard_exceptions.hxx" + +#undef PYCXX_STANDARD_EXCEPTION + + init_done = true; +} + + +} // end of namespace Py diff --git a/contrib/libs/pycxx/Python3/cxx_extensions.cxx b/contrib/libs/pycxx/Python3/cxx_extensions.cxx new file mode 100644 index 00000000000..342174e21c1 --- /dev/null +++ b/contrib/libs/pycxx/Python3/cxx_extensions.cxx @@ -0,0 +1,2265 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#if defined( Py_LIMITED_API ) && Py_LIMITED_API+0 < 0x03040000 +#error "PyCXX does not support limited API for Python below 3.4" +#endif + +#include "../Extensions.hxx" +#include "../Exception.hxx" +#include "../Objects.hxx" + +#include <assert.h> + +#ifdef PYCXX_DEBUG +// +// Functions useful when debugging PyCXX +// +void bpt( void ) +{ +} + +void printRefCount( PyObject *obj ) +{ + std::cout << "RefCount of 0x" << std::hex << reinterpret_cast< unsigned long >( obj ) << std::dec << " is " << Py_REFCNT( obj ) << std::endl; +} +#endif + +namespace Py +{ + +void Object::validate() +{ + // release pointer if not the right type + if( !accepts( p ) ) + { +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + std::string s( "PyCXX: Error creating object of type " ); + s += (typeid( *this )).name(); + + if( p != NULL ) + { + String from_repr = repr(); + s += " from "; + s += from_repr.as_std_string(); + } + else + { + s += " from (nil)"; + } +#endif + release(); + + // If error message already set + ifPyErrorThrowCxxException(); + + // Better error message if RTTI available +#if defined( _CPPRTTI ) || defined( __GNUG__ ) + throw TypeError( s ); +#else + throw TypeError( "PyCXX: type error." ); +#endif + } +} + +//================================================================================ +// +// Implementation of MethodTable +// +//================================================================================ + +PyMethodDef MethodTable::method( const char *method_name, PyCFunction f, int flags, const char *doc ) +{ + PyMethodDef m; + m.ml_name = const_cast<char *>( method_name ); + m.ml_meth = f; + m.ml_flags = flags; + m.ml_doc = const_cast<char *>( doc ); + return m; +} + +MethodTable::MethodTable() +{ + t.push_back( method( 0, 0, 0, 0 ) ); + mt = NULL; +} + +MethodTable::~MethodTable() +{ + delete [] mt; +} + +void MethodTable::add( const char *method_name, PyCFunction f, const char *doc, int flag ) +{ + if( !mt ) + { + t.insert( t.end()-1, method( method_name, f, flag, doc ) ); + } + else + { + throw RuntimeError( "Too late to add a module method!" ); + } +} + +PyMethodDef *MethodTable::table() +{ + if( !mt ) + { + Py_ssize_t t1size = t.size(); + mt = new PyMethodDef[ t1size ]; + int j = 0; + for( std::vector<PyMethodDef>::iterator i = t.begin(); i != t.end(); i++ ) + { + mt[ j++ ] = *i; + } + } + return mt; +} + +//================================================================================ +// +// Implementation of ExtensionModule +// +//================================================================================ +ExtensionModuleBase::ExtensionModuleBase( const char *name ) +: m_module_name( name ) +#ifdef Py_LIMITED_API +, m_full_module_name( m_module_name ) +#else +, m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) +#endif +, m_method_table() +//m_module_def +, m_module( NULL ) +{} + +ExtensionModuleBase::~ExtensionModuleBase() +{} + +const std::string &ExtensionModuleBase::name() const +{ + return m_module_name; +} + +const std::string &ExtensionModuleBase::fullName() const +{ + return m_full_module_name; +} + +class ExtensionModuleBasePtr : public PythonExtension<ExtensionModuleBasePtr> +{ +public: + ExtensionModuleBasePtr( ExtensionModuleBase *_module ) + : module( _module ) + {} + + virtual ~ExtensionModuleBasePtr() + {} + + ExtensionModuleBase *module; +}; + +void initExceptions(); + +void ExtensionModuleBase::initialize( const char *module_doc ) +{ + // init the exception code + initExceptions(); + + memset( &m_module_def, 0, sizeof( m_module_def ) ); + + m_module_def.m_name = const_cast<char *>( m_module_name.c_str() ); + m_module_def.m_doc = const_cast<char *>( module_doc ); + m_module_def.m_methods = m_method_table.table(); + // where does module_ptr get passed in? + + m_module = PyModule_Create( &m_module_def ); +} + +Module ExtensionModuleBase::module( void ) const +{ + return Module( m_module ); +} + +Dict ExtensionModuleBase::moduleDictionary( void ) const +{ + return module().getDict(); +} + +Object ExtensionModuleBase::moduleObject( void ) const +{ + return Object( m_module ); +} + +//================================================================================ +// +// Implementation of PythonType +// +//================================================================================ +extern "C" +{ + static void standard_dealloc( PyObject *p ); + // + // All the following functions redirect the call from Python + // onto the matching virtual function in PythonExtensionBase + // +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) + static int print_handler( PyObject *, FILE *, int ); +#endif + static PyObject *getattr_handler( PyObject *, char * ); + static int setattr_handler( PyObject *, char *, PyObject * ); + static PyObject *getattro_handler( PyObject *, PyObject * ); + static int setattro_handler( PyObject *, PyObject *, PyObject * ); + static PyObject *rich_compare_handler( PyObject *, PyObject *, int ); + static PyObject *repr_handler( PyObject * ); + static PyObject *str_handler( PyObject * ); + static Py_hash_t hash_handler( PyObject * ); + static PyObject *call_handler( PyObject *, PyObject *, PyObject * ); + static PyObject *iter_handler( PyObject * ); + static PyObject *iternext_handler( PyObject * ); + + // Sequence methods + static Py_ssize_t sequence_length_handler( PyObject * ); + static PyObject *sequence_concat_handler( PyObject *,PyObject * ); + static PyObject *sequence_repeat_handler( PyObject *, Py_ssize_t ); + static PyObject *sequence_item_handler( PyObject *, Py_ssize_t ); + static int sequence_ass_item_handler( PyObject *, Py_ssize_t, PyObject * ); + + static PyObject *sequence_inplace_concat_handler( PyObject *, PyObject * ); + static PyObject *sequence_inplace_repeat_handler( PyObject *, Py_ssize_t ); + + static int sequence_contains_handler( PyObject *, PyObject * ); + + // Mapping + static Py_ssize_t mapping_length_handler( PyObject * ); + static PyObject *mapping_subscript_handler( PyObject *, PyObject * ); + static int mapping_ass_subscript_handler( PyObject *, PyObject *, PyObject * ); + + // Numeric methods + static PyObject *number_negative_handler( PyObject * ); + static PyObject *number_positive_handler( PyObject * ); + static PyObject *number_absolute_handler( PyObject * ); + static PyObject *number_invert_handler( PyObject * ); + static PyObject *number_int_handler( PyObject * ); + static PyObject *number_float_handler( PyObject * ); + static PyObject *number_add_handler( PyObject *, PyObject * ); + static PyObject *number_subtract_handler( PyObject *, PyObject * ); + static PyObject *number_multiply_handler( PyObject *, PyObject * ); + static PyObject *number_remainder_handler( PyObject *, PyObject * ); + static PyObject *number_divmod_handler( PyObject *, PyObject * ); + static PyObject *number_lshift_handler( PyObject *, PyObject * ); + static PyObject *number_rshift_handler( PyObject *, PyObject * ); + static PyObject *number_and_handler( PyObject *, PyObject * ); + static PyObject *number_xor_handler( PyObject *, PyObject * ); + static PyObject *number_or_handler( PyObject *, PyObject * ); + static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); + + // Buffer +#ifndef Py_LIMITED_API + static int buffer_get_handler( PyObject *, Py_buffer *, int ); + static void buffer_release_handler( PyObject *, Py_buffer * ); +#endif +} + +extern "C" void standard_dealloc( PyObject *p ) +{ + PyMem_DEL( p ); +} + +bool PythonType::readyType() +{ +#ifdef Py_LIMITED_API + if( !tp_object ) + { + std::vector<PyType_Slot> spec_slots( slots.size() + 1 ); + int index = 0; + + for (std::unordered_map<int, void*>::const_iterator i = slots.cbegin(); i != slots.cend(); i++) + { + spec_slots[ index ].slot = i->first; + spec_slots[ index ].pfunc = i->second; + index++; + } + spec_slots[ index ].slot = 0; + spec->slots = spec_slots.data(); + tp_object = reinterpret_cast<PyTypeObject *>( PyType_FromSpec(spec) ); + } + return tp_object != NULL; +#else + return PyType_Ready( table ) >= 0; +#endif +} + +#ifdef Py_LIMITED_API +#define FILL_SEQUENCE_SLOT(slot) \ + if( methods_to_support&support_sequence_ ## slot ) { \ + slots[ Py_sq_ ## slot ] = reinterpret_cast<void *>( sequence_ ## slot ## _handler ); \ + } +#else +#define FILL_SEQUENCE_SLOT(slot) \ + if( methods_to_support&support_sequence_ ## slot ) { \ + sequence_table->sq_ ## slot = sequence_ ## slot ## _handler; \ + } +#endif + +PythonType &PythonType::supportSequenceType( int methods_to_support ) { +#ifndef Py_LIMITED_API + if(sequence_table) + { + return *this; + } + sequence_table = new PySequenceMethods; + memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0 + table->tp_as_sequence = sequence_table; +#endif + + FILL_SEQUENCE_SLOT(length) + FILL_SEQUENCE_SLOT(concat) + FILL_SEQUENCE_SLOT(repeat) + FILL_SEQUENCE_SLOT(item) + FILL_SEQUENCE_SLOT(ass_item) + FILL_SEQUENCE_SLOT(inplace_concat) + FILL_SEQUENCE_SLOT(inplace_repeat) + FILL_SEQUENCE_SLOT(contains) + return *this; +} + +#undef FILL_SEQUENCE_SLOT + +#ifdef Py_LIMITED_API +#define FILL_MAPPING_SLOT(slot) \ + if( methods_to_support&support_mapping_ ## slot ) { \ + slots[ Py_mp_ ## slot ] = reinterpret_cast<void *>( mapping_ ## slot ## _handler ); \ + } +#else +#define FILL_MAPPING_SLOT(slot) \ + if( methods_to_support&support_mapping_ ## slot ) { \ + mapping_table->mp_ ## slot = mapping_ ## slot ## _handler; \ + } +#endif + +PythonType &PythonType::supportMappingType( int methods_to_support ) +{ +#ifndef Py_LIMITED_API + if( mapping_table ) + { + return *this; + } + mapping_table = new PyMappingMethods; + memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0 + table->tp_as_mapping = mapping_table; +#endif + FILL_MAPPING_SLOT(length) + FILL_MAPPING_SLOT(subscript) + FILL_MAPPING_SLOT(ass_subscript) + return *this; +} + +#undef FILL_MAPPING_SLOT + +#ifdef Py_LIMITED_API +#define FILL_NUMBER_SLOT(slot) \ + if( methods_to_support&support_number_ ## slot ) { \ + slots[ Py_nb_ ## slot ] = reinterpret_cast<void *>( number_ ## slot ## _handler ); \ + } +#else +#define FILL_NUMBER_SLOT(slot) \ + if( methods_to_support&support_number_ ## slot ) { \ + number_table->nb_ ## slot = number_ ## slot ## _handler; \ + } +#endif + +PythonType &PythonType::supportNumberType( int methods_to_support ) +{ +#ifndef Py_LIMITED_API + if( number_table ) + { + return *this; + } + number_table = new PyNumberMethods; + memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0 + table->tp_as_number = number_table; +#endif + + FILL_NUMBER_SLOT(add) + FILL_NUMBER_SLOT(subtract) + FILL_NUMBER_SLOT(multiply) + FILL_NUMBER_SLOT(remainder) + FILL_NUMBER_SLOT(divmod) + FILL_NUMBER_SLOT(power) + FILL_NUMBER_SLOT(negative) + FILL_NUMBER_SLOT(positive) + FILL_NUMBER_SLOT(absolute) + FILL_NUMBER_SLOT(invert) + FILL_NUMBER_SLOT(lshift) + FILL_NUMBER_SLOT(rshift) + FILL_NUMBER_SLOT(and) + FILL_NUMBER_SLOT(xor) + FILL_NUMBER_SLOT(or) + FILL_NUMBER_SLOT(int) + FILL_NUMBER_SLOT(float) + return *this; +} + +#undef FILL_NUMBER_SLOT + +#ifndef Py_LIMITED_API +PythonType &PythonType::supportBufferType( int methods_to_support ) +{ + if( !buffer_table ) + { + buffer_table = new PyBufferProcs; + memset( buffer_table, 0, sizeof( PyBufferProcs ) ); // ensure new fields are 0 + table->tp_as_buffer = buffer_table; + + if( methods_to_support&support_buffer_getbuffer ) + { + buffer_table->bf_getbuffer = buffer_get_handler; + } + if( methods_to_support&support_buffer_releasebuffer ) + { + buffer_table->bf_releasebuffer = buffer_release_handler; + } + } + return *this; +} +#endif + +// if you define one sequence method you must define +// all of them except the assigns + +#ifdef Py_LIMITED_API +PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) +: spec( new PyType_Spec ) +{ + memset( spec, 0, sizeof( PyType_Spec ) ); + spec->name = const_cast<char *>( default_name ); + spec->basicsize = basic_size; + spec->itemsize = itemsize; + spec->flags = Py_TPFLAGS_DEFAULT; + + slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( standard_dealloc ); + + tp_object = 0; +} + +#else +PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) +: table( new PyTypeObject ) +, sequence_table( NULL ) +, mapping_table( NULL ) +, number_table( NULL ) +, buffer_table( NULL ) +{ + // PyTypeObject is defined in <python-sources>/Include/object.h + + memset( table, 0, sizeof( PyTypeObject ) ); // ensure new fields are 0 + *reinterpret_cast<PyObject *>( table ) = py_object_initializer; + reinterpret_cast<PyObject *>( table )->ob_type = _Type_Type(); + // QQQ table->ob_size = 0; + table->tp_name = const_cast<char *>( default_name ); + table->tp_basicsize = basic_size; + table->tp_itemsize = itemsize; + + // Methods to implement standard operations + table->tp_dealloc = (destructor)standard_dealloc; + table->tp_print = 0; + table->tp_getattr = 0; + table->tp_setattr = 0; + table->tp_repr = 0; + + // Method suites for standard classes + table->tp_as_number = 0; + table->tp_as_sequence = 0; + table->tp_as_mapping = 0; + + // More standard operations (here for binary compatibility) + table->tp_hash = 0; + table->tp_call = 0; + table->tp_str = 0; + table->tp_getattro = 0; + table->tp_setattro = 0; + + // Functions to access object as input/output buffer + table->tp_as_buffer = 0; + + // Flags to define presence of optional/expanded features + table->tp_flags = Py_TPFLAGS_DEFAULT; + + // Documentation string + table->tp_doc = 0; + + table->tp_traverse = 0; + + // delete references to contained objects + table->tp_clear = 0; + + // Assigned meaning in release 2.1 + // rich comparisons + table->tp_richcompare = 0; + // weak reference enabler + table->tp_weaklistoffset = 0; + + // Iterators + table->tp_iter = 0; + table->tp_iternext = 0; + + // Attribute descriptor and subclassing stuff + table->tp_methods = 0; + table->tp_members = 0; + table->tp_getset = 0; + table->tp_base = 0; + table->tp_dict = 0; + table->tp_descr_get = 0; + table->tp_descr_set = 0; + table->tp_dictoffset = 0; + table->tp_init = 0; + table->tp_alloc = 0; + table->tp_new = 0; + table->tp_free = 0; // Low-level free-memory routine + table->tp_is_gc = 0; // For PyObject_IS_GC + table->tp_bases = 0; + table->tp_mro = 0; // method resolution order + table->tp_cache = 0; + table->tp_subclasses = 0; + table->tp_weaklist = 0; + table->tp_del = 0; + + // Type attribute cache version tag. Added in version 2.6 + table->tp_version_tag = 0; + +#ifdef COUNT_ALLOCS + table->tp_alloc = 0; + table->tp_free = 0; + table->tp_maxalloc = 0; + table->tp_orev = 0; + table->tp_next = 0; +#endif +} +#endif + +PythonType::~PythonType() +{ +#ifdef Py_LIMITED_API + delete spec; + PyObject_Free(tp_object); +#else + delete table; + delete sequence_table; + delete mapping_table; + delete number_table; + delete buffer_table; +#endif +} + +PyTypeObject *PythonType::type_object() const +{ +#ifdef Py_LIMITED_API + return tp_object; +#else + return table; +#endif +} + +PythonType &PythonType::name( const char *nam ) +{ +#ifdef Py_LIMITED_API + spec->name = nam; +#else + table->tp_name = const_cast<char *>( nam ); +#endif + return *this; +} + +const char *PythonType::getName() const +{ +#ifdef Py_LIMITED_API + return spec->name; +#else + return table->tp_name; +#endif +} + +PythonType &PythonType::doc( const char *d ) +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_doc ] = reinterpret_cast<void *>( const_cast<char *>( d ) ); +#else + table->tp_doc = const_cast<char *>( d ); +#endif + return *this; +} + +const char *PythonType::getDoc() const +{ +#ifdef Py_LIMITED_API + if( tp_object ) + return reinterpret_cast<char *>( PyType_GetSlot( tp_object, Py_tp_doc ) ); + + std::unordered_map<int, void*>::const_iterator slot = slots.find( Py_tp_doc ); + if( slot == slots.end() ) + return NULL; + return reinterpret_cast<char *>( slot->second ); +#else + return table->tp_doc; +#endif +} + +PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_dealloc ] = reinterpret_cast<void *>( tp_dealloc ); +#else + table->tp_dealloc = tp_dealloc; +#endif + return *this; +} + +PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_init ] = reinterpret_cast<void *>( tp_init ); +#else + table->tp_init = tp_init; +#endif + return *this; +} + +PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_new ] = reinterpret_cast<void *>( tp_new ); +#else + table->tp_new = tp_new; +#endif + return *this; +} + +PythonType &PythonType::set_methods( PyMethodDef *methods ) +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_methods ] = reinterpret_cast<void *>( methods ); +#else + table->tp_methods = methods; +#endif + return *this; +} + +PythonType &PythonType::supportClass() +{ +#ifdef Py_LIMITED_API + spec->flags |= Py_TPFLAGS_BASETYPE; +#else + table->tp_flags |= Py_TPFLAGS_BASETYPE; +#endif + return *this; +} + +#ifdef PYCXX_PYTHON_2TO3 +#ifndef Py_LIMITED_API +PythonType &PythonType::supportPrint() +{ + table->tp_print = print_handler; + return *this; +} +#endif +#endif + +PythonType &PythonType::supportGetattr() +{ +#ifdef Py_LIMITED_API + slots[ Py_tp_getattr ] = reinterpret_cast<void *>( getattr_handler ); +#else + table->tp_getattr = getattr_handler; +#endif + return *this; +} + +PythonType &PythonType::supportSetattr() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_setattr ] = reinterpret_cast<void *>( setattr_handler ); +#else + table->tp_setattr = setattr_handler; +#endif + return *this; +} + +PythonType &PythonType::supportGetattro() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_getattro ] = reinterpret_cast<void *>( getattro_handler ); +#else + table->tp_getattro = getattro_handler; +#endif + return *this; +} + +PythonType &PythonType::supportSetattro() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_setattro ] = reinterpret_cast<void *>( setattro_handler ); +#else + table->tp_setattro = setattro_handler; +#endif + return *this; +} + +#ifdef PYCXX_PYTHON_2TO3 +PythonType &PythonType::supportCompare( void ) +{ + return *this; +} +#endif + + +PythonType &PythonType::supportRichCompare() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_richcompare ] = reinterpret_cast<void *>( rich_compare_handler ); +#else + table->tp_richcompare = rich_compare_handler; +#endif + return *this; +} + +PythonType &PythonType::supportRepr() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_repr ] = reinterpret_cast<void *>( repr_handler ); +#else + table->tp_repr = repr_handler; +#endif + return *this; +} + +PythonType &PythonType::supportStr() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_str ] = reinterpret_cast<void *>( str_handler ); +#else + table->tp_str = str_handler; +#endif + return *this; +} + +PythonType &PythonType::supportHash() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_hash ] = reinterpret_cast<void *>( hash_handler ); +#else + table->tp_hash = hash_handler; +#endif + return *this; +} + +PythonType &PythonType::supportCall() +{ +#ifdef Py_LIMITED_API + slots [ Py_tp_call ] = reinterpret_cast<void *>( call_handler ); +#else + table->tp_call = call_handler; +#endif + return *this; +} + +PythonType &PythonType::supportIter( int methods_to_support ) +{ + if( methods_to_support&support_iter_iter ) + { +#ifdef Py_LIMITED_API + slots [ Py_tp_iter ] = reinterpret_cast<void *>( iter_handler ); +#else + table->tp_iter = iter_handler; +#endif + } + if( methods_to_support&support_iter_iternext ) + { +#ifdef Py_LIMITED_API + slots [ Py_tp_iternext ] = reinterpret_cast<void *>( iternext_handler ); +#else + table->tp_iternext = iternext_handler; +#endif + } + return *this; +} + +//-------------------------------------------------------------------------------- +// +// Handlers +// +//-------------------------------------------------------------------------------- +PythonExtensionBase *getPythonExtensionBase( PyObject *self ) +{ + if(PyType_HasFeature(self->ob_type, Py_TPFLAGS_BASETYPE)) + { + PythonClassInstance *instance = reinterpret_cast<PythonClassInstance *>( self ); + return instance->m_pycxx_object; + } + else + { + return static_cast<PythonExtensionBase *>( self ); + } +} + +#if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) +extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->print( fp, flags ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} +#endif + +extern "C" PyObject *getattr_handler( PyObject *self, char *name ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->getattr( name ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->setattr( name, Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *getattro_handler( PyObject *self, PyObject *name ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->getattro( String( name ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->setattro( String( name ), Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *rich_compare_handler( PyObject *self, PyObject *other, int op ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->rich_compare( Object( other ), op ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *repr_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->repr() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *str_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->str() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" Py_hash_t hash_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->hash(); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + if( kw != NULL ) + return new_reference_to( p->call( Object( args ), Object( kw ) ) ); + else + return new_reference_to( p->call( Object( args ), Object() ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *iter_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->iter() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *iternext_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->iternext(); // might be a NULL ptr on end of iteration + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + + +// Sequence methods +extern "C" Py_ssize_t sequence_length_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_length(); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *sequence_concat_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_concat( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_repeat_handler( PyObject *self, Py_ssize_t count ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_repeat( count ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_item_handler( PyObject *self, Py_ssize_t index ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_item( index ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_ass_item( index, Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *sequence_inplace_concat_handler( PyObject *self, PyObject *o2 ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_inplace_concat( Object( o2 ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *sequence_inplace_repeat_handler( PyObject *self, Py_ssize_t count ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->sequence_inplace_repeat( count ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int sequence_contains_handler( PyObject *self, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->sequence_contains( Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +// Mapping +extern "C" Py_ssize_t mapping_length_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->mapping_length(); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" PyObject *mapping_subscript_handler( PyObject *self, PyObject *key ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->mapping_subscript( Object( key ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->mapping_ass_subscript( Object( key ), Object( value ) ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +// Number +extern "C" PyObject *number_negative_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_negative() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_positive_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_positive() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_absolute_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_absolute() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_invert_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_invert() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_int_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_int() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_float_handler( PyObject *self ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_float() ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_add( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_subtract( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_multiply( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_remainder( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_divmod( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_lshift( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_rshift( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_and( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_xor( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_or( Object( other ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return new_reference_to( p->number_power( Object( x1 ), Object( x2 ) ) ); + } + catch( BaseException & ) + { + return NULL; // indicate error + } +} + +// Buffer +#ifndef Py_LIMITED_API +extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags ) +{ + try + { + PythonExtensionBase *p = getPythonExtensionBase( self ); + return p->buffer_get( buf, flags ); + } + catch( BaseException & ) + { + return -1; // indicate error + } +} + +extern "C" void buffer_release_handler( PyObject *self, Py_buffer *buf ) +{ + PythonExtensionBase *p = getPythonExtensionBase( self ); + p->buffer_release( buf ); + // NOTE: No way to indicate error to Python +} +#endif + +//================================================================================ +// +// Implementation of PythonExtensionBase +// +//================================================================================ +#define missing_method( method ) \ + throw RuntimeError( "Extension object missing implement of " #method ); + +PythonExtensionBase::PythonExtensionBase() +{ + ob_refcnt = 0; +} + +PythonExtensionBase::~PythonExtensionBase() +{ + assert( ob_refcnt == 0 ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name ) +{ + TupleN args; + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1 ) +{ + TupleN args( arg1 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2 ) +{ + TupleN args( arg1, arg2 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3 ) +{ + TupleN args( arg1, arg2, arg3 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4 ) +{ + TupleN args( arg1, arg2, arg3, arg4 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ); + return self().callMemberFunction( fn_name, args ); +} + +Object PythonExtensionBase::callOnSelf( const std::string &fn_name, + const Object &arg1, const Object &arg2, const Object &arg3, + const Object &arg4, const Object &arg5, const Object &arg6, + const Object &arg7, const Object &arg8, const Object &arg9 ) +{ + TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ); + return self().callMemberFunction( fn_name, args ); +} + +void PythonExtensionBase::reinit( Tuple &/*args*/, Dict &/*kwds*/ ) +{ + throw RuntimeError( "Must not call __init__ twice on this class" ); +} + + +Object PythonExtensionBase::genericGetAttro( const String &name ) +{ + return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); +} + +int PythonExtensionBase::genericSetAttro( const String &name, const Object &value ) +{ + return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); +} + +#if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) +int PythonExtensionBase::print( FILE *, int ) +{ + missing_method( print ); +} +#endif + +Object PythonExtensionBase::getattr( const char * ) +{ + missing_method( getattr ); +} + +int PythonExtensionBase::setattr( const char *, const Object & ) +{ + missing_method( setattr ); +} + +Object PythonExtensionBase::getattro( const String &name ) +{ + return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); +} + +int PythonExtensionBase::setattro( const String &name, const Object &value ) +{ + return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); +} + + +int PythonExtensionBase::compare( const Object & ) +{ + missing_method( compare ); +} + +Object PythonExtensionBase::rich_compare( const Object &, int ) +{ + missing_method( rich_compare ); +} + +Object PythonExtensionBase::repr() +{ + missing_method( repr ); +} + +Object PythonExtensionBase::str() +{ + missing_method( str ); +} + +long PythonExtensionBase::hash() +{ + missing_method( hash ); +} + +Object PythonExtensionBase::call( const Object &, const Object & ) +{ + missing_method( call ); +} + +Object PythonExtensionBase::iter() +{ + missing_method( iter ); +} + +PyObject *PythonExtensionBase::iternext() +{ + missing_method( iternext ); +} + +// Sequence methods +Sequence::size_type PythonExtensionBase::sequence_length() +{ + missing_method( sequence_length ); +} + +Object PythonExtensionBase::sequence_concat( const Object & ) +{ + missing_method( sequence_concat ); +} + +Object PythonExtensionBase::sequence_repeat( Py_ssize_t ) +{ + missing_method( sequence_repeat ); +} + +Object PythonExtensionBase::sequence_item( Py_ssize_t ) +{ + missing_method( sequence_item ); +} + +int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Object & ) +{ + missing_method( sequence_ass_item ); +} + +Object PythonExtensionBase::sequence_inplace_concat( const Object & ) +{ + missing_method( sequence_inplace_concat ); +} + +Object PythonExtensionBase::sequence_inplace_repeat( Py_ssize_t ) +{ + missing_method( sequence_inplace_repeat ); +} + +int PythonExtensionBase::sequence_contains( const Object & ) +{ + missing_method( sequence_contains ); +} + +// Mapping +PyCxx_ssize_t PythonExtensionBase::mapping_length() +{ + missing_method( mapping_length ); +} + +Object PythonExtensionBase::mapping_subscript( const Object & ) +{ + missing_method( mapping_subscript ); +} + +int PythonExtensionBase::mapping_ass_subscript( const Object &, const Object & ) +{ + missing_method( mapping_ass_subscript ); +} + +Object PythonExtensionBase::number_negative() +{ + missing_method( number_negative ); +} + +Object PythonExtensionBase::number_positive() +{ + missing_method( number_positive ); +} + +Object PythonExtensionBase::number_absolute() +{ + missing_method( number_absolute ); +} + +Object PythonExtensionBase::number_invert() +{ + missing_method( number_invert ); +} + +Object PythonExtensionBase::number_int() +{ + missing_method( number_int ); +} + +Object PythonExtensionBase::number_float() +{ + missing_method( number_float ); +} + +Object PythonExtensionBase::number_long() +{ + missing_method( number_long ); +} + +Object PythonExtensionBase::number_add( const Object & ) +{ + missing_method( number_add ); +} + +Object PythonExtensionBase::number_subtract( const Object & ) +{ + missing_method( number_subtract ); +} + +Object PythonExtensionBase::number_multiply( const Object & ) +{ + missing_method( number_multiply ); +} + +Object PythonExtensionBase::number_remainder( const Object & ) +{ + missing_method( number_remainder ); +} + +Object PythonExtensionBase::number_divmod( const Object & ) +{ + missing_method( number_divmod ); +} + +Object PythonExtensionBase::number_lshift( const Object & ) +{ + missing_method( number_lshift ); +} + +Object PythonExtensionBase::number_rshift( const Object & ) +{ + missing_method( number_rshift ); +} + +Object PythonExtensionBase::number_and( const Object & ) +{ + missing_method( number_and ); +} + +Object PythonExtensionBase::number_xor( const Object & ) +{ + missing_method( number_xor ); +} + +Object PythonExtensionBase::number_or( const Object & ) +{ + missing_method( number_or ); +} + +Object PythonExtensionBase::number_power( const Object &, const Object & ) +{ + missing_method( number_power ); +} + + +// Buffer +#ifndef Py_LIMITED_API +int PythonExtensionBase::buffer_get( Py_buffer * /*buf*/, int /*flags*/ ) +{ + missing_method( buffer_get ); +} + +int PythonExtensionBase::buffer_release( Py_buffer * /*buf*/ ) +{ + // This method is optional and only required if the buffer's + // memory is dynamic. + return 0; +} +#endif + +//-------------------------------------------------------------------------------- +// +// Method call handlers for +// PythonExtensionBase +// ExtensionModuleBase +// +//-------------------------------------------------------------------------------- +// Note: Python calls noargs as varargs buts args==NULL +extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + + Object result( self->invoke_method_noargs( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ) ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } +} + +extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + Tuple args( _args ); + Object result + ( + self->invoke_method_varargs + ( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), + args + ) + ); + + return new_reference_to( result.ptr() ); + } + catch( BaseException & ) + { + return 0; + } +} + +extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) +{ + try + { + Tuple self_and_name_tuple( _self_and_name_tuple ); + + PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); + void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); + if( self_as_void == NULL ) + return NULL; + + ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void ); + + Tuple args( _args ); + + if( _keywords == NULL ) + { + Dict keywords; // pass an empty dict + + Object result + ( + self->invoke_method_keyword + ( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), + args, + keywords + ) + ); + + return new_reference_to( result.ptr() ); + } + else + { + Dict keywords( _keywords ); // make dict + + Object result + ( + self->invoke_method_keyword + ( + PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), + args, + keywords + ) + ); + + return new_reference_to( result.ptr() ); + } + } + catch( BaseException & ) + { + return 0; + } +} + + +//-------------------------------------------------------------------------------- +// +// ExtensionExceptionType +// +//-------------------------------------------------------------------------------- +ExtensionExceptionType::ExtensionExceptionType() +: Object() +{ +} + +void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name ) +{ + std::string module_name( module.fullName() ); + module_name += "."; + module_name += name; + + set( PyErr_NewException( const_cast<char *>( module_name.c_str() ), NULL, NULL ), true ); +} + +void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name, ExtensionExceptionType &parent ) + { + std::string module_name( module.fullName() ); + module_name += "."; + module_name += name; + + set( PyErr_NewException( const_cast<char *>( module_name.c_str() ), parent.ptr(), NULL ), true ); +} + +ExtensionExceptionType::~ExtensionExceptionType() +{ +} + +BaseException::BaseException( ExtensionExceptionType &exception, const std::string& reason ) + : reasonMessage(reason) +{ + PyErr_SetString( exception.ptr(), reason.c_str() ); +} + +BaseException::BaseException( ExtensionExceptionType &exception, Object &reason ) +{ + if (reason.hasAttr("message")) { + reasonMessage = reason.getAttr("message").str(); + } + PyErr_SetObject( exception.ptr(), reason.ptr() ); +} + +BaseException::BaseException( ExtensionExceptionType &exception, PyObject *reason ) +{ + PyErr_SetObject( exception.ptr(), reason ); +} + +BaseException::BaseException( PyObject *exception, Object &reason ) +{ + if (reason.hasAttr("message")) { + reasonMessage = reason.getAttr("message").str(); + } + PyErr_SetObject( exception, reason.ptr() ); +} + +BaseException::BaseException( PyObject *exception, PyObject *reason ) +{ + PyErr_SetObject( exception, reason ); +} + +BaseException::BaseException( PyObject *exception, const std::string &reason ) + : reasonMessage(reason) +{ + PyErr_SetString( exception, reason.c_str() ); +} + +BaseException::BaseException() +{ +} + +void BaseException::clear() +{ + PyErr_Clear(); +} + +const char* BaseException::what() const noexcept +{ + return reasonMessage.c_str(); +} + +// is the exception this specific exception 'exc' +bool BaseException::matches( ExtensionExceptionType &exc ) +{ + return PyErr_ExceptionMatches( exc.ptr() ) != 0; +} + +//------------------------------------------------------------ + +#if 1 +//------------------------------------------------------------ +// compare operators +bool operator!=( const Long &a, const Long &b ) +{ + return a.as_long() != b.as_long(); +} + +bool operator!=( const Long &a, int b ) +{ + return a.as_long() != b; +} + +bool operator!=( const Long &a, long b ) +{ + return a.as_long() != b; +} + +bool operator!=( int a, const Long &b ) +{ + return a != b.as_long(); +} + +bool operator!=( long a, const Long &b ) +{ + return a != b.as_long(); +} + +//------------------------------ +bool operator==( const Long &a, const Long &b ) +{ + return a.as_long() == b.as_long(); +} + +bool operator==( const Long &a, int b ) +{ + return a.as_long() == b; +} + +bool operator==( const Long &a, long b ) +{ + return a.as_long() == b; +} + +bool operator==( int a, const Long &b ) +{ + return a == b.as_long(); +} + +bool operator==( long a, const Long &b ) +{ + return a == b.as_long(); +} + +//------------------------------ +bool operator>( const Long &a, const Long &b ) +{ + return a.as_long() > b.as_long(); +} + +bool operator>( const Long &a, int b ) +{ + return a.as_long() > b; +} + +bool operator>( const Long &a, long b ) +{ + return a.as_long() > b; +} + +bool operator>( int a, const Long &b ) +{ + return a > b.as_long(); +} + +bool operator>( long a, const Long &b ) +{ + return a > b.as_long(); +} + +//------------------------------ +bool operator>=( const Long &a, const Long &b ) +{ + return a.as_long() >= b.as_long(); +} + +bool operator>=( const Long &a, int b ) +{ + return a.as_long() >= b; +} + +bool operator>=( const Long &a, long b ) +{ + return a.as_long() >= b; +} + +bool operator>=( int a, const Long &b ) +{ + return a >= b.as_long(); +} + +bool operator>=( long a, const Long &b ) +{ + return a >= b.as_long(); +} + +//------------------------------ +bool operator<( const Long &a, const Long &b ) +{ + return a.as_long() < b.as_long(); +} + +bool operator<( const Long &a, int b ) +{ + return a.as_long() < b; +} + +bool operator<( const Long &a, long b ) +{ + return a.as_long() < b; +} + +bool operator<( int a, const Long &b ) +{ + return a < b.as_long(); +} + +bool operator<( long a, const Long &b ) +{ + return a < b.as_long(); +} + +//------------------------------ +bool operator<=( const Long &a, const Long &b ) +{ + return a.as_long() <= b.as_long(); +} + +bool operator<=( int a, const Long &b ) +{ + return a <= b.as_long(); +} + +bool operator<=( long a, const Long &b ) +{ + return a <= b.as_long(); +} + +bool operator<=( const Long &a, int b ) +{ + return a.as_long() <= b; +} + +bool operator<=( const Long &a, long b ) +{ + return a.as_long() <= b; +} + +#ifdef HAVE_LONG_LONG +//------------------------------ +bool operator!=( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() != b; +} + +bool operator!=( PY_LONG_LONG a, const Long &b ) +{ + return a != b.as_long_long(); +} + +//------------------------------ +bool operator==( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() == b; +} + +bool operator==( PY_LONG_LONG a, const Long &b ) +{ + return a == b.as_long_long(); +} + +//------------------------------ +bool operator>( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() > b; +} + +bool operator>( PY_LONG_LONG a, const Long &b ) +{ + return a > b.as_long_long(); +} + +//------------------------------ +bool operator>=( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() >= b; +} + +bool operator>=( PY_LONG_LONG a, const Long &b ) +{ + return a >= b.as_long_long(); +} + +//------------------------------ +bool operator<( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() < b; +} + +bool operator<( PY_LONG_LONG a, const Long &b ) +{ + return a < b.as_long_long(); +} + +//------------------------------ +bool operator<=( const Long &a, PY_LONG_LONG b ) +{ + return a.as_long_long() <= b; +} + +bool operator<=( PY_LONG_LONG a, const Long &b ) +{ + return a <= b.as_long_long(); +} +#endif +#endif + +//------------------------------------------------------------ +// compare operators +bool operator!=( const Float &a, const Float &b ) +{ + return a.as_double() != b.as_double(); +} + +bool operator!=( const Float &a, double b ) +{ + return a.as_double() != b; +} + +bool operator!=( double a, const Float &b ) +{ + return a != b.as_double(); +} + +//------------------------------ +bool operator==( const Float &a, const Float &b ) +{ + return a.as_double() == b.as_double(); +} + +bool operator==( const Float &a, double b ) +{ + return a.as_double() == b; +} + +bool operator==( double a, const Float &b ) +{ + return a == b.as_double(); +} + +//------------------------------ +bool operator>( const Float &a, const Float &b ) +{ + return a.as_double() > b.as_double(); +} + +bool operator>( const Float &a, double b ) +{ + return a.as_double() > b; +} + +bool operator>( double a, const Float &b ) +{ + return a > b.as_double(); +} + +//------------------------------ +bool operator>=( const Float &a, const Float &b ) +{ + return a.as_double() >= b.as_double(); +} + +bool operator>=( const Float &a, double b ) +{ + return a.as_double() >= b; +} + +bool operator>=( double a, const Float &b ) +{ + return a >= b.as_double(); +} + +//------------------------------ +bool operator<( const Float &a, const Float &b ) +{ + return a.as_double() < b.as_double(); +} + +bool operator<( const Float &a, double b ) +{ + return a.as_double() < b; +} + +bool operator<( double a, const Float &b ) +{ + return a < b.as_double(); +} + +//------------------------------ +bool operator<=( const Float &a, const Float &b ) +{ + return a.as_double() <= b.as_double(); +} + +bool operator<=( double a, const Float &b ) +{ + return a <= b.as_double(); +} + +bool operator<=( const Float &a, double b ) +{ + return a.as_double() <= b; +} + +} // end of namespace Py diff --git a/contrib/libs/pycxx/Python3/cxx_standard_exceptions.hxx b/contrib/libs/pycxx/Python3/cxx_standard_exceptions.hxx new file mode 100644 index 00000000000..c1552960c17 --- /dev/null +++ b/contrib/libs/pycxx/Python3/cxx_standard_exceptions.hxx @@ -0,0 +1,68 @@ +#if !defined( PYCXX_STANDARD_EXCEPTION ) +#pragma error( "define PYCXX_STANDARD_EXCEPTION before including" ) +#endif + +// taken for python3.5 documentation + +// EnvironmentError and IOError are not used in Python3 +//PYCXX_STANDARD_EXCEPTION( EnvironmentError, QQQ ) +//PYCXX_STANDARD_EXCEPTION( IOError, QQQ ) + +// 5.4 Exception hierarchy +PYCXX_STANDARD_EXCEPTION( SystemExit, BaseException ) +PYCXX_STANDARD_EXCEPTION( KeyboardInterrupt, BaseException ) +PYCXX_STANDARD_EXCEPTION( GeneratorExit, BaseException ) +#if !defined( PYCXX_6_2_COMPATIBILITY ) +PYCXX_STANDARD_EXCEPTION( Exception, BaseException ) +#endif +PYCXX_STANDARD_EXCEPTION( StopIteration, Exception ) +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) && (!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000) +PYCXX_STANDARD_EXCEPTION( StopAsyncIteration, Exception ) +#endif +PYCXX_STANDARD_EXCEPTION( ArithmeticError, Exception ) +PYCXX_STANDARD_EXCEPTION( FloatingPointError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( OverflowError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( ZeroDivisionError, ArithmeticError ) +PYCXX_STANDARD_EXCEPTION( AssertionError, Exception ) +PYCXX_STANDARD_EXCEPTION( AttributeError, Exception ) +PYCXX_STANDARD_EXCEPTION( BufferError, Exception ) +PYCXX_STANDARD_EXCEPTION( EOFError, Exception ) +PYCXX_STANDARD_EXCEPTION( ImportError, Exception ) +PYCXX_STANDARD_EXCEPTION( LookupError, Exception ) +PYCXX_STANDARD_EXCEPTION( IndexError, LookupError ) +PYCXX_STANDARD_EXCEPTION( KeyError, LookupError ) +PYCXX_STANDARD_EXCEPTION( MemoryError, Exception ) +PYCXX_STANDARD_EXCEPTION( NameError, Exception ) +PYCXX_STANDARD_EXCEPTION( UnboundLocalError, NameError ) +PYCXX_STANDARD_EXCEPTION( OSError, Exception ) +PYCXX_STANDARD_EXCEPTION( BlockingIOError, OSError ) +PYCXX_STANDARD_EXCEPTION( ChildProcessError,OSError ) +PYCXX_STANDARD_EXCEPTION( ConnectionError, OSError ) +PYCXX_STANDARD_EXCEPTION( BrokenPipeError, ConnectionError ) +PYCXX_STANDARD_EXCEPTION( ConnectionAbortedError, ConnectionError ) +PYCXX_STANDARD_EXCEPTION( ConnectionRefusedError, ConnectionError ) +PYCXX_STANDARD_EXCEPTION( ConnectionResetError, ConnectionError ) +PYCXX_STANDARD_EXCEPTION( FileExistsError, OSError ) +PYCXX_STANDARD_EXCEPTION( FileNotFoundError, OSError ) +PYCXX_STANDARD_EXCEPTION( InterruptedError, OSError ) +PYCXX_STANDARD_EXCEPTION( IsADirectoryError, OSError ) +PYCXX_STANDARD_EXCEPTION( NotADirectoryError, OSError ) +PYCXX_STANDARD_EXCEPTION( PermissionError, OSError ) +PYCXX_STANDARD_EXCEPTION( ProcessLookupError, OSError ) +PYCXX_STANDARD_EXCEPTION( TimeoutError, OSError ) +PYCXX_STANDARD_EXCEPTION( ReferenceError, Exception ) +PYCXX_STANDARD_EXCEPTION( RuntimeError, Exception ) +PYCXX_STANDARD_EXCEPTION( NotImplementedError, RuntimeError ) +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5) && (!defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000) +PYCXX_STANDARD_EXCEPTION( RecursionError, RuntimeError ) +#endif +PYCXX_STANDARD_EXCEPTION( SyntaxError, Exception ) +PYCXX_STANDARD_EXCEPTION( IndentationError, SyntaxError ) +PYCXX_STANDARD_EXCEPTION( TabError, IndentationError ) +PYCXX_STANDARD_EXCEPTION( SystemError, Exception ) +PYCXX_STANDARD_EXCEPTION( TypeError, Exception ) +PYCXX_STANDARD_EXCEPTION( ValueError, Exception ) +PYCXX_STANDARD_EXCEPTION( UnicodeError, ValueError ) +PYCXX_STANDARD_EXCEPTION( UnicodeDecodeError, UnicodeError ) +PYCXX_STANDARD_EXCEPTION( UnicodeEncodeError, UnicodeError ) +PYCXX_STANDARD_EXCEPTION( UnicodeTranslateError,UnicodeError ) diff --git a/contrib/libs/pycxx/Python3/cxxextensions.c b/contrib/libs/pycxx/Python3/cxxextensions.c new file mode 100644 index 00000000000..bd05d0cf75f --- /dev/null +++ b/contrib/libs/pycxx/Python3/cxxextensions.c @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//---------------------------------------------------------------------------*/ + +#include "../WrapPython.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +PyObject py_object_initializer = + { + _PyObject_EXTRA_INIT + 1, + NULL // type must be init'ed by user + }; + +#ifdef __cplusplus +} +#endif diff --git a/contrib/libs/pycxx/Python3/cxxsupport.cxx b/contrib/libs/pycxx/Python3/cxxsupport.cxx new file mode 100644 index 00000000000..82c8b9c9fd0 --- /dev/null +++ b/contrib/libs/pycxx/Python3/cxxsupport.cxx @@ -0,0 +1,222 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#include "../Objects.hxx" +namespace Py +{ +#ifndef Py_LIMITED_API +Py_UNICODE unicode_null_string[1] = { 0 }; +#endif + +Type Object::type() const +{ + return Type( PyObject_Type( p ), true ); +} + +String Object::str() const +{ + return String( PyObject_Str( p ), true ); +} + +String Object::repr() const +{ + return String( PyObject_Repr( p ), true ); +} + +std::string Object::as_string() const +{ + return static_cast<std::string>( str() ); +} + +List Object::dir() const +{ + return List( PyObject_Dir( p ), true ); +} + +bool Object::isType( const Type &t ) const +{ + return type().ptr() == t.ptr(); +} + +Char::operator String() const +{ + return String( ptr() ); +} + +String Bytes::decode( const char *encoding, const char *error ) +{ + return String( PyUnicode_FromEncodedObject( ptr(), encoding, error ), true ); +} + +// Object compares +bool operator==( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_EQ ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +bool operator!=( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_NE ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +bool operator>=( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_GE ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +bool operator<=( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_LE ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +bool operator<( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_LT ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +bool operator>( const Object &o1, const Object &o2 ) +{ + int k = PyObject_RichCompareBool( *o1, *o2, Py_GT ); + ifPyErrorThrowCxxException(); + return k != 0; +} + +// iterator compares +bool operator==( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.eql( right ); +} + +bool operator!=( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.neq( right ); +} + +bool operator<( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.lss( right ); +} + +bool operator>( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.gtr( right ); +} + +bool operator<=( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.leq( right ); +} + +bool operator>=( const Sequence::iterator &left, const Sequence::iterator &right ) +{ + return left.geq( right ); +} + +// const_iterator compares +bool operator==( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.eql( right ); +} + +bool operator!=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.neq( right ); +} + +bool operator<( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.lss( right ); +} + +bool operator>( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.gtr( right ); +} + +bool operator<=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.leq( right ); +} + +bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) +{ + return left.geq( right ); +} + +// For mappings: +bool operator==( const Mapping::iterator &left, const Mapping::iterator &right ) +{ + return left.eql( right ); +} + +bool operator!=( const Mapping::iterator &left, const Mapping::iterator &right ) +{ + return left.neq( right ); +} + +// now for const_iterator +bool operator==( const Mapping::const_iterator &left, const Mapping::const_iterator &right ) +{ + return left.eql( right ); +} + +bool operator!=( const Mapping::const_iterator &left, const Mapping::const_iterator &right ) +{ + return left.neq( right ); +} + +// TMM: 31May'01 - Added the #ifndef so I can exclude iostreams. +#ifndef CXX_NO_IOSTREAMS +// output + +std::ostream &operator<<( std::ostream &os, const Object &ob ) +{ + return( os << static_cast<std::string>( ob.str() ) ); +} +#endif + +} // Py diff --git a/contrib/libs/pycxx/Version.hxx b/contrib/libs/pycxx/Version.hxx new file mode 100644 index 00000000000..2dc2779e94a --- /dev/null +++ b/contrib/libs/pycxx/Version.hxx @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- + +#ifndef __PyCXX_version_hxx__ +#define __PyCXX_version_hxx__ + +#define PYCXX_VERSION_MAJOR 7 +#define PYCXX_VERSION_MINOR 0 +#define PYCXX_VERSION_PATCH 3 +#define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch)) +#define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH ) +#endif diff --git a/contrib/libs/pycxx/WrapPython.h b/contrib/libs/pycxx/WrapPython.h new file mode 100755 index 00000000000..2d1dcafdbe8 --- /dev/null +++ b/contrib/libs/pycxx/WrapPython.h @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#if !defined(Y_PYCXX_BUILD) +#include <iostream> +#endif + +#ifndef __PyCXX_wrap_python_hxx__ +#define __PyCXX_wrap_python_hxx__ + +// On some platforms we have to include time.h to get select defined +#if !defined(__WIN32__) && !defined(WIN32) && !defined(_WIN32) && !defined(_WIN64) +#include <sys/time.h> +#endif + +// Prevent multiple conflicting definitions of swab from stdlib.h and unistd.h +#if defined(__sun) || defined(sun) +#if defined(_XPG4) +#undef _XPG4 +#endif +#endif + +// Python.h will redefine these and generate warning in the process +#undef _XOPEN_SOURCE +#undef _POSIX_C_SOURCE + +// (ignat): to avoid multiple definition (SIZEOF_SIZE_T also defined in util). +#undef SIZEOF_SIZE_T + +// pull in python definitions +#include <Python.h> + +#endif diff --git a/contrib/libs/pycxx/check.cpp b/contrib/libs/pycxx/check.cpp new file mode 100644 index 00000000000..b0b0227ab3a --- /dev/null +++ b/contrib/libs/pycxx/check.cpp @@ -0,0 +1,4 @@ +#include "Exception.hxx" +#include "Extensions.hxx" +#include "Objects.hxx" +#include "Version.hxx" diff --git a/contrib/libs/pycxx/cxx_exceptions.cxx b/contrib/libs/pycxx/cxx_exceptions.cxx new file mode 100644 index 00000000000..581c487d6aa --- /dev/null +++ b/contrib/libs/pycxx/cxx_exceptions.cxx @@ -0,0 +1,7 @@ +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxx_exceptions.cxx" +#else +#include "Python3/cxx_exceptions.cxx" +#endif diff --git a/contrib/libs/pycxx/cxx_extensions.cxx b/contrib/libs/pycxx/cxx_extensions.cxx new file mode 100755 index 00000000000..929e450a0b7 --- /dev/null +++ b/contrib/libs/pycxx/cxx_extensions.cxx @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxx_extensions.cxx" +#else +#include "Python3/cxx_extensions.cxx" +#endif diff --git a/contrib/libs/pycxx/cxxextensions.c b/contrib/libs/pycxx/cxxextensions.c new file mode 100755 index 00000000000..26bf669fe2d --- /dev/null +++ b/contrib/libs/pycxx/cxxextensions.c @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxxextensions.c" +#else +#include "Python3/cxxextensions.c" +#endif diff --git a/contrib/libs/pycxx/cxxsupport.cxx b/contrib/libs/pycxx/cxxsupport.cxx new file mode 100755 index 00000000000..9f25d989159 --- /dev/null +++ b/contrib/libs/pycxx/cxxsupport.cxx @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) 1998 - 2007, The Regents of the University of California +// Produced at the Lawrence Livermore National Laboratory +// All rights reserved. +// +// This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The +// full copyright notice is contained in the file COPYRIGHT located at the root +// of the PyCXX distribution. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the disclaimer below. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the disclaimer (as noted below) in the +// documentation and/or materials provided with the distribution. +// - Neither the name of the UC/LLNL nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF +// CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +//----------------------------------------------------------------------------- +#include "WrapPython.h" + +#if PY_MAJOR_VERSION == 2 +#include "Python2/cxxsupport.cxx" +#else +#include "Python3/cxxsupport.cxx" +#endif |