NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
dict.h
Go to the documentation of this file.
1#ifndef INCLUDED_DICT_
2#define INCLUDED_DICT_
3
4#include <cmath>
5#include <list>
6#include <memory>
7
8#include "logger.h"
9
10namespace newlang {
11
12#ifndef DOXYGEN_SHOULD_SKIP_THIS
13
14 template<typename T, typename... Rest>
15 struct is_all : std::false_type {
16 };
17
18 template<typename T, typename First>
19 struct is_all<T, First> : std::is_same<T, First> {
20 };
21
22 template<typename T, typename First, typename... Rest>
23 struct is_all<T, First, Rest...>
24 : std::integral_constant<bool, std::is_same<T, First>::value && is_all<T, Rest...>::value> {
25 };
26
27 template<typename T, typename... Rest>
28 struct is_any : std::false_type {
29 };
30
31 template<typename T, typename First>
32 struct is_any<T, First> : std::is_same<T, First> {
33 };
34
35 template<typename T, typename First, typename... Rest>
36 struct is_any<T, First, Rest...>
37 : std::integral_constant<bool, std::is_same<T, First>::value || is_any<T, Rest...>::value> {
38 };
39
40 template<class T>
41 typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
42 almost_equal(T x, T y, int ulp) {
43 // the machine epsilon has to be scaled to the magnitude of the values used
44 // and multiplied by the desired precision in ULPs (units in the last place)
45 return std::fabs(x - y) <= std::numeric_limits<T>::epsilon() * std::fabs(x + y) * ulp
46 // unless the result is subnormal
47 || std::fabs(x - y) < std::numeric_limits<T>::min();
48 }
49
50#endif
51
52 template <typename T> class Iter;
53 /*
54 * Аргумент по умолчанию может быть литерал или выражение.
55 * Если аргумент по умолчанию — это выражение, то оно вычисляется только один раз для всей программы при загрузке модуля.
56 * Аргументы по умолчанию парсятся из токенов (создаются или вычисляются) при загрузке модуля, т.е. при создании
57 * аругментов по умолчанию, а сами значения хранятся уже как объекты.
58 *
59 * Аргументы в функции всегда имеют номер, который начинается с единицы в порядке определения в прототипе + некоторые могут иметь наименование.
60 * Даже обязательные аргументы (которые не имеют значения по умолчанию в прототипе финкции), могут быть переданы по имени,
61 * а сами именованные аргументы могут быть указаны в произвольном порядке. Поэтому в реализации Args для обязательных
62 * аргументов так же хранится имя аргумента, но его значение отсутствует.
63 *
64 * Так как позционные аргументы тоже могут передавать как именованные, то контроль и подстчет кол-ва
65 * не именованных аргументов при вызове фунции ничего не определяет.
66 * Следовательно, при вызове функции не именованные аргументы записываются по порядку, а именованные по имени.
67 * Контроль передаваемых аргументов производится на наличие значения у каждого аргумента.
68 * Если при определении функции после всех аргументов стоит многоточие, то разрешается добавлять
69 * новые аргументы по мимо тех, которые уже определены в прототипе функции.
70 */
71
72 template <typename T, typename PTR = std::shared_ptr<T>>
73 class Dict : public std::list<std::pair<std::string, PTR>>
74 {
75 public:
76 typedef PTR Type;
77 typedef std::pair<std::string, Type> PairType;
78 typedef std::list<PairType> ListType;
79
80 friend class Context;
81
82 template <typename I>
83 typename std::enable_if < std::is_integral<I>::value && !std::is_pointer<I>::value, const PairType &>::type
84 inline operator[](I index) {
85 return at(index);
86 }
87
88 template <typename N>
89 typename std::enable_if < std::is_same<N, std::string>::value || std::is_pointer<N>::value, const PairType &>::type
90 inline operator[](N name) {
91 return at(name);
92 }
93
94 inline PairType & push_back(const PairType & p) {
95 ListType::push_back(p);
96 return *at_index(-1);
97 }
98
99 inline PairType & push_back(const Type value, const std::string &name = "") {
100 return push_back(pair(value, name));
101 }
102
103 // inline PairType top() const {
104 // if (ListType::empty()) {
105 // LOG_RUNTIME("Empty Index '%ld' not exists!", index);
106 // }
107 // return *ListType::back();
108 // }
109
110 static inline PairType pair(const Type value, const std::string name = "") {
111 return std::pair<std::string, Type>(name, value);
112 }
113
114 virtual PairType & at(const int64_t index) {
115 return *at_index(index);
116 }
117
118 virtual const PairType & at(const int64_t index) const {
119 return *at_index_const(index);
120 }
121
122 typename ListType::iterator find(const std::string_view name) {
123 auto iter = ListType::begin();
124 while (iter != ListType::end()) {
125 if (iter->first.compare(name.begin()) == 0) {
126 return iter;
127 }
128 iter++;
129 }
130 return ListType::end();
131 }
132
133 // typename ListType::const_iterator find(const std::string_view name) const {
134 // return find(name);
135 // }
136
137 virtual PairType & at(const std::string name) {
138 auto iter = find(name);
139 if (iter != ListType::end()) {
140 return *iter;
141 }
142 LOG_RUNTIME("Property '%s' not found!", name.c_str());
143 }
144
145 virtual const std::string & name(const int64_t index) const {
146 return at_index_const(index)->first;
147 }
148
149 virtual int64_t index(const std::string_view field_name) {
150 typename ListType::iterator found = find(field_name.begin());
151 if (found == ListType::end()) {
152 return -1;
153 }
154 return std::distance(ListType::begin(), found);
155 }
156
157 virtual void clear_() {
158 ListType::clear();
159 }
160
161 virtual int64_t resize(int64_t new_size, const Type fill, const std::string &name = "") {
162 if (new_size >= 0) {
163 // Размер положительный, просто изменить число элементов добавив или удалив последние
164 ListType::resize(new_size, std::pair<std::string, Type>(name, fill));
165 } else {
166 // Если размер отрицательный - добавить или удалить вначале
167 new_size = -new_size;
168 if (static_cast<int64_t> (ListType::size()) > new_size) {
169
170 ListType::erase(ListType::begin(), at_index(ListType::size() - new_size));
171
172 } else if (static_cast<int64_t> (ListType::size()) < new_size) {
173 ListType::insert(ListType::begin(), (ListType::size() - new_size), std::pair<std::string, Type>(name, fill));
174 } else {
175 ListType::clear();
176 }
177 }
178 return ListType::size();
179 }
180
181 typename ListType::iterator at_index(const int64_t index) {
182 if (index < 0) {
183 if (-index <= static_cast<int64_t> (ListType::size())) {
184 int64_t pos = index + 1;
185 typename ListType::iterator iter = ListType::end();
186 while (iter != ListType::begin()) {
187 iter--;
188 if (pos == 0) {
189 return iter;
190 }
191 pos++;
192 }
193 }
194 } else {
195 int64_t pos = 0;
196 typename ListType::iterator iter = ListType::begin();
197 while (iter != ListType::end()) {
198 if (pos == index) {
199 return iter;
200 }
201 pos++;
202 iter++;
203 }
204 }
205 LOG_RUNTIME("Index '%ld' not exists!", index);
206 }
207
208 typename ListType::const_iterator at_index_const(const int64_t index) const {
209 if (index < 0) {
210 if (-index < static_cast<int64_t> (ListType::size())) {
211 int64_t pos = index + 1;
212 typename ListType::const_iterator iter = ListType::end();
213 while (iter != ListType::begin()) {
214 iter--;
215 if (pos == 0) {
216 return iter;
217 }
218 pos++;
219 }
220 }
221 } else {
222 int64_t pos = 0;
223 typename ListType::const_iterator iter = ListType::begin();
224 while (iter != ListType::end()) {
225 if (pos == index) {
226 return iter;
227 }
228 pos++;
229 iter++;
230 }
231 }
232 LOG_RUNTIME("Index '%ld' not exists!", index);
233 }
234
235 virtual void erase(const int64_t index) {
236 ListType::erase(at_index_const(index));
237 }
238
239 virtual void erase(const size_t index_from, const size_t index_to) {
240 if (index_from <= index_to) {
241 if (index_from == index_to) {
242 if (index_from < ListType::size()) {
243 ListType::erase(at_index(index_from));
244 }
245 } else {
246 ListType::erase(at_index(index_from), (index_to < ListType::size() ? at_index(index_to) : ListType::end()));
247 }
248 } else {
249 ASSERT(index_to < index_from);
250 ListType::erase(at_index(index_to), ListType::end());
251 ListType::erase(ListType::begin(), (index_from < ListType::size() ? at_index(index_from) : ListType::end()));
252 }
253 }
254
255 virtual ~Dict() {
256 }
257
258 /*
259 * Конструкторы для создания списка параметров (при подготовке аргументов перед вызовом функции)
260 */
262 }
263
265
266 push_front(arg.second, arg.first);
267 }
268
269 template <class... A> inline Dict(PairType arg, A... rest) : Dict(rest...) {
270 push_front(arg.second, arg.first);
271 }
272 };
273
274} // namespace newlang
275
276
277#endif // INCLUDED_DICT_
std::pair< std::string, Type > PairType
Definition dict.h:77
ListType::iterator find(const std::string_view name)
Definition dict.h:122
virtual int64_t index(const std::string_view field_name)
Definition dict.h:149
Dict(PairType arg)
Definition dict.h:264
virtual PairType & at(const std::string name)
Definition dict.h:137
PairType & push_back(const Type value, const std::string &name="")
Definition dict.h:99
virtual int64_t resize(int64_t new_size, const Type fill, const std::string &name="")
Definition dict.h:161
PairType & push_back(const PairType &p)
Definition dict.h:94
Dict(PairType arg, A... rest)
Definition dict.h:269
virtual ~Dict()
Definition dict.h:255
virtual const std::string & name(const int64_t index) const
Definition dict.h:145
std::enable_if< std::is_integral< I >::value &&!std::is_pointer< I >::value, constPairType & >::type operator[](I index)
Definition dict.h:84
ListType::const_iterator at_index_const(const int64_t index) const
Definition dict.h:208
ListType::iterator at_index(const int64_t index)
Definition dict.h:181
static PairType pair(const Type value, const std::string name="")
Definition dict.h:110
virtual PairType & at(const int64_t index)
Definition dict.h:114
std::list< PairType > ListType
Definition dict.h:78
virtual void clear_()
Definition dict.h:157
virtual const PairType & at(const int64_t index) const
Definition dict.h:118
virtual void erase(const int64_t index)
Definition dict.h:235
virtual void erase(const size_t index_from, const size_t index_to)
Definition dict.h:239
std::enable_if< std::is_same< N, std::string >::value||std::is_pointer< N >::value, constPairType & >::type operator[](N name)
Definition dict.h:90
PTR Type
Definition dict.h:76
#define LOG_RUNTIME(format,...)
Definition logger.h:26
#define ASSERT(condition)
Definition logger.h:60
Definition nlc.h:59