Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/python/src/object/enum.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 6.9 KB
Line 
1// Copyright David Abrahams 2002.
2// Distributed under the Boost Software License, Version 1.0. (See
3// accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6#include <boost/python/object/enum_base.hpp>
7#include <boost/python/cast.hpp>
8#include <boost/python/scope.hpp>
9#include <boost/python/object.hpp>
10#include <boost/python/tuple.hpp>
11#include <boost/python/dict.hpp>
12#include <boost/python/str.hpp>
13#include <boost/python/extract.hpp>
14#include <boost/python/object_protocol.hpp>
15#include <structmember.h>
16
17namespace boost { namespace python { namespace objects { 
18
19struct enum_object
20{
21    PyIntObject base_object;
22    PyObject* name;
23};
24
25static PyMemberDef enum_members[] = {
26    {"name", T_OBJECT_EX, offsetof(enum_object,name),READONLY, 0},
27    {0, 0, 0, 0, 0}
28};
29
30
31extern "C"
32{
33    static PyObject* enum_repr(PyObject* self_)
34    {
35        enum_object* self = downcast<enum_object>(self_);
36        if (!self->name)
37        {
38            return PyString_FromFormat("%s(%ld)", self_->ob_type->tp_name, PyInt_AS_LONG(self_));
39        }
40        else
41        {
42            char* name = PyString_AsString(self->name);
43            if (name == 0)
44                return 0;
45           
46            return PyString_FromFormat("%s.%s", self_->ob_type->tp_name, name);
47        }
48    }
49
50    static PyObject* enum_str(PyObject* self_)
51    {
52        enum_object* self = downcast<enum_object>(self_);
53        if (!self->name)
54        {
55            return PyInt_Type.tp_str(self_);
56        }
57        else
58        {
59            return incref(self->name);
60        }
61    }
62}
63
64static PyTypeObject enum_type_object = {
65    PyObject_HEAD_INIT(0) // &PyType_Type
66    0,
67    "Boost.Python.enum",
68    sizeof(enum_object),                    /* tp_basicsize */
69    0,                                      /* tp_itemsize */
70    0,                                      /* tp_dealloc */
71    0,                                      /* tp_print */
72    0,                                      /* tp_getattr */
73    0,                                      /* tp_setattr */
74    0,                                      /* tp_compare */
75    enum_repr,                              /* tp_repr */
76    0,                                      /* tp_as_number */
77    0,                                      /* tp_as_sequence */
78    0,                                      /* tp_as_mapping */
79    0,                                      /* tp_hash */
80    0,                                      /* tp_call */
81    enum_str,                               /* tp_str */
82    0,                                      /* tp_getattro */
83    0,                                      /* tp_setattro */
84    0,                                      /* tp_as_buffer */
85    Py_TPFLAGS_DEFAULT
86    | Py_TPFLAGS_CHECKTYPES
87    | Py_TPFLAGS_HAVE_GC
88    | Py_TPFLAGS_BASETYPE,                  /* tp_flags */
89    0,                                      /* tp_doc */
90    0,                                      /* tp_traverse */
91    0,                                      /* tp_clear */
92    0,                                      /* tp_richcompare */
93    0,                                      /* tp_weaklistoffset */
94    0,                                      /* tp_iter */
95    0,                                      /* tp_iternext */
96    0,                                      /* tp_methods */
97    enum_members,                           /* tp_members */
98    0,                                      /* tp_getset */
99    0, //&PyInt_Type,                       /* tp_base */
100    0,                                      /* tp_dict */
101    0,                                      /* tp_descr_get */
102    0,                                      /* tp_descr_set */
103    0,                                      /* tp_dictoffset */
104    0,                                      /* tp_init */
105    0,                                      /* tp_alloc */
106    0,                                      /* tp_new */
107    0,                                      /* tp_free */
108    0,                                      /* tp_is_gc */
109    0,                                      /* tp_bases */
110    0,                                      /* tp_mro */
111    0,                                      /* tp_cache */
112    0,                                      /* tp_subclasses */
113    0,                                      /* tp_weaklist */
114#if PYTHON_API_VERSION >= 1012
115    0                                       /* tp_del */
116#endif
117};
118
119object module_prefix();
120
121namespace
122{
123  object new_enum_type(char const* name)
124  {
125      if (enum_type_object.tp_dict == 0)
126      {
127          enum_type_object.ob_type = incref(&PyType_Type);
128          enum_type_object.tp_base = &PyInt_Type;
129          if (PyType_Ready(&enum_type_object))
130              throw_error_already_set();
131      }
132
133      type_handle metatype(borrowed(&PyType_Type));
134      type_handle base(borrowed(&enum_type_object));
135
136      // suppress the instance __dict__ in these enum objects. There
137      // may be a slicker way, but this'll do for now.
138      dict d;
139      d["__slots__"] = tuple();
140      d["values"] = dict();
141
142      object module_name = module_prefix();
143      if (module_name)
144          module_name += '.';
145     
146      object result = (object(metatype))(
147          module_name + name, make_tuple(base), d);
148     
149      scope().attr(name) = result;
150
151      return result;
152  }
153}
154
155enum_base::enum_base(
156    char const* name
157    , converter::to_python_function_t to_python
158    , converter::convertible_function convertible
159    , converter::constructor_function construct
160    , type_info id
161    )
162    : object(new_enum_type(name))
163{
164    converter::registration& converters
165        = const_cast<converter::registration&>(
166            converter::registry::lookup(id));
167           
168    converters.m_class_object = downcast<PyTypeObject>(this->ptr());
169    converter::registry::insert(to_python, id);
170    converter::registry::insert(convertible, construct, id);
171}
172
173void enum_base::add_value(char const* name_, long value)
174{
175    // Convert name to Python string
176    object name(name_);
177
178    // Create a new enum instance by calling the class with a value
179    object x = (*this)(value);
180
181    // Store the object in the enum class
182    (*this).attr(name_) = x;
183
184    dict d = extract<dict>(this->attr("values"))();
185    d[value] = x;
186   
187    // Set the name field in the new enum instanec
188    enum_object* p = downcast<enum_object>(x.ptr());
189    Py_XDECREF(p->name);
190    p->name = incref(name.ptr());
191}
192
193void enum_base::export_values()
194{
195    dict d = extract<dict>(this->attr("values"))();
196    list values = d.values();
197    scope current;
198   
199    for (unsigned i = 0, max = len(values); i < max; ++i)
200    {
201        api::setattr(current, object(values[i].attr("name")), values[i]);
202    }
203 }
204
205PyObject* enum_base::to_python(PyTypeObject* type_, long x)
206{
207    object type((type_handle(borrowed(type_))));
208
209    dict d = extract<dict>(type.attr("values"))();
210    object v = d.get(x, object());
211    return incref(
212        (v == object() ? type(x) : v).ptr());
213}
214
215}}} // namespace boost::python::object
Note: See TracBrowser for help on using the repository browser.