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/Python3/Objects.hxx | |
parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (diff) | |
download | ydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz |
validate canons without yatest_common
Diffstat (limited to 'contrib/libs/pycxx/Python3/Objects.hxx')
-rwxr-xr-x | contrib/libs/pycxx/Python3/Objects.hxx | 3578 |
1 files changed, 3578 insertions, 0 deletions
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 |