xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/qpack/value_splitting_header_list.h"
6 
7 #include "absl/strings/string_view.h"
8 #include "quiche/quic/platform/api/quic_logging.h"
9 
10 namespace quic {
11 namespace {
12 
13 const char kCookieKey[] = "cookie";
14 const char kCookieSeparator = ';';
15 const char kOptionalSpaceAfterCookieSeparator = ' ';
16 const char kNonCookieSeparator = '\0';
17 
18 }  // namespace
19 
const_iterator(const spdy::Http2HeaderBlock * header_list,spdy::Http2HeaderBlock::const_iterator header_list_iterator)20 ValueSplittingHeaderList::const_iterator::const_iterator(
21     const spdy::Http2HeaderBlock* header_list,
22     spdy::Http2HeaderBlock::const_iterator header_list_iterator)
23     : header_list_(header_list),
24       header_list_iterator_(header_list_iterator),
25       value_start_(0) {
26   UpdateHeaderField();
27 }
28 
operator ==(const const_iterator & other) const29 bool ValueSplittingHeaderList::const_iterator::operator==(
30     const const_iterator& other) const {
31   return header_list_iterator_ == other.header_list_iterator_ &&
32          value_start_ == other.value_start_;
33 }
34 
operator !=(const const_iterator & other) const35 bool ValueSplittingHeaderList::const_iterator::operator!=(
36     const const_iterator& other) const {
37   return !(*this == other);
38 }
39 
40 const ValueSplittingHeaderList::const_iterator&
operator ++()41 ValueSplittingHeaderList::const_iterator::operator++() {
42   if (value_end_ == absl::string_view::npos) {
43     // This was the last frament within |*header_list_iterator_|,
44     // move on to the next header element of |header_list_|.
45     ++header_list_iterator_;
46     value_start_ = 0;
47   } else {
48     // Find the next fragment within |*header_list_iterator_|.
49     value_start_ = value_end_ + 1;
50   }
51   UpdateHeaderField();
52 
53   return *this;
54 }
55 
56 const ValueSplittingHeaderList::value_type&
operator *() const57 ValueSplittingHeaderList::const_iterator::operator*() const {
58   return header_field_;
59 }
60 const ValueSplittingHeaderList::value_type*
operator ->() const61 ValueSplittingHeaderList::const_iterator::operator->() const {
62   return &header_field_;
63 }
64 
UpdateHeaderField()65 void ValueSplittingHeaderList::const_iterator::UpdateHeaderField() {
66   QUICHE_DCHECK(value_start_ != absl::string_view::npos);
67 
68   if (header_list_iterator_ == header_list_->end()) {
69     return;
70   }
71 
72   const absl::string_view name = header_list_iterator_->first;
73   const absl::string_view original_value = header_list_iterator_->second;
74 
75   if (name == kCookieKey) {
76     value_end_ = original_value.find(kCookieSeparator, value_start_);
77   } else {
78     value_end_ = original_value.find(kNonCookieSeparator, value_start_);
79   }
80 
81   const absl::string_view value =
82       original_value.substr(value_start_, value_end_ - value_start_);
83   header_field_ = std::make_pair(name, value);
84 
85   // Skip character after ';' separator if it is a space.
86   if (name == kCookieKey && value_end_ != absl::string_view::npos &&
87       value_end_ + 1 < original_value.size() &&
88       original_value[value_end_ + 1] == kOptionalSpaceAfterCookieSeparator) {
89     ++value_end_;
90   }
91 }
92 
ValueSplittingHeaderList(const spdy::Http2HeaderBlock * header_list)93 ValueSplittingHeaderList::ValueSplittingHeaderList(
94     const spdy::Http2HeaderBlock* header_list)
95     : header_list_(header_list) {
96   QUICHE_DCHECK(header_list_);
97 }
98 
begin() const99 ValueSplittingHeaderList::const_iterator ValueSplittingHeaderList::begin()
100     const {
101   return const_iterator(header_list_, header_list_->begin());
102 }
103 
end() const104 ValueSplittingHeaderList::const_iterator ValueSplittingHeaderList::end() const {
105   return const_iterator(header_list_, header_list_->end());
106 }
107 
108 }  // namespace quic
109