Mercurial > minori
comparison dep/toml11/toml/comments.hpp @ 318:3b355fa948c7
config: use TOML instead of INI
unfortunately, INI is not enough, and causes some paths including
semicolons to break with our current storage of the library folders.
so, I decided to switch to TOML which does support real arrays...
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 12 Jun 2024 05:25:41 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
317:b1f4d1867ab1 | 318:3b355fa948c7 |
---|---|
1 // Copyright Toru Niina 2019. | |
2 // Distributed under the MIT License. | |
3 #ifndef TOML11_COMMENTS_HPP | |
4 #define TOML11_COMMENTS_HPP | |
5 #include <initializer_list> | |
6 #include <iterator> | |
7 #include <stdexcept> | |
8 #include <string> | |
9 #include <type_traits> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #ifdef TOML11_PRESERVE_COMMENTS_BY_DEFAULT | |
14 # define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::preserve_comments | |
15 #else | |
16 # define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::discard_comments | |
17 #endif | |
18 | |
19 // This file provides mainly two classes, `preserve_comments` and `discard_comments`. | |
20 // Those two are a container that have the same interface as `std::vector<std::string>` | |
21 // but bahaves in the opposite way. `preserve_comments` is just the same as | |
22 // `std::vector<std::string>` and each `std::string` corresponds to a comment line. | |
23 // Conversely, `discard_comments` discards all the strings and ignores everything | |
24 // assigned in it. `discard_comments` is always empty and you will encounter an | |
25 // error whenever you access to the element. | |
26 namespace toml | |
27 { | |
28 struct discard_comments; // forward decl | |
29 | |
30 // use it in the following way | |
31 // | |
32 // const toml::basic_value<toml::preserve_comments> data = | |
33 // toml::parse<toml::preserve_comments>("example.toml"); | |
34 // | |
35 // the interface is almost the same as std::vector<std::string>. | |
36 struct preserve_comments | |
37 { | |
38 // `container_type` is not provided in discard_comments. | |
39 // do not use this inner-type in a generic code. | |
40 using container_type = std::vector<std::string>; | |
41 | |
42 using size_type = container_type::size_type; | |
43 using difference_type = container_type::difference_type; | |
44 using value_type = container_type::value_type; | |
45 using reference = container_type::reference; | |
46 using const_reference = container_type::const_reference; | |
47 using pointer = container_type::pointer; | |
48 using const_pointer = container_type::const_pointer; | |
49 using iterator = container_type::iterator; | |
50 using const_iterator = container_type::const_iterator; | |
51 using reverse_iterator = container_type::reverse_iterator; | |
52 using const_reverse_iterator = container_type::const_reverse_iterator; | |
53 | |
54 preserve_comments() = default; | |
55 ~preserve_comments() = default; | |
56 preserve_comments(preserve_comments const&) = default; | |
57 preserve_comments(preserve_comments &&) = default; | |
58 preserve_comments& operator=(preserve_comments const&) = default; | |
59 preserve_comments& operator=(preserve_comments &&) = default; | |
60 | |
61 explicit preserve_comments(const std::vector<std::string>& c): comments(c){} | |
62 explicit preserve_comments(std::vector<std::string>&& c) | |
63 : comments(std::move(c)) | |
64 {} | |
65 preserve_comments& operator=(const std::vector<std::string>& c) | |
66 { | |
67 comments = c; | |
68 return *this; | |
69 } | |
70 preserve_comments& operator=(std::vector<std::string>&& c) | |
71 { | |
72 comments = std::move(c); | |
73 return *this; | |
74 } | |
75 | |
76 explicit preserve_comments(const discard_comments&) {} | |
77 | |
78 explicit preserve_comments(size_type n): comments(n) {} | |
79 preserve_comments(size_type n, const std::string& x): comments(n, x) {} | |
80 preserve_comments(std::initializer_list<std::string> x): comments(x) {} | |
81 template<typename InputIterator> | |
82 preserve_comments(InputIterator first, InputIterator last) | |
83 : comments(first, last) | |
84 {} | |
85 | |
86 template<typename InputIterator> | |
87 void assign(InputIterator first, InputIterator last) {comments.assign(first, last);} | |
88 void assign(std::initializer_list<std::string> ini) {comments.assign(ini);} | |
89 void assign(size_type n, const std::string& val) {comments.assign(n, val);} | |
90 | |
91 // Related to the issue #97. | |
92 // | |
93 // It is known that `std::vector::insert` and `std::vector::erase` in | |
94 // the standard library implementation included in GCC 4.8.5 takes | |
95 // `std::vector::iterator` instead of `std::vector::const_iterator`. | |
96 // Because of the const-correctness, we cannot convert a `const_iterator` to | |
97 // an `iterator`. It causes compilation error in GCC 4.8.5. | |
98 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__clang__) | |
99 # if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) <= 40805 | |
100 # define TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION | |
101 # endif | |
102 #endif | |
103 | |
104 #ifdef TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION | |
105 iterator insert(iterator p, const std::string& x) | |
106 { | |
107 return comments.insert(p, x); | |
108 } | |
109 iterator insert(iterator p, std::string&& x) | |
110 { | |
111 return comments.insert(p, std::move(x)); | |
112 } | |
113 void insert(iterator p, size_type n, const std::string& x) | |
114 { | |
115 return comments.insert(p, n, x); | |
116 } | |
117 template<typename InputIterator> | |
118 void insert(iterator p, InputIterator first, InputIterator last) | |
119 { | |
120 return comments.insert(p, first, last); | |
121 } | |
122 void insert(iterator p, std::initializer_list<std::string> ini) | |
123 { | |
124 return comments.insert(p, ini); | |
125 } | |
126 | |
127 template<typename ... Ts> | |
128 iterator emplace(iterator p, Ts&& ... args) | |
129 { | |
130 return comments.emplace(p, std::forward<Ts>(args)...); | |
131 } | |
132 | |
133 iterator erase(iterator pos) {return comments.erase(pos);} | |
134 iterator erase(iterator first, iterator last) | |
135 { | |
136 return comments.erase(first, last); | |
137 } | |
138 #else | |
139 iterator insert(const_iterator p, const std::string& x) | |
140 { | |
141 return comments.insert(p, x); | |
142 } | |
143 iterator insert(const_iterator p, std::string&& x) | |
144 { | |
145 return comments.insert(p, std::move(x)); | |
146 } | |
147 iterator insert(const_iterator p, size_type n, const std::string& x) | |
148 { | |
149 return comments.insert(p, n, x); | |
150 } | |
151 template<typename InputIterator> | |
152 iterator insert(const_iterator p, InputIterator first, InputIterator last) | |
153 { | |
154 return comments.insert(p, first, last); | |
155 } | |
156 iterator insert(const_iterator p, std::initializer_list<std::string> ini) | |
157 { | |
158 return comments.insert(p, ini); | |
159 } | |
160 | |
161 template<typename ... Ts> | |
162 iterator emplace(const_iterator p, Ts&& ... args) | |
163 { | |
164 return comments.emplace(p, std::forward<Ts>(args)...); | |
165 } | |
166 | |
167 iterator erase(const_iterator pos) {return comments.erase(pos);} | |
168 iterator erase(const_iterator first, const_iterator last) | |
169 { | |
170 return comments.erase(first, last); | |
171 } | |
172 #endif | |
173 | |
174 void swap(preserve_comments& other) {comments.swap(other.comments);} | |
175 | |
176 void push_back(const std::string& v) {comments.push_back(v);} | |
177 void push_back(std::string&& v) {comments.push_back(std::move(v));} | |
178 void pop_back() {comments.pop_back();} | |
179 | |
180 template<typename ... Ts> | |
181 void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(args)...);} | |
182 | |
183 void clear() {comments.clear();} | |
184 | |
185 size_type size() const noexcept {return comments.size();} | |
186 size_type max_size() const noexcept {return comments.max_size();} | |
187 size_type capacity() const noexcept {return comments.capacity();} | |
188 bool empty() const noexcept {return comments.empty();} | |
189 | |
190 void reserve(size_type n) {comments.reserve(n);} | |
191 void resize(size_type n) {comments.resize(n);} | |
192 void resize(size_type n, const std::string& c) {comments.resize(n, c);} | |
193 void shrink_to_fit() {comments.shrink_to_fit();} | |
194 | |
195 reference operator[](const size_type n) noexcept {return comments[n];} | |
196 const_reference operator[](const size_type n) const noexcept {return comments[n];} | |
197 reference at(const size_type n) {return comments.at(n);} | |
198 const_reference at(const size_type n) const {return comments.at(n);} | |
199 reference front() noexcept {return comments.front();} | |
200 const_reference front() const noexcept {return comments.front();} | |
201 reference back() noexcept {return comments.back();} | |
202 const_reference back() const noexcept {return comments.back();} | |
203 | |
204 pointer data() noexcept {return comments.data();} | |
205 const_pointer data() const noexcept {return comments.data();} | |
206 | |
207 iterator begin() noexcept {return comments.begin();} | |
208 iterator end() noexcept {return comments.end();} | |
209 const_iterator begin() const noexcept {return comments.begin();} | |
210 const_iterator end() const noexcept {return comments.end();} | |
211 const_iterator cbegin() const noexcept {return comments.cbegin();} | |
212 const_iterator cend() const noexcept {return comments.cend();} | |
213 | |
214 reverse_iterator rbegin() noexcept {return comments.rbegin();} | |
215 reverse_iterator rend() noexcept {return comments.rend();} | |
216 const_reverse_iterator rbegin() const noexcept {return comments.rbegin();} | |
217 const_reverse_iterator rend() const noexcept {return comments.rend();} | |
218 const_reverse_iterator crbegin() const noexcept {return comments.crbegin();} | |
219 const_reverse_iterator crend() const noexcept {return comments.crend();} | |
220 | |
221 friend bool operator==(const preserve_comments&, const preserve_comments&); | |
222 friend bool operator!=(const preserve_comments&, const preserve_comments&); | |
223 friend bool operator< (const preserve_comments&, const preserve_comments&); | |
224 friend bool operator<=(const preserve_comments&, const preserve_comments&); | |
225 friend bool operator> (const preserve_comments&, const preserve_comments&); | |
226 friend bool operator>=(const preserve_comments&, const preserve_comments&); | |
227 | |
228 friend void swap(preserve_comments&, std::vector<std::string>&); | |
229 friend void swap(std::vector<std::string>&, preserve_comments&); | |
230 | |
231 private: | |
232 | |
233 container_type comments; | |
234 }; | |
235 | |
236 inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;} | |
237 inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;} | |
238 inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments < rhs.comments;} | |
239 inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;} | |
240 inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments > rhs.comments;} | |
241 inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;} | |
242 | |
243 inline void swap(preserve_comments& lhs, preserve_comments& rhs) | |
244 { | |
245 lhs.swap(rhs); | |
246 return; | |
247 } | |
248 inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs) | |
249 { | |
250 lhs.comments.swap(rhs); | |
251 return; | |
252 } | |
253 inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs) | |
254 { | |
255 lhs.swap(rhs.comments); | |
256 return; | |
257 } | |
258 | |
259 template<typename charT, typename traits> | |
260 std::basic_ostream<charT, traits>& | |
261 operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com) | |
262 { | |
263 for(const auto& c : com) | |
264 { | |
265 os << '#' << c << '\n'; | |
266 } | |
267 return os; | |
268 } | |
269 | |
270 namespace detail | |
271 { | |
272 | |
273 // To provide the same interface with `preserve_comments`, `discard_comments` | |
274 // should have an iterator. But it does not contain anything, so we need to | |
275 // add an iterator that points nothing. | |
276 // | |
277 // It always points null, so DO NOT unwrap this iterator. It always crashes | |
278 // your program. | |
279 template<typename T, bool is_const> | |
280 struct empty_iterator | |
281 { | |
282 using value_type = T; | |
283 using reference_type = typename std::conditional<is_const, T const&, T&>::type; | |
284 using pointer_type = typename std::conditional<is_const, T const*, T*>::type; | |
285 using difference_type = std::ptrdiff_t; | |
286 using iterator_category = std::random_access_iterator_tag; | |
287 | |
288 empty_iterator() = default; | |
289 ~empty_iterator() = default; | |
290 empty_iterator(empty_iterator const&) = default; | |
291 empty_iterator(empty_iterator &&) = default; | |
292 empty_iterator& operator=(empty_iterator const&) = default; | |
293 empty_iterator& operator=(empty_iterator &&) = default; | |
294 | |
295 // DO NOT call these operators. | |
296 reference_type operator*() const noexcept {std::terminate();} | |
297 pointer_type operator->() const noexcept {return nullptr;} | |
298 reference_type operator[](difference_type) const noexcept {return this->operator*();} | |
299 | |
300 // These operators do nothing. | |
301 empty_iterator& operator++() noexcept {return *this;} | |
302 empty_iterator operator++(int) noexcept {return *this;} | |
303 empty_iterator& operator--() noexcept {return *this;} | |
304 empty_iterator operator--(int) noexcept {return *this;} | |
305 | |
306 empty_iterator& operator+=(difference_type) noexcept {return *this;} | |
307 empty_iterator& operator-=(difference_type) noexcept {return *this;} | |
308 | |
309 empty_iterator operator+(difference_type) const noexcept {return *this;} | |
310 empty_iterator operator-(difference_type) const noexcept {return *this;} | |
311 }; | |
312 | |
313 template<typename T, bool C> | |
314 bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;} | |
315 template<typename T, bool C> | |
316 bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;} | |
317 template<typename T, bool C> | |
318 bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;} | |
319 template<typename T, bool C> | |
320 bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;} | |
321 template<typename T, bool C> | |
322 bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;} | |
323 template<typename T, bool C> | |
324 bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;} | |
325 | |
326 template<typename T, bool C> | |
327 typename empty_iterator<T, C>::difference_type | |
328 operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;} | |
329 | |
330 template<typename T, bool C> | |
331 empty_iterator<T, C> | |
332 operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;} | |
333 template<typename T, bool C> | |
334 empty_iterator<T, C> | |
335 operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::difference_type) noexcept {return lhs;} | |
336 | |
337 } // detail | |
338 | |
339 // The default comment type. It discards all the comments. It requires only one | |
340 // byte to contain, so the memory footprint is smaller than preserve_comments. | |
341 // | |
342 // It just ignores `push_back`, `insert`, `erase`, and any other modifications. | |
343 // IT always returns size() == 0, the iterator taken by `begin()` is always the | |
344 // same as that of `end()`, and accessing through `operator[]` or iterators | |
345 // always causes a segmentation fault. DO NOT access to the element of this. | |
346 // | |
347 // Why this is chose as the default type is because the last version (2.x.y) | |
348 // does not contain any comments in a value. To minimize the impact on the | |
349 // efficiency, this is chosen as a default. | |
350 // | |
351 // To reduce the memory footprint, later we can try empty base optimization (EBO). | |
352 struct discard_comments | |
353 { | |
354 using size_type = std::size_t; | |
355 using difference_type = std::ptrdiff_t; | |
356 using value_type = std::string; | |
357 using reference = std::string&; | |
358 using const_reference = std::string const&; | |
359 using pointer = std::string*; | |
360 using const_pointer = std::string const*; | |
361 using iterator = detail::empty_iterator<std::string, false>; | |
362 using const_iterator = detail::empty_iterator<std::string, true>; | |
363 using reverse_iterator = detail::empty_iterator<std::string, false>; | |
364 using const_reverse_iterator = detail::empty_iterator<std::string, true>; | |
365 | |
366 discard_comments() = default; | |
367 ~discard_comments() = default; | |
368 discard_comments(discard_comments const&) = default; | |
369 discard_comments(discard_comments &&) = default; | |
370 discard_comments& operator=(discard_comments const&) = default; | |
371 discard_comments& operator=(discard_comments &&) = default; | |
372 | |
373 explicit discard_comments(const std::vector<std::string>&) noexcept {} | |
374 explicit discard_comments(std::vector<std::string>&&) noexcept {} | |
375 discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;} | |
376 discard_comments& operator=(std::vector<std::string>&&) noexcept {return *this;} | |
377 | |
378 explicit discard_comments(const preserve_comments&) noexcept {} | |
379 | |
380 explicit discard_comments(size_type) noexcept {} | |
381 discard_comments(size_type, const std::string&) noexcept {} | |
382 discard_comments(std::initializer_list<std::string>) noexcept {} | |
383 template<typename InputIterator> | |
384 discard_comments(InputIterator, InputIterator) noexcept {} | |
385 | |
386 template<typename InputIterator> | |
387 void assign(InputIterator, InputIterator) noexcept {} | |
388 void assign(std::initializer_list<std::string>) noexcept {} | |
389 void assign(size_type, const std::string&) noexcept {} | |
390 | |
391 iterator insert(const_iterator, const std::string&) {return iterator{};} | |
392 iterator insert(const_iterator, std::string&&) {return iterator{};} | |
393 iterator insert(const_iterator, size_type, const std::string&) {return iterator{};} | |
394 template<typename InputIterator> | |
395 iterator insert(const_iterator, InputIterator, InputIterator) {return iterator{};} | |
396 iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};} | |
397 | |
398 template<typename ... Ts> | |
399 iterator emplace(const_iterator, Ts&& ...) {return iterator{};} | |
400 iterator erase(const_iterator) {return iterator{};} | |
401 iterator erase(const_iterator, const_iterator) {return iterator{};} | |
402 | |
403 void swap(discard_comments&) {return;} | |
404 | |
405 void push_back(const std::string&) {return;} | |
406 void push_back(std::string&& ) {return;} | |
407 void pop_back() {return;} | |
408 | |
409 template<typename ... Ts> | |
410 void emplace_back(Ts&& ...) {return;} | |
411 | |
412 void clear() {return;} | |
413 | |
414 size_type size() const noexcept {return 0;} | |
415 size_type max_size() const noexcept {return 0;} | |
416 size_type capacity() const noexcept {return 0;} | |
417 bool empty() const noexcept {return true;} | |
418 | |
419 void reserve(size_type) {return;} | |
420 void resize(size_type) {return;} | |
421 void resize(size_type, const std::string&) {return;} | |
422 void shrink_to_fit() {return;} | |
423 | |
424 // DO NOT access to the element of this container. This container is always | |
425 // empty, so accessing through operator[], front/back, data causes address | |
426 // error. | |
427 | |
428 reference operator[](const size_type) noexcept {never_call("toml::discard_comment::operator[]");} | |
429 const_reference operator[](const size_type) const noexcept {never_call("toml::discard_comment::operator[]");} | |
430 reference at(const size_type) {throw std::out_of_range("toml::discard_comment is always empty.");} | |
431 const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");} | |
432 reference front() noexcept {never_call("toml::discard_comment::front");} | |
433 const_reference front() const noexcept {never_call("toml::discard_comment::front");} | |
434 reference back() noexcept {never_call("toml::discard_comment::back");} | |
435 const_reference back() const noexcept {never_call("toml::discard_comment::back");} | |
436 | |
437 pointer data() noexcept {return nullptr;} | |
438 const_pointer data() const noexcept {return nullptr;} | |
439 | |
440 iterator begin() noexcept {return iterator{};} | |
441 iterator end() noexcept {return iterator{};} | |
442 const_iterator begin() const noexcept {return const_iterator{};} | |
443 const_iterator end() const noexcept {return const_iterator{};} | |
444 const_iterator cbegin() const noexcept {return const_iterator{};} | |
445 const_iterator cend() const noexcept {return const_iterator{};} | |
446 | |
447 reverse_iterator rbegin() noexcept {return iterator{};} | |
448 reverse_iterator rend() noexcept {return iterator{};} | |
449 const_reverse_iterator rbegin() const noexcept {return const_iterator{};} | |
450 const_reverse_iterator rend() const noexcept {return const_iterator{};} | |
451 const_reverse_iterator crbegin() const noexcept {return const_iterator{};} | |
452 const_reverse_iterator crend() const noexcept {return const_iterator{};} | |
453 | |
454 private: | |
455 | |
456 [[noreturn]] static void never_call(const char *const this_function) | |
457 { | |
458 #ifdef __has_builtin | |
459 # if __has_builtin(__builtin_unreachable) | |
460 __builtin_unreachable(); | |
461 # endif | |
462 #endif | |
463 throw std::logic_error{this_function}; | |
464 } | |
465 }; | |
466 | |
467 inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;} | |
468 inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;} | |
469 inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;} | |
470 inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;} | |
471 inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;} | |
472 inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;} | |
473 | |
474 inline void swap(const discard_comments&, const discard_comments&) noexcept {return;} | |
475 | |
476 template<typename charT, typename traits> | |
477 std::basic_ostream<charT, traits>& | |
478 operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&) | |
479 { | |
480 return os; | |
481 } | |
482 | |
483 } // toml11 | |
484 #endif// TOML11_COMMENTS_HPP |