/* -*- 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 #include #include #include #include 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(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(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(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: */