/* * Rick Ratzel * 3/11/2004 * * Copyright (c) 2004 Richard L. Ratzel * see file "COPYRIGHT" for more details... */ #include #include extern "C" { #include #include extern int Py_NoSiteFlag; extern int Py_FrozenFlag; extern int Py_VerboseFlag; } static int objCnt = 0; // // exception class thrown for all CF classes // CFException::CFException( const char* val ) { d_val = val; } const char* CFException::getVal() const { return d_val; } // // constructor simply copies the id (since Python maintains the actual data) // and determines the type for other method calls // CFObj::CFObj( int id ) { d_id = id; switch( getType( id ) ) { case 1 : d_type = CFINT; break; case 2 : d_type = CFSTRING; break; case 3 : d_type = CFFLOAT; break; case 4 : d_type = CFDOUBLE; break; case 5 : d_type = CFLIST; break; case 6 : d_type = CFMAP; break; default : d_type = CFUNKNOWN; break; } } CFObj::CFObj( const CFObj& cfo ) { d_id = cfo.d_id; d_type = cfo.d_type; } // // tell the Python interp to delete the obj maintained by id // CFObj::~CFObj() { delete_obj( d_id ); } int CFObj::id() const { return d_id; } CFObj::CFObjType CFObj::type() const { return d_type; } // // accessors...return the appropriate type, if possible // int CFObj::getInt() const { if( d_type == CFINT ) { return extractInt( d_id ); } else { throw CFException( "cannot call getInt() on a non-int CFObj" ); } } char* CFObj::getString() const { if( d_type == CFSTRING ) { return extractString( d_id ); } else { throw CFException( "cannot call getString() on a non-string CFObj" ); } } float CFObj::getFloat() const { if( d_type == CFFLOAT ) { return extractFloat( d_id ); } else { throw CFException( "cannot call getFloat() on a non-float CFObj" ); } } double CFObj::getDouble() const { if( d_type == CFDOUBLE ) { return extractDouble( d_id ); } else { throw CFException( "cannot call getDouble() on a non-double CFObj" ); } } // // methods specific to lists // int CFObj::length() const { if( d_type == CFLIST ) { return getListLength( d_id ); } else { throw CFException( "cannot call length() on a non-list CFObj" ); } } // // methods specific to maps // CFObj CFObj::keys() const { if( d_type == CFMAP ) { return CFObj( getKeys( d_id, objCnt++ ) ); } else { throw CFException( "cannot call keys() on a non-map CFObj" ); } } // // operator[]...for lists and maps // ints for lists only, everything else can be used as a key in a map // CFObj CFObj::operator[]( const CFObj& k ) const { if( d_type == CFLIST ) { if( k.d_type == CFINT ) { return CFObj( getNthItemInList( d_id, k.getInt(), objCnt++ ) ); } else { throw CFException( "cannot call [] using a non-list CFObj key" ); } } else if( d_type == CFMAP ) { switch( k.d_type ) { case CFINT : return CFObj( getItemInMapIntKey( d_id, k.getInt(), objCnt++ ) ); case CFSTRING : return CFObj( getItemInMapStringKey( d_id, k.getString(), objCnt++ ) ); case CFFLOAT : return CFObj( getItemInMapFloatKey( d_id, k.getFloat(), objCnt++ ) ); case CFDOUBLE : return CFObj( getItemInMapDoubleKey( d_id, k.getDouble(), objCnt++ ) ); default : throw CFException( "cannot call [] with a CFUNKNOWN, CFLIST, or CFMAP CFObj key" ); } } else { throw CFException( "cannot call [] on a non-list or non-map CFObj" ); } } CFObj CFObj::operator[]( int k ) const { if( d_type == CFLIST ) { return CFObj( getNthItemInList( d_id, k, objCnt++ ) ); } else if( d_type == CFMAP ) { return CFObj( getItemInMapIntKey( d_id, k, objCnt++ ) ); } else { throw CFException( "cannot call [] on a non-list or non-map CFObj" ); } } CFObj CFObj::operator[]( char* k ) const { if( d_type == CFMAP ) { return CFObj( getItemInMapStringKey( d_id, k, objCnt++ ) ); } else { throw CFException( "cannot call [] on a non-map CFObj" ); } } CFObj CFObj::operator[]( float k ) const { if( d_type == CFMAP ) { return CFObj( getItemInMapFloatKey( d_id, k, objCnt++ ) ); } else { throw CFException( "cannot call [] on a non-map CFObj" ); } } CFObj CFObj::operator[]( double k ) const { if( d_type == CFMAP ) { return CFObj( getItemInMapDoubleKey( d_id, k, objCnt++ ) ); } else { throw CFException( "cannot call [] on a non-map CFObj" ); } } // // configfile constructor takes a filename, makes sure Python interp is setup // and creates a new configfile instance within the Python interp // configfile::configfile( char* fileName ) { assertInitialized(); d_id = configfile_create( fileName, objCnt++ ); } // // copy constructor simply copies the id since the actual data is in the interp // configfile::configfile( const configfile& cf ) { d_id = cf.d_id; } // // destructor tells the interp to delete the instance // configfile::~configfile() { delete_obj( d_id ); } // // make sure the interp is initialized...initialize if not // void configfile::assertInitialized() { if( !Py_IsInitialized() ) { Py_NoSiteFlag = 1; Py_FrozenFlag = 0; Py_VerboseFlag = 0; Py_Initialize(); PyRun_SimpleString( "import configfile" ); } } const char* configfile::getFileName() { return configfile_getFileName( d_id ); } CFObj configfile::getVars() { return CFObj( configfile_getVars( d_id, objCnt++ ) ); } CFObj configfile::getValue( char* var ) { return CFObj( configfile_getValue( d_id, var, objCnt++ ) ); } CFObj configfile::getValue( const CFObj& var ) { if( var.type() != CFObj::CFSTRING ) { throw CFException( "cannot call getValue() with a non-string CFObj" ); } return CFObj( configfile_getValue( d_id, var.getString(), objCnt++ ) ); } // // stream for exception...simply add the value string // ostream& operator<<( ostream& ostr, const CFException& cfe ) { ostr << cfe.getVal(); return ostr; } // // stream for CFObj...recursive for "complex" types // ostream& operator<<( ostream& ostr, const CFObj& cfo ) { CFObj::CFObjType t = cfo.type(); if( t == CFObj::CFLIST ) { ostr << "["; int len = cfo.length(); for( int i = 0; i < len; i++ ) { ostr << cfo[i]; if( i+1 < len ) { ostr << ", "; } } ostr << "]"; } else if( t == CFObj::CFMAP ) { ostr << "{"; CFObj keys = cfo.keys(); int numKeys = keys.length(); for( int i = 0; i < numKeys; i++ ) { ostr << keys[i]; ostr << " : "; ostr << cfo[keys[i]]; if( i+1 < numKeys ) { ostr << ", "; } } ostr << "}"; } else if( t == CFObj::CFINT ) { ostr << cfo.getInt(); } else if( t == CFObj::CFSTRING ) { ostr << "\"" << cfo.getString() << "\""; } else if( t == CFObj::CFFLOAT ) { ostr << cfo.getFloat(); } else if( t == CFObj::CFDOUBLE ) { ostr << cfo.getDouble(); } else { ostr << "CFUNKNOWN"; } return ostr; }