summaryrefslogtreecommitdiffstats
path: root/src/python/sheet_rows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/python/sheet_rows.cpp')
-rw-r--r--src/python/sheet_rows.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/python/sheet_rows.cpp b/src/python/sheet_rows.cpp
new file mode 100644
index 0000000..be49589
--- /dev/null
+++ b/src/python/sheet_rows.cpp
@@ -0,0 +1,209 @@
+/* -*- 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 "sheet_rows.hpp"
+#include "memory.hpp"
+#include "cell.hpp"
+#include "orcus/spreadsheet/sheet.hpp"
+#include "orcus/spreadsheet/document.hpp"
+
+#include <ixion/model_context.hpp>
+
+namespace orcus { namespace python {
+
+sheet_rows_data::sheet_rows_data() :
+ m_doc(nullptr),
+ m_sheet(nullptr),
+ m_range(ixion::abs_range_t::invalid),
+ m_current_row(-1) {}
+
+sheet_rows_data::~sheet_rows_data() {}
+
+namespace {
+
+/**
+ * Python object for orcus.SheetRows.
+ */
+struct pyobj_sheet_rows
+{
+ PyObject_HEAD
+
+ sheet_rows_data* m_data;
+};
+
+void sheet_rows_dealloc(pyobj_sheet_rows* self)
+{
+ delete self->m_data;
+
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+PyObject* sheet_rows_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/)
+{
+ pyobj_sheet_rows* self = (pyobj_sheet_rows*)type->tp_alloc(type, 0);
+ self->m_data = new sheet_rows_data;
+ return reinterpret_cast<PyObject*>(self);
+}
+
+int sheet_rows_init(pyobj_sheet_rows* /*self*/, PyObject* /*args*/, PyObject* /*kwargs*/)
+{
+ return 0;
+}
+
+PyObject* sheet_rows_iter(PyObject* self)
+{
+ sheet_rows_data* data = reinterpret_cast<pyobj_sheet_rows*>(self)->m_data;
+
+ const ixion::abs_range_t& range = data->m_range;
+ if (range.valid())
+ {
+ data->m_current_row = 0;
+
+ ixion::abs_rc_range_t sheet_range;
+ sheet_range.first.column = 0;
+ sheet_range.first.row = 0;
+ sheet_range.last.column = range.last.column;
+ sheet_range.last.row = range.last.row;
+
+ data->m_range_iterator = data->m_doc->get_model_context().get_model_iterator(
+ data->m_sheet->get_index(), ixion::rc_direction_t::horizontal, sheet_range);
+ }
+
+ Py_INCREF(self);
+ return self;
+}
+
+PyObject* sheet_rows_iternext(PyObject* self)
+{
+ sheet_rows_data* data = reinterpret_cast<pyobj_sheet_rows*>(self)->m_data;
+ ixion::model_iterator& iter = data->m_range_iterator;
+
+ if (!iter.has())
+ {
+ // No more elements. Stop the iteration.
+ PyErr_SetNone(PyExc_StopIteration);
+ return nullptr;
+ }
+
+ PyObject* pyobj_row = PyTuple_New(data->m_range.last.column+1);
+
+ for (; iter.has(); iter.next())
+ {
+ const auto& cell = iter.get();
+ if (cell.row != data->m_current_row)
+ {
+ ++data->m_current_row;
+ assert(cell.row == data->m_current_row);
+ break;
+ }
+
+ PyObject* obj = nullptr;
+ switch (cell.type)
+ {
+ case ixion::celltype_t::empty:
+ {
+ obj = create_cell_object_empty();
+ break;
+ }
+ case ixion::celltype_t::boolean:
+ {
+ obj = create_cell_object_boolean(std::get<bool>(cell.value));
+ break;
+ }
+ case ixion::celltype_t::numeric:
+ {
+ obj = create_cell_object_numeric(std::get<double>(cell.value));
+ break;
+ }
+ case ixion::celltype_t::string:
+ {
+ ixion::string_id_t sid = std::get<ixion::string_id_t>(cell.value);
+ const ixion::model_context& cxt = data->m_doc->get_model_context();
+ const std::string* ps = cxt.get_string(sid);
+ obj = create_cell_object_string(ps);
+ break;
+ }
+ case ixion::celltype_t::formula:
+ {
+ const ixion::formula_cell* fc = std::get<const ixion::formula_cell*>(cell.value);
+ ixion::abs_address_t pos(data->m_sheet->get_index(), cell.row, cell.col);
+ obj = create_cell_object_formula(*data->m_doc, pos, fc);
+ break;
+ }
+ case ixion::celltype_t::unknown:
+ break;
+ }
+
+ if (!obj)
+ return nullptr;
+
+ PyTuple_SetItem(pyobj_row, cell.col, obj);
+ }
+
+ return pyobj_row;
+}
+
+PyTypeObject sheet_rows_type =
+{
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "orcus.SheetRows", // tp_name
+ sizeof(pyobj_sheet_rows), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)sheet_rows_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 sheet rows iterator", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ (getiterfunc)sheet_rows_iter, // tp_iter
+ (iternextfunc)sheet_rows_iternext, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ (initproc)sheet_rows_init, // tp_init
+ 0, // tp_alloc
+ sheet_rows_new, // tp_new
+};
+
+}
+
+PyTypeObject* get_sheet_rows_type()
+{
+ return &sheet_rows_type;
+}
+
+void store_sheet_rows_data(PyObject* self, const spreadsheet::document* orcus_doc, const spreadsheet::sheet* orcus_sheet)
+{
+ sheet_rows_data* data = reinterpret_cast<pyobj_sheet_rows*>(self)->m_data;
+ data->m_doc = orcus_doc;
+ data->m_sheet = orcus_sheet;
+ data->m_range = orcus_sheet->get_data_range();
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */