1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
#if !defined(TUPLE_H_INCLUDED_)
#define TUPLE_H_INCLUDED_
#include "sequence.h"
#include <string>
namespace py {
class tuple : public sequence
{
public:
//-------------------------------------------------------------------------
// constructors
//-------------------------------------------------------------------------
tuple(int sz=0) : sequence (PyTuple_New(sz)) { lose_ref(_obj); }
tuple(const tuple& other) : sequence(other) { }
tuple(PyObject* obj) : sequence(obj) { _violentTypeCheck(); }
tuple(const list& lst)
: sequence (PyList_AsTuple(lst)) { lose_ref(_obj); }
//-------------------------------------------------------------------------
// destructor
//-------------------------------------------------------------------------
virtual ~tuple() {};
//-------------------------------------------------------------------------
// operator=
//-------------------------------------------------------------------------
virtual tuple& operator=(const tuple& other) {
grab_ref(other);
return *this;
};
/*virtual*/ tuple& operator=(const object& other) {
grab_ref(other);
_violentTypeCheck();
return *this;
};
//-------------------------------------------------------------------------
// type checking
//-------------------------------------------------------------------------
virtual void _violentTypeCheck() {
if (!PyTuple_Check(_obj)) {
grab_ref(0);
fail(PyExc_TypeError, "Not a Python Tuple");
}
};
//-------------------------------------------------------------------------
// set_item
//
// We have to do a little extra checking here, because tuples can only
// be assigned to if there is only a single reference to them.
//-------------------------------------------------------------------------
virtual void set_item(int ndx, object& val) {
if (_obj->ob_refcnt != 1)
fail(PyExc_TypeError,"Tuples values can't be set if ref count > 1\n");
int rslt = PyTuple_SetItem(_obj, ndx, val);
val.disown(); //when using PyTuple_SetItem, he steals my reference
if (rslt==-1)
throw 1;
};
//-------------------------------------------------------------------------
// operator[] -- const and non-const versions of element access.
//-------------------------------------------------------------------------
indexed_ref operator [] (int i) {
// get a "borrowed" refcount
PyObject* o = PyTuple_GetItem(_obj, i);
// don't throw error for when [] fails because it might be on left hand
// side (a[0] = 1). If the tuple was just created, it will be filled
// with NULL values, and setting the values should be ok. However, we
// do want to catch index errors that might occur on the right hand side
// (obj = a[4] when a has len==3).
if (!o) {
if (PyErr_ExceptionMatches(PyExc_IndexError))
throw 1;
}
return indexed_ref(o, *this, i); // this increfs
};
};// class tuple
} // namespace
#endif // TUPLE_H_INCLUDED_
|