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