1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 #include "formula_tokens.hpp"
9 #include "formula_token.hpp"
10 #include "orcus/spreadsheet/document.hpp"
11
12 #include <ixion/formula_tokens.hpp>
13 #include <structmember.h>
14
15 namespace ss = orcus::spreadsheet;
16
17 namespace orcus { namespace python {
18
19 namespace {
20
21 /** non-python part. */
22 struct formula_tokens_data
23 {
24 const ss::document* doc;
25 ixion::abs_address_t origin;
26 const ixion::formula_tokens_t* tokens = nullptr;
27 ixion::formula_tokens_t::const_iterator pos;
28 ixion::formula_tokens_t::const_iterator end;
29 };
30
31 /** python object */
32 struct pyobj_formula_tokens
33 {
34 PyObject_HEAD
35
36 formula_tokens_data* data = nullptr;
37 };
38
t(PyObject * self)39 inline pyobj_formula_tokens* t(PyObject* self)
40 {
41 return reinterpret_cast<pyobj_formula_tokens*>(self);
42 }
43
init_members(pyobj_formula_tokens * self,const ss::document & doc,const ixion::abs_address_t & origin,const ixion::formula_tokens_t & tokens)44 void init_members(
45 pyobj_formula_tokens* self, const ss::document& doc, const ixion::abs_address_t& origin, const ixion::formula_tokens_t& tokens)
46 {
47 assert(self->data);
48 self->data->doc = &doc;
49 self->data->origin = origin;
50 self->data->tokens = &tokens;
51 }
52
tp_dealloc(pyobj_formula_tokens * self)53 void tp_dealloc(pyobj_formula_tokens* self)
54 {
55 delete self->data;
56 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
57 }
58
tp_init(pyobj_formula_tokens * self,PyObject *,PyObject *)59 int tp_init(pyobj_formula_tokens* self, PyObject* /*args*/, PyObject* /*kwargs*/)
60 {
61 return 0;
62 }
63
tp_new(PyTypeObject * type,PyObject *,PyObject *)64 PyObject* tp_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/)
65 {
66 pyobj_formula_tokens* self = t(type->tp_alloc(type, 0));
67 self->data = new formula_tokens_data;
68 return reinterpret_cast<PyObject*>(self);
69 }
70
tp_iter(PyObject * self)71 PyObject* tp_iter(PyObject* self)
72 {
73 formula_tokens_data& data = *t(self)->data;
74 data.pos = data.tokens->cbegin();
75 data.end = data.tokens->cend();
76
77 Py_INCREF(self);
78 return self;
79 }
80
tp_iternext(PyObject * self)81 PyObject* tp_iternext(PyObject* self)
82 {
83 formula_tokens_data& data = *t(self)->data;
84
85 if (data.pos == data.end)
86 {
87 // No more elements. Stop the iteration.
88 PyErr_SetNone(PyExc_StopIteration);
89 return nullptr;
90 }
91
92 PyObject* ft_obj = create_formula_token_object(*data.doc, data.origin, **data.pos);
93 ++data.pos;
94 return ft_obj;
95 }
96
sq_length(PyObject * self)97 Py_ssize_t sq_length(PyObject* self)
98 {
99 formula_tokens_data& data = *t(self)->data;
100 return data.tokens->size();
101 }
102
103 PySequenceMethods tp_as_sequence =
104 {
105 sq_length, // lenfunc sq_length
106 0, // binaryfunc sq_concat
107 0, // ssizeargfunc sq_repeat
108 0, // ssizeargfunc sq_item
109 0, // void *was_sq_slice
110 0, // ssizeobjargproc sq_ass_item
111 0, // void *was_sq_ass_slice
112 0, // objobjproc sq_contains
113 0, // binaryfunc sq_inplace_concat
114 0, // ssizeargfunc sq_inplace_repeat
115 };
116
117 PyMethodDef tp_methods[] =
118 {
119 { nullptr }
120 };
121
122 PyMemberDef tp_members[] =
123 {
124 { nullptr }
125 };
126
127 PyTypeObject formula_tokens_type =
128 {
129 PyVarObject_HEAD_INIT(nullptr, 0)
130 "orcus.FormulaTokens", // tp_name
131 sizeof(pyobj_formula_tokens), // tp_basicsize
132 0, // tp_itemsize
133 (destructor)tp_dealloc, // tp_dealloc
134 0, // tp_print
135 0, // tp_getattr
136 0, // tp_setattr
137 0, // tp_compare
138 0, // tp_repr
139 0, // tp_as_number
140 &tp_as_sequence, // tp_as_sequence
141 0, // tp_as_mapping
142 0, // tp_hash
143 0, // tp_call
144 0, // tp_str
145 0, // tp_getattro
146 0, // tp_setattro
147 0, // tp_as_buffer
148 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
149 "orcus spreadsheet formula tokens", // tp_doc
150 0, // tp_traverse
151 0, // tp_clear
152 0, // tp_richcompare
153 0, // tp_weaklistoffset
154 tp_iter, // tp_iter
155 tp_iternext, // tp_iternext
156 tp_methods, // tp_methods
157 tp_members, // tp_members
158 0, // tp_getset
159 0, // tp_base
160 0, // tp_dict
161 0, // tp_descr_get
162 0, // tp_descr_set
163 0, // tp_dictoffset
164 (initproc)tp_init, // tp_init
165 0, // tp_alloc
166 tp_new, // tp_new
167 };
168
169 } // anonymous namespace
170
create_formula_tokens_iterator_object(const ss::document & doc,const ixion::abs_address_t & origin,const ixion::formula_tokens_t & tokens)171 PyObject* create_formula_tokens_iterator_object(
172 const ss::document& doc, const ixion::abs_address_t& origin, const ixion::formula_tokens_t& tokens)
173 {
174 PyTypeObject* ft_type = get_formula_tokens_type();
175 if (!ft_type)
176 {
177 PyErr_SetString(PyExc_RuntimeError, "Failed to get the formula tokens type object.");
178 return nullptr;
179 }
180
181 PyObject* obj = ft_type->tp_new(ft_type, nullptr, nullptr);
182 if (!obj)
183 {
184 PyErr_SetString(PyExc_RuntimeError, "Failed to instantiate a formula tokens object.");
185 return nullptr;
186 }
187
188 init_members(t(obj), doc, origin, tokens);
189
190 return obj;
191 }
192
get_formula_tokens_type()193 PyTypeObject* get_formula_tokens_type()
194 {
195 return &formula_tokens_type;
196 }
197
198 }}
199
200 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
201