diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:48:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:48:59 +0000 |
commit | c484829272cd13a738e35412498e12f2c9a194ac (patch) | |
tree | a1f5ec09629ee895bd3963fa8820b45f2f4c574b /src/python/named_expression.cpp | |
parent | Initial commit. (diff) | |
download | liborcus-upstream/0.19.2.tar.xz liborcus-upstream/0.19.2.zip |
Adding upstream version 0.19.2.upstream/0.19.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/python/named_expression.cpp')
-rw-r--r-- | src/python/named_expression.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/python/named_expression.cpp b/src/python/named_expression.cpp new file mode 100644 index 0000000..1402daa --- /dev/null +++ b/src/python/named_expression.cpp @@ -0,0 +1,215 @@ +/* -*- 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_expression.hpp" +#include "formula_token.hpp" +#include "formula_tokens.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 of the object. */ +struct named_exp_data +{ + const ss::document* doc = nullptr; + const ixion::formula_tokens_t* tokens = nullptr; + ixion::abs_address_t origin; +}; + +/** + * Python object for orcus.NamedExpression. + */ +struct pyobj_named_exp +{ + PyObject_HEAD + + PyObject* origin; + PyObject* formula; + + named_exp_data* data; +}; + +inline pyobj_named_exp* t(PyObject* self) +{ + return reinterpret_cast<pyobj_named_exp*>(self); +} + +void init_members(pyobj_named_exp* self) +{ + Py_INCREF(Py_None); + self->origin = Py_None; + + Py_INCREF(Py_None); + self->formula = Py_None; +} + +void tp_dealloc(pyobj_named_exp* self) +{ + delete self->data; + self->data = nullptr; + + Py_CLEAR(self->origin); + Py_CLEAR(self->formula); + + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); +} + +int tp_init(pyobj_named_exp* self, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + init_members(self); + return 0; +} + +PyObject* tp_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + pyobj_named_exp* self = (pyobj_named_exp*)type->tp_alloc(type, 0); + self->data = new named_exp_data; + return reinterpret_cast<PyObject*>(self); +} + +PyObject* ne_get_formula_tokens(PyObject* self, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + named_exp_data& data = *t(self)->data; + if (!data.tokens) + { + Py_INCREF(Py_None); + return Py_None; + } + + return create_formula_tokens_iterator_object(*data.doc, data.origin, *data.tokens); +} + +PyMethodDef tp_methods[] = +{ + { "get_formula_tokens", (PyCFunction)ne_get_formula_tokens, METH_NOARGS, "Get a formula tokens iterator." }, + { nullptr } +}; + +PyMemberDef tp_members[] = +{ + { (char*)"origin", T_OBJECT_EX, offsetof(pyobj_named_exp, origin), READONLY, (char*)"anchoring cell for the named expression" }, + { (char*)"formula", T_OBJECT_EX, offsetof(pyobj_named_exp, formula), READONLY, (char*)"formula string" }, + { nullptr } +}; + +PyTypeObject named_exp_type = +{ + PyVarObject_HEAD_INIT(nullptr, 0) + "orcus.NamedExpression", // tp_name + sizeof(pyobj_named_exp), // 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 + 0, // 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 named expression", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // 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_exp_object(const spreadsheet::document& doc, const ixion::named_expression_t* exp) +{ + PyTypeObject* named_exp_type = get_named_exp_type(); + if (!named_exp_type) + { + PyErr_SetString(PyExc_RuntimeError, "Failed to get the named expression type object."); + return nullptr; + } + + PyObject* obj = named_exp_type->tp_new(named_exp_type, nullptr, nullptr); + if (!obj) + { + PyErr_SetString(PyExc_RuntimeError, "Failed to instantiate a named expression object."); + return nullptr; + } + + pyobj_named_exp* self = reinterpret_cast<pyobj_named_exp*>(obj); + init_members(self); + + if (exp) + { + named_exp_data& data = *self->data; + data.doc = &doc; + data.origin = exp->origin; + data.tokens = &exp->tokens; + + const ixion::model_context& cxt = doc.get_model_context(); + auto* resolver = doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + + // Create base + std::string origin_s = resolver->get_name(exp->origin, ixion::abs_address_t(), true); + self->origin = PyUnicode_FromStringAndSize(origin_s.data(), origin_s.size()); + + // Create formula expression string. + std::string formula_s = ixion::print_formula_tokens(cxt, exp->origin, *resolver, exp->tokens); + self->formula = PyUnicode_FromStringAndSize(formula_s.data(), formula_s.size()); + } + + return obj; +} + +PyObject* create_named_exp_dict(const ss::document& doc, ixion::named_expressions_iterator iter) +{ + PyObject* dict = PyDict_New(); + for (; iter.has(); iter.next()) + { + auto ne = iter.get(); + PyObject* name = PyUnicode_FromStringAndSize(ne.name->data(), ne.name->size()); + PyObject* tokens = create_named_exp_object(doc, ne.expression); + PyDict_SetItem(dict, name, tokens); + } + + return dict; +} + +PyTypeObject* get_named_exp_type() +{ + return &named_exp_type; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |