File: //proc/self/root/opt/alt/python27/share/doc/alt-python27-matplotlib-1.0.1/CXX/Python3/Objects.hxx
//-----------------------------------------------------------------------------
//
// 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