summaryrefslogtreecommitdiffstats
path: root/src/python/named_expressions.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/python/named_expressions.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/python/named_expressions.cpp b/src/python/named_expressions.cpp
new file mode 100644
index 0000000..6faffee
--- /dev/null
+++ b/src/python/named_expressions.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "named_expressions.hpp"
+#include "named_expression.hpp"
+#include "global.hpp"
+#include "orcus/spreadsheet/document.hpp"
+
+#include <ixion/formula.hpp>
+#include <ixion/model_context.hpp>
+#include <ixion/named_expressions_iterator.hpp>
+#include <ixion/formula_name_resolver.hpp>
+#include <structmember.h>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus { namespace python {
+
+namespace {
+
+/** non-python part. */
+struct named_exps_data
+{
+ ss::sheet_t origin_sheet = -1; // -1 for global, >=0 for sheet local.
+ const ss::document* doc = nullptr;
+ ixion::named_expressions_iterator src; // original iterator to copy from.
+ ixion::named_expressions_iterator iter;
+};
+
+/** python object. */
+struct pyobj_named_exps
+{
+ PyObject_HEAD
+
+ named_exps_data* data;
+};
+
+inline pyobj_named_exps* t(PyObject* self)
+{
+ return reinterpret_cast<pyobj_named_exps*>(self);
+}
+
+PyObject* named_exps_names(PyObject* self, PyObject* /*args*/, PyObject* /*kwargs*/)
+{
+ named_exps_data& data = *t(self)->data;
+ PyObject* s = PySet_New(nullptr);
+
+ for (auto iter = data.src; iter.has(); iter.next())
+ {
+ const std::string* name = iter.get().name;
+ PySet_Add(s, PyUnicode_FromStringAndSize(name->data(), name->size()));
+ }
+
+ return s;
+}
+
+void tp_dealloc(pyobj_named_exps* self)
+{
+ delete self->data;
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+int tp_init(pyobj_named_exps* /*self*/, PyObject* /*args*/, PyObject* /*kwargs*/)
+{
+ return 0;
+}
+
+PyObject* tp_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/)
+{
+ pyobj_named_exps* self = t(type->tp_alloc(type, 0));
+ self->data = new named_exps_data;
+ return reinterpret_cast<PyObject*>(self);
+}
+
+PyObject* tp_iter(PyObject* self)
+{
+ named_exps_data& data = *t(self)->data;
+ data.iter = data.src;
+
+ Py_INCREF(self);
+ return self;
+}
+
+PyObject* tp_iternext(PyObject* self)
+{
+ named_exps_data& data = *t(self)->data;
+ auto& iter = data.iter;
+
+ if (!iter.has())
+ {
+ PyErr_SetNone(PyExc_StopIteration);
+ return nullptr;
+ }
+
+ ixion::named_expressions_iterator::named_expression item = iter.get();
+ iter.next();
+
+ PyObject* name = PyUnicode_FromStringAndSize(item.name->data(), item.name->size());
+ if (!name)
+ return nullptr;
+
+ PyObject* ne = create_named_exp_object(*data.doc, item.expression);
+ if (!ne)
+ return nullptr;
+
+ PyObject* tup = PyTuple_New(2);
+ PyTuple_SET_ITEM(tup, 0, name);
+ PyTuple_SET_ITEM(tup, 1, ne);
+
+ return tup;
+}
+
+Py_ssize_t sq_length(PyObject* self)
+{
+ named_exps_data& data = *t(self)->data;
+ return data.src.size();
+}
+
+PySequenceMethods tp_as_sequence =
+{
+ sq_length, // lenfunc sq_length
+ 0, // binaryfunc sq_concat
+ 0, // ssizeargfunc sq_repeat
+ 0, // ssizeargfunc sq_item
+ 0, // void *was_sq_slice
+ 0, // ssizeobjargproc sq_ass_item
+ 0, // void *was_sq_ass_slice
+ 0, // objobjproc sq_contains
+ 0, // binaryfunc sq_inplace_concat
+ 0, // ssizeargfunc sq_inplace_repeat
+};
+
+PyMethodDef tp_methods[] =
+{
+ { "names", (PyCFunction)named_exps_names, METH_NOARGS, "Get names for all named expressions stored." },
+ { nullptr }
+};
+
+PyMemberDef tp_members[] =
+{
+ { nullptr }
+};
+
+PyTypeObject named_exps_type =
+{
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "orcus.NamedExpressions", // tp_name
+ sizeof(pyobj_named_exps), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)tp_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &tp_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
+ "orcus spreadsheet formula tokens", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ tp_iter, // tp_iter
+ tp_iternext, // tp_iternext
+ tp_methods, // tp_methods
+ tp_members, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ (initproc)tp_init, // tp_init
+ 0, // tp_alloc
+ tp_new, // tp_new
+};
+
+} // anonymous namespace
+
+PyObject* create_named_expressions_object(
+ spreadsheet::sheet_t origin_sheet, const spreadsheet::document& doc, ixion::named_expressions_iterator iter)
+{
+ PyTypeObject* type = get_named_exps_type();
+
+ PyObject* obj = create_object_from_type(type);
+ if (!obj)
+ return nullptr;
+
+ type->tp_init(obj, nullptr, nullptr);
+
+ named_exps_data& data = *t(obj)->data;
+ data.src = iter;
+ data.origin_sheet = origin_sheet;
+ data.doc = &doc;
+
+ return obj;
+}
+
+PyTypeObject* get_named_exps_type()
+{
+ return &named_exps_type;
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */