summaryrefslogtreecommitdiffstats
path: root/include/ixion/model_context.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/ixion/model_context.hpp')
-rw-r--r--include/ixion/model_context.hpp446
1 files changed, 446 insertions, 0 deletions
diff --git a/include/ixion/model_context.hpp b/include/ixion/model_context.hpp
new file mode 100644
index 0000000..b9d0987
--- /dev/null
+++ b/include/ixion/model_context.hpp
@@ -0,0 +1,446 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_IXION_MODEL_CONTEXT_HPP
+#define INCLUDED_IXION_MODEL_CONTEXT_HPP
+
+#include "env.hpp"
+#include "formula_tokens_fwd.hpp"
+#include "types.hpp"
+
+#include <string>
+#include <memory>
+#include <variant>
+
+namespace ixion {
+
+class cell_access;
+class dirty_cell_tracker;
+class formula_cell;
+class formula_name_resolver;
+class formula_result;
+class matrix;
+class model_iterator;
+class named_expressions_iterator;
+struct abs_address_t;
+struct abs_range_t;
+struct abs_rc_range_t;
+struct config;
+struct named_expression_t;
+
+namespace iface {
+
+class session_handler;
+class table_handler;
+
+}
+
+namespace detail {
+
+class model_context_impl;
+
+}
+
+/**
+ * This class stores all data relevant to current session. You can think of
+ * this like a document model for each formula calculation run. Note that
+ * only those methods called from the formula interpreter are specified in
+ * the interface; this explains why accessors for the most part only have
+ * the 'get' method not paired with its 'set' counterpart.
+ */
+class IXION_DLLPUBLIC model_context final
+{
+ friend class named_expressions_iterator;
+ friend class cell_access;
+
+ std::unique_ptr<detail::model_context_impl> mp_impl;
+
+public:
+ class IXION_DLLPUBLIC session_handler_factory
+ {
+ public:
+ virtual std::unique_ptr<iface::session_handler> create();
+ virtual ~session_handler_factory();
+ };
+
+ /**
+ * Cell value only to be used to input a collection of cells to sheet.
+ * Formula cells are not supported.
+ */
+ struct IXION_DLLPUBLIC input_cell
+ {
+ using value_type = std::variant<bool, double, std::string_view>;
+
+ celltype_t type;
+ value_type value;
+
+ /** Initializes the cell to be empty. */
+ input_cell(std::nullptr_t);
+ /** Boolean cell value. */
+ input_cell(bool b);
+ /** The char array must be null-terminated. */
+ input_cell(const char* s);
+ /** Numeric cell value. */
+ input_cell(double v);
+
+ input_cell(const input_cell& other);
+ };
+
+ class IXION_DLLPUBLIC input_row
+ {
+ std::initializer_list<input_cell> m_cells;
+ public:
+ input_row(std::initializer_list<input_cell> cells);
+
+ const std::initializer_list<input_cell>& cells() const;
+ };
+
+ model_context();
+ model_context(const rc_size_t& sheet_size);
+ ~model_context();
+
+ /**
+ * Query the current policy on what to do when a formula cell result is
+ * being requested while the result has not yet been computed.
+ */
+ formula_result_wait_policy_t get_formula_result_wait_policy() const;
+
+ /**
+ * This method is used to notify the model access implementer of formula
+ * events.
+ *
+ * @param event event type.
+ */
+ void notify(formula_event_t event);
+
+ const config& get_config() const;
+ dirty_cell_tracker& get_cell_tracker();
+ const dirty_cell_tracker& get_cell_tracker() const;
+
+ bool is_empty(const abs_address_t& addr) const;
+ bool is_empty(const abs_range_t& range) const;
+ celltype_t get_celltype(const abs_address_t& addr) const;
+ cell_value_t get_cell_value_type(const abs_address_t& addr) const;
+
+ /**
+ * Get a numeric representation of the cell value at specified position.
+ * If the cell at the specified position is a formula cell and its result
+ * has not yet been computed, it will block until the result becomes
+ * available.
+ *
+ * @param addr position of the cell.
+ *
+ * @return numeric representation of the cell value.
+ */
+ double get_numeric_value(const abs_address_t& addr) const;
+ bool get_boolean_value(const abs_address_t& addr) const;
+ string_id_t get_string_identifier(const abs_address_t& addr) const;
+
+ /**
+ * Get a string value associated with the cell at the specified position.
+ * It returns a valid string value only when the cell is a string cell, or
+ * is a formula cell containing a string result. Otherwise, it returns a
+ * nullptr.
+ *
+ * @param addr position of the cell.
+ *
+ * @return pointer to a string value if the cell stores a valid string
+ * value, else nullptr.
+ */
+ std::string_view get_string_value(const abs_address_t& addr) const;
+ const formula_cell* get_formula_cell(const abs_address_t& addr) const;
+ formula_cell* get_formula_cell(const abs_address_t& addr);
+
+ formula_result get_formula_result(const abs_address_t& addr) const;
+
+ /**
+ * Get a named expression token set associated with specified name if
+ * present. It first searches the local sheet scope for the name, then if
+ * it's not present, it searches the global scope.
+ *
+ * @param sheet index of the sheet scope to search in.
+ * @param name name of the expression.
+ *
+ * @return const pointer to the token set if exists, nullptr otherwise.
+ */
+ const named_expression_t* get_named_expression(sheet_t sheet, std::string_view name) const;
+
+ double count_range(const abs_range_t& range, values_t values_type) const;
+
+ /**
+ * Obtain range value in matrix form. Multi-sheet ranges are not
+ * supported. If the specified range consists of multiple sheets, it
+ * throws an exception.
+ *
+ * @param range absolute, single-sheet range address. Multi-sheet ranges
+ * are not allowed.
+ *
+ * @return range value represented as matrix.
+ */
+ matrix get_range_value(const abs_range_t& range) const;
+
+ /**
+ * Session handler instance receives various events from the formula
+ * interpretation run, in order to respond to those events. This is
+ * optional; the model context implementation is not required to provide a
+ * handler.
+ *
+ * @return a new session handler instance. It may be nullptr.
+ */
+ std::unique_ptr<iface::session_handler> create_session_handler();
+
+ /**
+ * Table interface provides access to all table ranges stored in the
+ * document model. A table is a 2-dimensional range of cells that include
+ * named columns. It is used when resolving a table reference that refers
+ * to a cell or a range of cells by the table name and/or column name.
+ *
+ * @return non-null pointer to the table storage inside the model, or
+ * nullptr if no table is present or supported by the model
+ * implementation.
+ */
+ iface::table_handler* get_table_handler();
+ const iface::table_handler* get_table_handler() const;
+
+ /**
+ * Try to add a new string to the string pool. If the same string already
+ * exists in the pool, the new string won't be added to the pool.
+ *
+ * @param s string to try to add to the pool.
+ *
+ * @return string_id_t integer value representing the string.
+ */
+ string_id_t add_string(std::string_view s);
+ const std::string* get_string(string_id_t identifier) const;
+
+ /**
+ * Get the index of sheet from sheet name. If the sheet name doesn't exist,
+ * it returns a value equal to <code>ixion::invalid_sheet</code>.
+ *
+ * @param name sheet name.
+ *
+ * @return 0-based sheet index, or <code>ixion::invalid_sheet</code> in case
+ * the document doesn't have a sheet by the specified name.
+ */
+ sheet_t get_sheet_index(std::string_view name) const;
+ std::string get_sheet_name(sheet_t sheet) const;
+
+ /**
+ * Set a new name to an existing sheet.
+ *
+ * @param sheet 0-based sheet index.
+ * @param name New name of a sheet.
+ */
+ void set_sheet_name(sheet_t sheet, std::string name);
+
+ /**
+ * Get the size of a sheet.
+ *
+ * @return sheet size.
+ */
+ rc_size_t get_sheet_size() const;
+
+ /**
+ * Return the number of sheets.
+ *
+ * @return number of sheets.
+ */
+ size_t get_sheet_count() const;
+
+ string_id_t append_string(std::string_view s);
+
+ void set_sheet_size(const rc_size_t& sheet_size);
+ void set_config(const config& cfg);
+
+ void empty_cell(const abs_address_t& addr);
+
+ void set_numeric_cell(const abs_address_t& addr, double val);
+ void set_boolean_cell(const abs_address_t& adr, bool val);
+ void set_string_cell(const abs_address_t& addr, std::string_view s);
+ void set_string_cell(const abs_address_t& addr, string_id_t identifier);
+
+ cell_access get_cell_access(const abs_address_t& addr) const;
+
+ /**
+ * Duplicate the value of the source cell to one or more cells located
+ * immediately below it.
+ *
+ * @param src position of the source cell to copy the value from.
+ * @param n_dst number of cells below to copy the value to. It must be at
+ * least one.
+ */
+ void fill_down_cells(const abs_address_t& src, size_t n_dst);
+
+ /**
+ * Set a formula cell at a specified address.
+ *
+ * @param addr address at which to set a formula cell.
+ * @param tokens formula tokens to put into the formula cell.
+ *
+ * @return pointer to the formula cell instance inserted into the model.
+ */
+ formula_cell* set_formula_cell(const abs_address_t& addr, formula_tokens_t tokens);
+
+ /**
+ * Set a formula cell at a specified address. This variant takes a
+ * formula tokens store that can be shared between multiple formula cell
+ * instances.
+ *
+ * @param addr address at which to set a formula cell.
+ * @param tokens formula tokens to put into the formula cell.
+ *
+ * @return pointer to the formula cell instance inserted into the model.
+ */
+ formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens);
+
+ /**
+ * Set a formula cell at a specified address. This variant takes a
+ * formula tokens store that can be shared between multiple formula cell
+ * instances.
+ *
+ * @param addr address at which to set a formula cell.
+ * @param tokens formula tokens to put into the formula cell.
+ * @param result cached result of this formula cell.
+ *
+ * @return pointer to the formula cell instance inserted into the model.
+ */
+ formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens, formula_result result);
+
+ void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens);
+
+ void set_grouped_formula_cells(const abs_range_t& group_range, formula_tokens_t tokens, formula_result result);
+
+ abs_range_t get_data_range(sheet_t sheet) const;
+
+ /**
+ * Set a named expression associated with a string name in the global
+ * scope.
+ *
+ * @param name name of the expression.
+ * @param expr formula tokens to use for the named expression.
+ */
+ void set_named_expression(std::string name, formula_tokens_t expr);
+
+ /**
+ * Set a named expression associated with a string name in the global
+ * scope.
+ *
+ * @param name name of the expression.
+ * @param origin position of the origin cell. Origin cell is relevant
+ * only when you need to convert the tokens into a string
+ * representation.
+ * @param expr formula tokens to use for the named expression.
+ */
+ void set_named_expression(std::string name, const abs_address_t& origin, formula_tokens_t expr);
+
+ /**
+ * Set a named expression associated with a string name in a sheet-local
+ * scope.
+ *
+ * @param sheet 0-based index of the sheet to register this expression
+ * with.
+ * @param name name of the expression.
+ * @param expr formula tokens to use for the named expression.
+ */
+ void set_named_expression(sheet_t sheet, std::string name, formula_tokens_t expr);
+
+ /**
+ * Set a named expression associated with a string name in a sheet-local
+ * scope.
+ *
+ * @param sheet 0-based index of the sheet to register this expression
+ * with.
+ * @param name name of the expression.
+ * @param origin position of the origin cell. Origin cell is relevant
+ * only when you need to convert the tokens into a string
+ * representation.
+ * @param expr formula tokens to use for the named expression.
+ */
+ void set_named_expression(sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t expr);
+
+ /**
+ * Append a new sheet to the model. The caller must ensure that the name
+ * of the new sheet is unique within the model context. When the name
+ * being used for the new sheet already exists, it throws a
+ * model_context_error exception.
+ *
+ * @param name name of the sheet to be inserted.
+ *
+ * @return sheet index of the inserted sheet.
+ *
+ * @throw model_context_error
+ */
+ sheet_t append_sheet(std::string name);
+
+ /**
+ * A convenient way to mass-insert a range of cell values. You can
+ * use a nested initializet list representing a range of cell values. The
+ * outer list represents rows.
+ *
+ * @param sheet sheet index.
+ * @param rows nested list of cell values. The outer list represents
+ * rows.
+ */
+ void set_cell_values(sheet_t sheet, std::initializer_list<input_row> rows);
+
+ void set_session_handler_factory(session_handler_factory* factory);
+
+ void set_table_handler(iface::table_handler* handler);
+
+ size_t get_string_count() const;
+
+ void dump_strings() const;
+
+ /**
+ * Get an integer string ID from a string value. If the string value
+ * doesn't exist in the pool, the value equal to empty_string_id gets
+ * returned.
+ *
+ * @param s string value.
+ *
+ * @return string_id_t integer string ID associated with the string value
+ * given.
+ */
+ string_id_t get_identifier_from_string(std::string_view s) const;
+
+ /**
+ * Get an immutable iterator that lets you iterate cell values in one
+ * sheet one at a time. <i>The caller has to ensure that the model
+ * content does not change for the duration of the iteration.</i>
+ *
+ * @param sheet sheet index.
+ * @param dir direction of the iteration.
+ * @param range range on the specified sheet to iterate over.
+ *
+ * @return model iterator instance.
+ */
+ model_iterator get_model_iterator(
+ sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const;
+
+ /**
+ * Get an iterator for global named expressions.
+ */
+ named_expressions_iterator get_named_expressions_iterator() const;
+
+ /**
+ * Get an interator for sheet-local named expressions.
+ *
+ * @param sheet 0-based index of the sheet where the named expressions are
+ * stored.
+ */
+ named_expressions_iterator get_named_expressions_iterator(sheet_t sheet) const;
+
+ void walk(
+ sheet_t sheet, const abs_rc_range_t& range, column_block_callback_t cb) const;
+
+ bool empty() const;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */