summaryrefslogtreecommitdiffstats
path: root/src/libixion/model_context_impl.hpp
blob: 57b73d8da7d909a42676a340a7959714c04c996e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/* -*- 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_MODEL_CONTEXT_IMPL_HPP
#define INCLUDED_MODEL_CONTEXT_IMPL_HPP

#include "ixion/model_context.hpp"
#include "ixion/types.hpp"
#include "ixion/config.hpp"
#include "ixion/dirty_cell_tracker.hpp"

#include "workbook.hpp"
#include "column_store_type.hpp"

#include <vector>
#include <string>
#include <unordered_map>
#include <mutex>
#include <deque>

namespace ixion { namespace detail {

class safe_string_pool
{
    using string_pool_type = std::deque<std::string>;
    using string_map_type = std::unordered_map<std::string_view, string_id_t>;

    std::mutex m_mtx;
    string_pool_type m_strings;
    string_map_type m_string_map;
    std::string m_empty_string;

    string_id_t append_string_unsafe(std::string_view s);

public:
    string_id_t append_string(std::string_view s);
    string_id_t add_string(std::string_view s);
    const std::string* get_string(string_id_t identifier) const;

    size_t size() const;
    void dump_strings() const;
    string_id_t get_identifier_from_string(std::string_view s) const;
};

class model_context_impl
{
    typedef std::vector<std::string> strings_type;

public:
    model_context_impl() = delete;
    model_context_impl(const model_context_impl&) = delete;
    model_context_impl& operator= (model_context_impl) = delete;

    model_context_impl(model_context& parent, const rc_size_t& sheet_size);
    ~model_context_impl();

    formula_result_wait_policy_t get_formula_result_wait_policy() const
    {
        return m_formula_res_wait_policy;
    }

    void notify(formula_event_t event);

    const config& get_config() const
    {
        return m_config;
    }

    void set_config(const config& cfg)
    {
        m_config = cfg;
    }

    void set_sheet_size(const rc_size_t& sheet_size);

    dirty_cell_tracker& get_cell_tracker()
    {
        return m_tracker;
    }

    const dirty_cell_tracker& get_cell_tracker() const
    {
        return m_tracker;
    }

    std::unique_ptr<iface::session_handler> create_session_handler();

    void set_session_handler_factory(model_context::session_handler_factory* factory)
    {
        mp_session_factory = factory;
    }

    iface::table_handler* get_table_handler()
    {
        return mp_table_handler;
    }

    const iface::table_handler* get_table_handler() const
    {
        return mp_table_handler;
    }

    void set_table_handler(iface::table_handler* handler)
    {
        mp_table_handler = handler;
    }

    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& addr, 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);
    void fill_down_cells(const abs_address_t& src, size_t n_dst);
    formula_cell* set_formula_cell(const abs_address_t& addr, const formula_tokens_store_ptr_t& tokens);
    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;

    bool is_empty(const abs_address_t& addr) const;
    bool is_empty(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;
    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;
    std::string_view get_string_value(const abs_address_t& addr) const;
    string_id_t get_identifier_from_string(std::string_view s) 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;

    void set_named_expression(std::string name, const abs_address_t& origin, formula_tokens_t&& expr);
    void set_named_expression(sheet_t sheet, std::string name, const abs_address_t& origin, formula_tokens_t&& expr);

    const named_expression_t* get_named_expression(std::string_view name) const;
    const named_expression_t* get_named_expression(sheet_t sheet, std::string_view name) const;

    sheet_t get_sheet_index(std::string_view name) const;
    std::string get_sheet_name(sheet_t sheet) const;
    void set_sheet_name(sheet_t sheet, std::string name);
    rc_size_t get_sheet_size() const;
    size_t get_sheet_count() const;
    sheet_t append_sheet(std::string&& name);

    void set_cell_values(sheet_t sheet, std::initializer_list<model_context::input_row>&& rows);

    string_id_t append_string(std::string_view s);
    string_id_t add_string(std::string_view s);
    const std::string* get_string(string_id_t identifier) const;
    size_t get_string_count() const;
    void dump_strings() const;

    const column_store_t* get_column(sheet_t sheet, col_t col) const;
    const column_stores_t* get_columns(sheet_t sheet) const;

    double count_range(abs_range_t range, values_t values_type) const;

    void walk(sheet_t sheet, const abs_rc_range_t& range, column_block_callback_t cb) const;

    bool empty() const;

    const worksheet* fetch_sheet(sheet_t sheet_index) const;

    column_store_t::const_position_type get_cell_position(const abs_address_t& addr) const;

    const detail::named_expressions_t& get_named_expressions() const;
    const detail::named_expressions_t& get_named_expressions(sheet_t sheet) const;

    model_iterator get_model_iterator(
        sheet_t sheet, rc_direction_t dir, const abs_rc_range_t& range) const;

private:
    abs_range_t shrink_to_workbook(abs_range_t range) const;

private:
    model_context& m_parent;

    rc_size_t m_sheet_size;
    workbook m_sheets;

    config m_config;
    dirty_cell_tracker m_tracker;
    iface::table_handler* mp_table_handler;
    detail::named_expressions_t m_named_expressions;

    model_context::session_handler_factory* mp_session_factory;

    strings_type m_sheet_names; ///< index to sheet name map.

    safe_string_pool m_str_pool;

    formula_result_wait_policy_t m_formula_res_wait_policy;
};

}}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */