D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
self
/
root
/
opt
/
alt
/
python27
/
share
/
doc
/
alt-python27-matplotlib-1.0.1
/
CXX
/
Python3
/
Filename :
Objects.hxx
back
Copy
//----------------------------------------------------------------------------- // // 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 "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Python3/Config.hxx" #include "CXX/Python3/CxxDebug.hxx" #include "CXX/Python3/Exception.hxx" #include <iostream> #include STR_STREAM #include <string> #include <iterator> #include <utility> #include <typeinfo> namespace Py { typedef int 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 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 *pyob ) 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 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; } //operator bool() const //{ // return as_bool(); //} // int print( FILE *fp, int flags=Py_Print_RAW ) //{ // return PyObject_Print( p, fp, flags ); //} 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 ) throw AttributeError( "getAttr failed." ); } void delAttr( const std::string &s ) { if( PyObject_DelAttrString( p, const_cast<char*>( s.c_str() ) ) == -1 ) throw AttributeError( "delAttr failed." ); } // 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 ) // failed to link on Windows? throw KeyError( "delItem failed." ); } // 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() { } bool accepts( PyObject *pyob ) { 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 //operator bool() const //{ // return as_bool(); //} // 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() ); } 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 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 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 int 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( NULL ) , 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 size_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 std::string::npos; // ? } 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 ) { throw Exception(); } } 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; int count; public: ~iterator() {} iterator() : seq( 0 ) , count( 0 ) {} iterator( SeqBase<T> *s, int 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+( int n ) const { return iterator( seq, count + n ); } iterator operator-( int n ) const { return iterator( seq, count - n ); } iterator &operator+=( int n ) { count = count + n; return *this; } iterator &operator-=( int n ) { count = count - n; return *this; } int 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, int 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+( int 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-( int n ) { return const_iterator( seq, count - n ); } const_iterator &operator+=( int n ) { count = count + n; return *this; } const_iterator &operator-=( int 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 Byte: public Object { public: // Membership virtual bool accepts( PyObject *pyob ) const { return pyob != NULL && Py::_Unicode_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() ), static_cast<int>( v.length() ) ), true ) { validate(); } Bytes( const std::string &v, Py_ssize_t vsize ) : SeqBase<Byte>( PyBytes_FromStringAndSize( const_cast<char*>( v.data() ), static_cast<int>( 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() ), static_cast<int>( v.length() ) ), true ); return *this; } String decode( const char *encoding, const char *error="strict" ); // Queries virtual size_type size() const { return static_cast<size_type>( 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_type>( 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(); } Char( Py_UNICODE v ) : Object( PyUnicode_FromOrdinal( v ), true ) { validate(); } Char( const unicodestring &v ) : Object( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),1 ), true ) { validate(); } // 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; } Char &operator=( const unicodestring &v ) { set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ), 1 ), true ); return *this; } Char &operator=( int v_ ) { Py_UNICODE v( v_ ); set( PyUnicode_FromUnicode( &v, 1 ), true ); return *this; } Char &operator=( Py_UNICODE v ) { set( PyUnicode_FromUnicode( &v, 1 ), true ); return *this; } // 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 ) ) { validate(); } String( const std::string &latin1 ) : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ) ) { validate(); } String( const char *latin1, Py_ssize_t size ) : SeqBase<Char>( PyUnicode_FromStringAndSize( latin1, size ) ) { 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 ) ) { validate(); } String( const char *s, const char *encoding, const char *errors=NULL ) : SeqBase<Char>( PyUnicode_Decode( s, strlen(s), encoding, errors ) ) { validate(); } String( const char *s, Py_ssize_t size, const char *encoding, const char *errors=NULL ) : SeqBase<Char>( PyUnicode_Decode( s, size, encoding, errors ) ) { validate(); } // 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; } String &operator=( const unicodestring &v ) { set( PyUnicode_FromUnicode( const_cast<Py_UNICODE *>( v.data() ), static_cast<int>( v.length() ) ), true ); return *this; } // Encode Bytes encode( const char *encoding, const char *error="strict" ) const { return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ) ); } // Queries virtual size_type size() const { return static_cast<size_type>( PyUnicode_GET_SIZE( ptr() ) ); } unicodestring as_unicodestring() const { return unicodestring( PyUnicode_AS_UNICODE( ptr() ), static_cast<size_type>( PyUnicode_GET_SIZE( ptr() ) ) ); } 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 ) { throw Exception(); } } // 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 ) { throw Exception(); } } } // 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 ) { throw Exception(); } } } // 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 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( int 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 ) { throw Exception(); } } } // List from a sequence List( const Sequence &s ) : Sequence() { int n =( int )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 ) { throw Exception(); } } } 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( int i, int j, const Object &v ) { if( PyList_SetSlice( ptr(), i, j, *v ) == -1 ) { throw Exception(); } } void append( const Object &ob ) { if( PyList_Append( ptr(), *ob ) == -1 ) { throw Exception(); } } void extend( const Object &ob ) { setSlice( size(), size(), ob ); } void insert( int i, const Object &ob ) { if( PyList_Insert( ptr(), i, *ob ) == -1 ) { throw Exception(); } } void sort() { if( PyList_Sort( ptr() ) == -1 ) { throw Exception(); } } void reverse() { if( PyList_Reverse( ptr() ) == -1 ) { throw Exception(); } } }; // 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 size_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 size_type 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 ); } int 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 ) { throw Exception(); } } virtual void setItem( const std::string &s, const Object &ob ) { if( PyMapping_SetItemString( ptr(), const_cast<char*>( s.c_str() ), *ob ) == -1 ) { throw Exception(); } } virtual void setItem( const Object &s, const Object &ob ) { if( PyObject_SetItem( ptr(), s.ptr(), ob.ptr() ) == -1 ) { throw Exception(); } } void delItem( const std::string &s ) { if( PyMapping_DelItemString( ptr(), const_cast<char*>( s.c_str() ) ) == -1 ) { throw Exception(); } } void delItem( const Object &s ) { if( PyMapping_DelItem( ptr(), *s ) == -1 ) { throw Exception(); } } // 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 int 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 int pos; // index into the keys public: ~const_iterator() {} const_iterator() : map( 0 ) , keys() , pos() {} const_iterator( const MapBase<T> *m, List k, int 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 { return asObject( PyObject_CallObject( ptr(), args.ptr() ) ); } // Call with keywords Object apply( const Tuple &args, const Dict &kw ) const { return asObject( PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ) ); } Object apply( PyObject *pargs = 0 ) const { 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! } }; // 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 Exception &) // 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 Exception &) // 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 Exception &) // 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