// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears // in all copies. This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. #ifndef OBJECTS_DWA051100_H_ # define OBJECTS_DWA051100_H_ # include "wrap_python.h" # include "pyconfig.h" # include "pyptr.h" # include "boost/operators.hpp" # include namespace python { class object { public: explicit object(ref p); // Return a reference to the held object ref reference() const; // Return a raw pointer to the held object PyObject* get() const; private: ref m_p; }; class tuple : public object { public: explicit tuple(std::size_t n = 0); explicit tuple(ref p); template tuple(const std::pair& x) : object(ref(PyTuple_New(2))) { set_item(0, x.first); set_item(1, x.second); } template tuple(const First& first, const Second& second) : object(ref(PyTuple_New(2))) { set_item(0, first); set_item(1, second); } template tuple(const First& first, const Second& second, const Third& third) : object(ref(PyTuple_New(3))) { set_item(0, first); set_item(1, second); set_item(2, third); } template tuple(const First& first, const Second& second, const Third& third, const Fourth& fourth) : object(ref(PyTuple_New(4))) { set_item(0, first); set_item(1, second); set_item(2, third); set_item(3, fourth); } static PyTypeObject* type_obj(); static bool accepts(ref p); std::size_t size() const; ref operator[](std::size_t pos) const; template void set_item(std::size_t pos, const T& rhs) { this->set_item(pos, make_ptr(rhs)); } void set_item(std::size_t pos, const ref& rhs); tuple slice(int low, int high) const; friend tuple operator+(const tuple&, const tuple&); tuple& operator+=(const tuple& rhs); }; class list : public object { struct proxy; struct slice_proxy; public: explicit list(ref p); explicit list(std::size_t sz = 0); static PyTypeObject* type_obj(); static bool accepts(ref p); std::size_t size(); ref operator[](std::size_t pos) const; proxy operator[](std::size_t pos); ref get_item(std::size_t pos) const; template void set_item(std::size_t pos, const T& x) { this->set_item(pos, make_ptr(x)); } void set_item(std::size_t pos, const ref& ); // void set_item(std::size_t pos, const object& ); template void insert(std::size_t index, const T& x) { this->insert(index, make_ptr(x)); } void insert(std::size_t index, const ref& item); template void push_back(const T& item) { this->push_back(make_ptr(item)); } void push_back(const ref& item); template void append(const T& item) { this->append(make_ptr(item)); } void append(const ref& item); list slice(int low, int high) const; slice_proxy slice(int low, int high); void sort(); void reverse(); tuple as_tuple() const; }; class string : public object, public boost::multipliable2 { public: // Construct from an owned PyObject*. // Precondition: p must point to a python string. explicit string(ref p); explicit string(const char* s); string(const char* s, std::size_t length); string(const string& rhs); enum interned_t { interned }; string(const char* s, interned_t); // Get the type object for Strings static PyTypeObject* type_obj(); // Return true if the given object is a python string static bool accepts(ref o); // Return the length of the string. std::size_t size() const; // Returns a null-terminated representation of the contents of string. // The pointer refers to the internal buffer of string, not a copy. // The data must not be modified in any way. It must not be de-allocated. const char* c_str() const; string& operator*=(unsigned int repeat_count); string& operator+=(const string& rhs); friend string operator+(string x, string y); string& operator+=(const char* rhs); friend string operator+(string x, const char* y); friend string operator+(const char* x, string y); void intern(); friend string operator%(const string& format, const tuple& args); }; class dictionary : public object { private: struct proxy; public: explicit dictionary(ref p); dictionary(); void clear(); static PyTypeObject* type_obj(); static bool accepts(ref p); public: template proxy operator[](const Key& key) { return this->operator[](make_ptr(key)); } proxy operator[](ref key); template ref operator[](const Key& key) const { return this->operator[](make_ptr(key)); } ref operator[](ref key) const; template ref get_item(const Key& key) const { return this->get_item(make_ptr(key)); } ref get_item(const ref& key) const; template ref get_item(const Key& key, const Default& default_) const { return this->get_item(make_ptr(key), make_ptr(default_)); } ref get_item(const ref& key, const ref& default_) const; template void set_item(const Key& key, const Value& value) { this->set_item(make_ptr(key), make_ptr(value)); } void set_item(const ref& key, const ref& value); template void erase(const Key& key) { this->erase(make_ptr(key)); } void erase(ref key); // proxy operator[](const object& key); // ref operator[](const object& key) const; // ref get_item(const object& key, ref default_ = ref()) const; // void set_item(const object& key, const ref& value); // void erase(const object& key); list items() const; list keys() const; list values() const; std::size_t size() const; // TODO: iterator support }; struct dictionary::proxy { template const ref& operator=(const T& rhs) { return (*this) = make_ptr(rhs); } const ref& operator=(const ref& rhs); operator ref() const; private: friend class dictionary; proxy(const ref& dict, const ref& key); // This is needed to work around the very strange MSVC error report that the // return type of the built-in operator= differs from that of the ones // defined above. Couldn't hurt to make these un-assignable anyway, though. const ref& operator=(const proxy&); // Not actually implemented private: ref m_dict; ref m_key; }; struct list::proxy { template const ref& operator=(const T& rhs) { return (*this) = make_ptr(rhs); } const ref& operator=(const ref& rhs); operator ref() const; private: friend class list; proxy(const ref& list, std::size_t index); // This is needed to work around the very strange MSVC error report that the // return type of the built-in operator= differs from that of the ones // defined above. Couldn't hurt to make these un-assignable anyway, though. const ref& operator=(const proxy&); // Not actually implemented private: list m_list; std::size_t m_index; }; struct list::slice_proxy { const list& operator=(const list& rhs); operator ref() const; operator list() const; std::size_t size(); ref operator[](std::size_t pos) const; private: friend class list; slice_proxy(const ref& list, int low, int high); private: ref m_list; int m_low, m_high; }; } // namespace python BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE PyObject* to_python(const python::tuple&); python::tuple from_python(PyObject* p, python::type); inline python::tuple from_python(PyObject* p, python::type) { return from_python(p, python::type()); } PyObject* to_python(const python::list&); python::list from_python(PyObject* p, python::type); inline python::list from_python(PyObject* p, python::type) { return from_python(p, python::type()); } PyObject* to_python(const python::string&); python::string from_python(PyObject* p, python::type); inline python::string from_python(PyObject* p, python::type) { return from_python(p, python::type()); } PyObject* to_python(const python::dictionary&); python::dictionary from_python(PyObject* p, python::type); inline python::dictionary from_python(PyObject* p, python::type) { return from_python(p, python::type()); } BOOST_PYTHON_END_CONVERSION_NAMESPACE #endif // OBJECTS_DWA051100_H_