-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.h
178 lines (144 loc) · 8.55 KB
/
common.h
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
#pragma once
#include <iosfwd>
#include <memory>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
// Позиция ячейки. Индексация с нуля.
struct Position {
int row = 0;
int col = 0;
bool operator==(Position rhs) const;
bool operator<(Position rhs) const;
bool IsValid() const;
std::string ToString() const;
static Position FromString(std::string_view str);
static const int MAX_ROWS = 16384;
static const int MAX_COLS = 16384;
static const Position NONE;
};
struct Size {
int rows = 0;
int cols = 0;
bool operator==(Size rhs) const;
};
// Описывает ошибки, которые могут возникнуть при вычислении формулы.
class FormulaError {
public:
enum class Category {
Ref, // ссылка на ячейку с некорректной позицией
Value, // ячейка не может быть трактована как число
Div0, // в результате вычисления возникло деление на ноль
};
FormulaError(Category category){
category_ = category;
}
Category GetCategory() const{
return category_;
}
bool operator==(FormulaError rhs) const{
return category_ == rhs.GetCategory();
}
std::string_view ToString() const{
if (GetCategory() == Category::Div0){
return "#DIV/0!";
} else if (GetCategory() == Category::Ref){
return "#REF!";
} else {
return "#VALUE!";
}
}
private:
Category category_;
};
std::ostream& operator<<(std::ostream& output, FormulaError fe);
// Исключение, выбрасываемое при попытке передать в метод некорректную позицию
class InvalidPositionException : public std::out_of_range {
public:
using std::out_of_range::out_of_range;
};
// Исключение, выбрасываемое при попытке задать синтаксически некорректную
// формулу
class FormulaException : public std::runtime_error {
public:
using std::runtime_error::runtime_error;
};
// Исключение, выбрасываемое при попытке задать формулу, которая приводит к
// циклической зависимости между ячейками
class CircularDependencyException : public std::runtime_error {
public:
using std::runtime_error::runtime_error;
};
class CellInterface {
public:
// Либо текст ячейки, либо значение формулы, либо сообщение об ошибке из
// формулы
using Value = std::variant<std::string, double, FormulaError>;
virtual ~CellInterface() = default;
// Задаёт содержимое ячейки. Если текст начинается со знака "=", то он
// интерпретируется как формула. Уточнения по записи формулы:
// * Если текст содержит только символ "=" и больше ничего, то он не считается
// формулой
// * Если текст начинается с символа "'" (апостроф), то при выводе значения
// ячейки методом GetValue() он опускается. Можно использовать, если нужно
// начать текст со знака "=", но чтобы он не интерпретировался как формула.
virtual void Set(std::string text) = 0;
// Возвращает видимое значение ячейки.
// В случае текстовой ячейки это её текст (без экранирующих символов). В
// случае формулы - числовое значение формулы или сообщение об ошибке.
virtual Value GetValue() const = 0;
// Возвращает внутренний текст ячейки, как если бы мы начали её
// редактирование. В случае текстовой ячейки это её текст (возможно,
// содержащий экранирующие символы). В случае формулы - её выражение.
virtual std::string GetText() const = 0;
// Возвращает список ячеек, которые непосредственно задействованы в данной
// формуле. Список отсортирован по возрастанию и не содержит повторяющихся
// ячеек. В случае текстовой ячейки список пуст.
virtual std::vector<Position> GetReferencedCells() const = 0;
virtual std::vector<Position> GetDependentCells() const = 0;
virtual void AddDependentCell(Position pos) = 0;
virtual void ClearCache_() = 0;
};
inline constexpr char FORMULA_SIGN = '=';
inline constexpr char ESCAPE_SIGN = '\'';
// Интерфейс таблицы
class SheetInterface {
public:
virtual ~SheetInterface() = default;
// Задаёт содержимое ячейки. Если текст начинается со знака "=", то он
// интерпретируется как формула. Если задаётся синтаксически некорректная
// формула, то бросается исключение FormulaException и значение ячейки не
// изменяется. Если задаётся формула, которая приводит к циклической
// зависимости (в частности, если формула использует текущую ячейку), то
// бросается исключение CircularDependencyException и значение ячейки не
// изменяется.
// Уточнения по записи формулы:
// * Если текст содержит только символ "=" и больше ничего, то он не считается
// формулой
// * Если текст начинается с символа "'" (апостроф), то при выводе значения
// ячейки методом GetValue() он опускается. Можно использовать, если нужно
// начать текст со знака "=", но чтобы он не интерпретировался как формула.
virtual void SetCell(Position pos, std::string text) = 0;
// Возвращает значение ячейки.
// Если ячейка пуста, может вернуть nullptr.
virtual const CellInterface* GetCell(Position pos) const = 0;
virtual CellInterface* GetCell(Position pos) = 0;
// Очищает ячейку.
// Последующий вызов GetCell() для этой ячейки вернёт либо nullptr, либо
// объект с пустым текстом.
virtual void ClearCell(Position pos) = 0;
// Вычисляет размер области, которая участвует в печати.
// Определяется как ограничивающий прямоугольник всех ячеек с непустым
// текстом.
virtual Size GetPrintableSize() const = 0;
// Выводит всю таблицу в переданный поток. Столбцы разделяются знаком
// табуляции. После каждой строки выводится символ перевода строки. Для
// преобразования ячеек в строку используются методы GetValue() или GetText()
// соответственно. Пустая ячейка представляется пустой строкой в любом случае.
virtual void PrintValues(std::ostream& output) const = 0;
virtual void PrintTexts(std::ostream& output) const = 0;
};
// Создаёт готовую к работе пустую таблицу.
std::unique_ptr<SheetInterface> CreateSheet();