summaryrefslogtreecommitdiffstats
path: root/include/ixion/address.hpp
blob: aed09a2ebbefec62ad643d4b84da426ccd404b83 (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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/* -*- 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_ADDRESS_HPP
#define INCLUDED_IXION_ADDRESS_HPP

#include "types.hpp"

#include <string>
#include <vector>
#include <ostream>
#include <unordered_set>

namespace ixion {

/**
 * Row address not specified. This is used to reference an entire column
 * when a specific column address is given.
 */
IXION_DLLPUBLIC_VAR const row_t row_unset;

/**
 * Highest number that can be used to reference a row address. Numbers
 * higher than this number are all used as special indices.
 */
IXION_DLLPUBLIC_VAR const row_t row_upper_bound;

/**
 * Column address not specified. This is used to reference an entire row
 * when a specific row address is given.
 */
IXION_DLLPUBLIC_VAR const col_t column_unset;

/**
 * Highest number that can be used to reference a column address. Numbers
 * higher than this number are all used as special indices.
 */
IXION_DLLPUBLIC_VAR const col_t column_upper_bound;

/**
 * Stores absolute address, and absolute address only.
 */
struct IXION_DLLPUBLIC abs_address_t
{
    enum init_invalid { invalid };

    sheet_t sheet;
    row_t   row;
    col_t   column;

    abs_address_t();
    abs_address_t(init_invalid);
    abs_address_t(sheet_t _sheet, row_t _row, col_t _column);
    abs_address_t(const abs_address_t& r);

    bool valid() const;
    ::std::string get_name() const;

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const abs_address_t& addr) const;
    };
};

IXION_DLLPUBLIC bool operator==(const abs_address_t& left, const abs_address_t& right);
IXION_DLLPUBLIC bool operator!=(const abs_address_t& left, const abs_address_t& right);
IXION_DLLPUBLIC bool operator<(const abs_address_t& left, const abs_address_t& right);

/**
 * Stores either absolute or relative address.
 */
struct IXION_DLLPUBLIC address_t
{
    sheet_t sheet;
    row_t   row;
    col_t   column;
    bool    abs_sheet:1;
    bool    abs_row:1;
    bool    abs_column:1;

    address_t();
    address_t(sheet_t _sheet, row_t _row, col_t _column,
              bool _abs_sheet=true, bool _abs_row=true, bool _abs_column=true);
    address_t(const address_t& r);
    address_t(const abs_address_t& r);

    bool valid() const;
    abs_address_t to_abs(const abs_address_t& origin) const;
    ::std::string get_name() const;

    void set_absolute(bool abs);

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const address_t& addr) const;
    };
};

IXION_DLLPUBLIC bool operator==(const address_t& left, const address_t& right);
IXION_DLLPUBLIC bool operator!=(const address_t& left, const address_t& right);
IXION_DLLPUBLIC bool operator<(const address_t& left, const address_t& right);

struct IXION_DLLPUBLIC abs_rc_address_t
{
    enum init_invalid { invalid };

    row_t row;
    col_t column;

    abs_rc_address_t();
    abs_rc_address_t(init_invalid);
    abs_rc_address_t(row_t _row, col_t _column);
    abs_rc_address_t(const abs_rc_address_t& r);
    abs_rc_address_t(const abs_address_t& r);

    bool valid() const;

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const abs_rc_address_t& addr) const;
    };
};

IXION_DLLPUBLIC bool operator==(const abs_rc_address_t& left, const abs_rc_address_t& right);
IXION_DLLPUBLIC bool operator!=(const abs_rc_address_t& left, const abs_rc_address_t& right);
IXION_DLLPUBLIC bool operator<(const abs_rc_address_t& left, const abs_rc_address_t& right);

/**
 * Stores either absolute or relative address, but unlike the address_t
 * counterpart, this struct only stores row and column positions.
 */
struct IXION_DLLPUBLIC rc_address_t
{
    row_t row;
    col_t column;
    bool  abs_row:1;
    bool  abs_column:1;

    rc_address_t();
    rc_address_t(row_t _row, col_t _column, bool _abs_row=true, bool _abs_column=true);
    rc_address_t(const rc_address_t& r);

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const rc_address_t& addr) const;
    };
};

/**
 * Stores absolute range address.
 */
struct IXION_DLLPUBLIC abs_range_t
{
    enum init_invalid { invalid };

    abs_address_t first;
    abs_address_t last;

    abs_range_t();
    abs_range_t(init_invalid);
    abs_range_t(sheet_t _sheet, row_t _row, col_t _col);

    /**
     * @param _sheet 0-based sheet index.
     * @param _row 0-based row position of the top-left cell of the range.
     * @param _col 0-based column position of the top-left cell of the range.
     * @param _row_span row length of the range. It must be 1 or greater.
     * @param _col_span column length of the range.  It must be 1 or greater.
     */
    abs_range_t(sheet_t _sheet, row_t _row, col_t _col, row_t _row_span, col_t _col_span);
    abs_range_t(const abs_address_t& addr);
    abs_range_t(const abs_address_t& addr, row_t row_span, col_t col_span);

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const abs_range_t& range) const;
    };

    bool valid() const;

    /**
     * Expand the range horizontally to include all columns.  The row range
     * will remain unchanged.
     */
    void set_all_columns();

    /**
     * Expand the range vertically to include all rows.  The column range will
     * remain unchanged.
     */
    void set_all_rows();

    /**
     * @return true if the range is unspecified in the horizontal direction
     *         i.e. all columns are selected, false otherwise.
     */
    bool all_columns() const;

    /**
     * @return true if the range is unspecified in the vertical direction i.e.
     *         all rows are selected, false otherwise.
     */
    bool all_rows() const;

    /**
     * Check whether or not a given address is contained within this range.
     */
    bool contains(const abs_address_t& addr) const;

    /**
     * Reorder range values as needed to ensure the range is valid.
     */
    void reorder();
};

IXION_DLLPUBLIC bool operator==(const abs_range_t& left, const abs_range_t& right);
IXION_DLLPUBLIC bool operator!=(const abs_range_t& left, const abs_range_t& right);
IXION_DLLPUBLIC bool operator<(const abs_range_t& left, const abs_range_t& right);

struct IXION_DLLPUBLIC abs_rc_range_t
{
    enum init_invalid { invalid };

    abs_rc_address_t first;
    abs_rc_address_t last;

    abs_rc_range_t();
    abs_rc_range_t(init_invalid);
    abs_rc_range_t(const abs_rc_range_t& other);
    abs_rc_range_t(const abs_range_t& other);

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const abs_rc_range_t& range) const;
    };

    bool valid() const;

    /**
     * Expand the range horizontally to include all columns.  The row range
     * will remain unchanged.
     */
    void set_all_columns();

    /**
     * Expand the range vertically to include all rows.  The column range will
     * remain unchanged.
     */
    void set_all_rows();

    /**
     * @return true if the range is unspecified in the horizontal direction
     *         i.e. all columns are selected, false otherwise.
     */
    bool all_columns() const;

    /**
     * @return true if the range is unspecified in the vertical direction i.e.
     *         all rows are selected, false otherwise.
     */
    bool all_rows() const;

    /**
     * Check whether or not a given address is contained within this range.
     */
    bool contains(const abs_rc_address_t& addr) const;
};

IXION_DLLPUBLIC bool operator==(const abs_rc_range_t& left, const abs_rc_range_t& right);
IXION_DLLPUBLIC bool operator!=(const abs_rc_range_t& left, const abs_rc_range_t& right);
IXION_DLLPUBLIC bool operator<(const abs_rc_range_t& left, const abs_rc_range_t& right);

/**
 * Stores range whose component may be relative or absolute.
 */
struct IXION_DLLPUBLIC range_t
{
    address_t first;
    address_t last;

    range_t();
    range_t(const address_t& _first, const address_t& _last);
    range_t(const range_t& r);
    range_t(const abs_range_t& r);

    bool valid() const;

    /**
     * Expand the range horizontally to include all columns.  The row range
     * will remain unchanged.
     */
    void set_all_columns();

    /**
     * Expand the range vertically to include all rows.  The column range will
     * remain unchanged.
     */
    void set_all_rows();

    /**
     * @return true if the range is unspecified in the horizontal direction
     *         i.e. all columns are selected, false otherwise.
     */
    bool all_columns() const;

    /**
     * @return true if the range is unspecified in the vertical direction i.e.
     *         all rows are selected, false otherwise.
     */
    bool all_rows() const;

    abs_range_t to_abs(const abs_address_t& origin) const;

    void set_absolute(bool abs);

    struct hash
    {
        IXION_DLLPUBLIC size_t operator() (const range_t& range) const;
    };
};

IXION_DLLPUBLIC bool operator==(const range_t& left, const range_t& right);
IXION_DLLPUBLIC bool operator!=(const range_t& left, const range_t& right);

IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_address_t& addr);
IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_rc_address_t& addr);
IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const address_t& addr);
IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_range_t& range);
IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const abs_rc_range_t& range);
IXION_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const range_t& range);

/**
 * Type that represents a collection of multiple absolute cell addresses.
 */
using abs_address_set_t = std::unordered_set<abs_address_t, abs_address_t::hash>;
using abs_range_set_t = std::unordered_set<abs_range_t, abs_range_t::hash>;
using abs_rc_range_set_t = std::unordered_set<abs_rc_range_t, abs_rc_range_t::hash>;

}

#endif

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