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 |
