Line data Source code
1 : // 2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) 3 : // 4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 : // 7 : // Official repository: https://github.com/cppalliance/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_HPP 11 : #define BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_HPP 12 : 13 : #include <boost/core/detail/string_view.hpp> 14 : #include <boost/assert.hpp> 15 : 16 : namespace boost { 17 : namespace http_proto { 18 : 19 : //------------------------------------------------ 20 : // 21 : // iterator 22 : // 23 : //------------------------------------------------ 24 : 25 : class fields_view_base::iterator 26 : { 27 : detail::header const* ph_ = nullptr; 28 : std::size_t i_ = 0; 29 : 30 : friend class fields_base; 31 : friend class fields_view_base; 32 : 33 1632 : iterator( 34 : detail::header const* ph, 35 : std::size_t i) noexcept 36 1632 : : ph_(ph) 37 1632 : , i_(i) 38 : { 39 1632 : } 40 : 41 : public: 42 : using value_type = 43 : fields_view_base::value_type; 44 : using reference = 45 : fields_view_base::reference; 46 : using pointer = reference; 47 : using difference_type = 48 : std::ptrdiff_t; 49 : using iterator_category = 50 : std::bidirectional_iterator_tag; 51 : 52 2 : iterator() = default; 53 : iterator(iterator const&) = default; 54 : iterator& operator=( 55 : iterator const&) = default; 56 : 57 : bool 58 1930 : operator==( 59 : iterator const& other) const noexcept 60 : { 61 : // If this assert goes off, it means you 62 : // are trying to compare iterators from 63 : // different containers, which is undefined! 64 1930 : BOOST_ASSERT(ph_ == other.ph_); 65 : 66 1930 : return i_ == other.i_; 67 : } 68 : 69 : bool 70 1761 : operator!=( 71 : iterator const& other) const noexcept 72 : { 73 1761 : return !(*this == other); 74 : } 75 : 76 : BOOST_HTTP_PROTO_DECL 77 : reference 78 : operator*() const noexcept; 79 : 80 : pointer 81 1801 : operator->() const noexcept 82 : { 83 1801 : return *(*this); 84 : } 85 : 86 : iterator& 87 1162 : operator++() noexcept 88 : { 89 1162 : BOOST_ASSERT(i_ < ph_->count); 90 1162 : ++i_; 91 1162 : return *this; 92 : } 93 : 94 : iterator 95 1 : operator++(int) noexcept 96 : { 97 1 : auto temp = *this; 98 1 : ++(*this); 99 1 : return temp; 100 : } 101 : 102 : iterator& 103 133 : operator--() noexcept 104 : { 105 133 : BOOST_ASSERT(i_ > 0); 106 133 : --i_; 107 133 : return *this; 108 : } 109 : 110 : iterator 111 1 : operator--(int) noexcept 112 : { 113 1 : auto temp = *this; 114 1 : --(*this); 115 1 : return temp; 116 : } 117 : }; 118 : 119 : //------------------------------------------------ 120 : 121 : class fields_view_base::reverse_iterator 122 : { 123 : detail::header const* ph_ = nullptr; 124 : std::size_t i_ = 0; 125 : 126 : friend class fields_base; 127 : friend class fields_view_base; 128 : 129 : reverse_iterator( 130 : detail::header const* ph, 131 : std::size_t i) noexcept 132 : : ph_(ph) 133 : , i_(i) 134 : { 135 : } 136 : 137 : public: 138 : using value_type = 139 : fields_view_base::value_type; 140 : using reference = 141 : fields_view_base::reference; 142 : using pointer = reference; 143 : using difference_type = 144 : std::ptrdiff_t; 145 : using iterator_category = 146 : std::bidirectional_iterator_tag; 147 : 148 2 : reverse_iterator() = default; 149 : reverse_iterator(reverse_iterator const&) = default; 150 : reverse_iterator& operator=( 151 : reverse_iterator const&) = default; 152 : 153 : explicit 154 5 : reverse_iterator( 155 : iterator it) noexcept 156 5 : : ph_(it.ph_) 157 5 : , i_(it.i_) 158 : { 159 5 : } 160 : 161 : bool 162 5 : operator==( 163 : reverse_iterator const& other) const noexcept 164 : { 165 : // If this assert goes off, it means you 166 : // are trying to compare iterators from 167 : // different containers, which is undefined! 168 5 : BOOST_ASSERT(ph_ == other.ph_); 169 : 170 5 : return i_ == other.i_; 171 : } 172 : 173 : bool 174 1 : operator!=( 175 : reverse_iterator const& other) const noexcept 176 : { 177 1 : return !(*this == other); 178 : } 179 : 180 : BOOST_HTTP_PROTO_DECL 181 : reference 182 : operator*() const noexcept; 183 : 184 : pointer 185 24 : operator->() const noexcept 186 : { 187 24 : return *(*this); 188 : } 189 : 190 : reverse_iterator& 191 3 : operator++() noexcept 192 : { 193 3 : BOOST_ASSERT(i_ > 0); 194 3 : --i_; 195 3 : return *this; 196 : } 197 : 198 : reverse_iterator 199 1 : operator++(int) noexcept 200 : { 201 1 : auto temp = *this; 202 1 : ++(*this); 203 1 : return temp; 204 : } 205 : 206 : reverse_iterator& 207 3 : operator--() noexcept 208 : { 209 3 : BOOST_ASSERT(i_ < ph_->count); 210 3 : ++i_; 211 3 : return *this; 212 : } 213 : 214 : reverse_iterator 215 1 : operator--(int) noexcept 216 : { 217 1 : auto temp = *this; 218 1 : --(*this); 219 1 : return temp; 220 : } 221 : }; 222 : 223 : //------------------------------------------------ 224 : // 225 : // subrange 226 : // 227 : //------------------------------------------------ 228 : 229 : class fields_view_base::subrange 230 : { 231 : detail::header const* ph_ = nullptr; 232 : std::size_t i_ = 0; 233 : 234 : friend class fields_view; 235 : friend class fields_view_base; 236 : friend struct detail::header; 237 : 238 66 : subrange( 239 : detail::header const* ph, 240 : std::size_t i) noexcept 241 66 : : ph_(ph) 242 66 : , i_(i) 243 : { 244 66 : } 245 : 246 : public: 247 : class iterator; 248 : //class reverse_iterator; 249 : using const_iterator = iterator; 250 : using value_type = std::string; 251 : using reference = core::string_view; 252 : using const_reference = reference; 253 : using size_type = std::size_t; 254 : using difference_type = std::ptrdiff_t; 255 : 256 : /** Constructor 257 : 258 : Default-constructed subranges are empty. 259 : */ 260 : subrange() noexcept = default; 261 : 262 : subrange(subrange const&) noexcept = default; 263 : subrange& operator=( 264 : subrange const&) noexcept = default; 265 : 266 : iterator begin() const noexcept; 267 : iterator end() const noexcept; 268 : }; 269 : 270 : //------------------------------------------------ 271 : // 272 : // subrange::iterator 273 : // 274 : //------------------------------------------------ 275 : 276 : class fields_view_base::subrange:: 277 : iterator 278 : { 279 : detail::header const* ph_ = nullptr; 280 : std::size_t i_ = 0; 281 : 282 : friend class fields_view_base::subrange; 283 : 284 : BOOST_HTTP_PROTO_DECL 285 : iterator( 286 : detail::header const* ph, 287 : std::size_t i) noexcept; 288 : 289 : // end 290 : BOOST_HTTP_PROTO_DECL 291 : iterator( 292 : detail::header const* ph) noexcept; 293 : 294 : public: 295 : using value_type = std::string; 296 : using reference = core::string_view; 297 : using pointer = void const*; 298 : using difference_type = 299 : std::ptrdiff_t; 300 : using iterator_category = 301 : std::forward_iterator_tag; 302 : 303 : iterator() = default; 304 : iterator(iterator const&) = default; 305 : iterator& operator=( 306 : iterator const&) = default; 307 : 308 : // conversion to regular iterator 309 : operator 310 : fields_view_base:: 311 : iterator() const noexcept 312 : { 313 : return {ph_, i_}; 314 : } 315 : 316 : bool 317 145 : operator==( 318 : iterator const& other) const noexcept 319 : { 320 : // If this assert goes off, it means you 321 : // are trying to compare iterators from 322 : // different containers, which is undefined! 323 145 : BOOST_ASSERT(ph_ == other.ph_); 324 : 325 145 : return i_ == other.i_; 326 : } 327 : 328 : bool 329 145 : operator!=( 330 : iterator const& other) const noexcept 331 : { 332 145 : return !(*this == other); 333 : } 334 : 335 : BOOST_HTTP_PROTO_DECL 336 : reference const 337 : operator*() const noexcept; 338 : 339 : reference const 340 : operator->() const noexcept 341 : { 342 : return *(*this); 343 : } 344 : 345 : BOOST_HTTP_PROTO_DECL 346 : iterator& 347 : operator++() noexcept; 348 : 349 : iterator 350 : operator++(int) noexcept 351 : { 352 : auto temp = *this; 353 : ++(*this); 354 : return temp; 355 : } 356 : }; 357 : 358 : inline 359 : auto 360 66 : fields_view_base:: 361 : subrange:: 362 : begin() const noexcept -> 363 : iterator 364 : { 365 66 : return {ph_, i_}; 366 : } 367 : 368 : inline 369 : auto 370 66 : fields_view_base:: 371 : subrange:: 372 : end() const noexcept -> 373 : iterator 374 : { 375 66 : return {ph_}; 376 : } 377 : 378 : //------------------------------------------------ 379 : 380 : inline 381 : fields_view_base:: 382 : value_type:: 383 : operator 384 : fields_view_base:: 385 : reference() const noexcept 386 : { 387 : return reference{ 388 : id, name, value}; 389 : } 390 : 391 : //------------------------------------------------ 392 : 393 : inline 394 : auto 395 749 : fields_view_base:: 396 : begin() const noexcept -> 397 : iterator 398 : { 399 749 : return iterator(ph_, 0); 400 : } 401 : 402 : inline 403 : auto 404 883 : fields_view_base:: 405 : end() const noexcept -> 406 : iterator 407 : { 408 883 : return iterator(ph_, ph_->count); 409 : } 410 : 411 : inline 412 : auto 413 3 : fields_view_base:: 414 : rbegin() const noexcept -> 415 : reverse_iterator 416 : { 417 3 : return reverse_iterator(end()); 418 : } 419 : 420 : inline 421 : auto 422 2 : fields_view_base:: 423 : rend() const noexcept -> 424 : reverse_iterator 425 : { 426 2 : return reverse_iterator(begin()); 427 : } 428 : 429 : } // http_proto 430 : } // boost 431 : 432 : #endif