Move Http2HeaderBlock to http2_header_block*. This allows users of SpdyHeaderBlock to update includes and build dependencies at the same time when they are migrated to Http2HeaderBlock. PiperOrigin-RevId: 461041592
diff --git a/build/source_list.bzl b/build/source_list.bzl index e5c653b..9fb34e8 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -371,6 +371,7 @@ "spdy/core/hpack/hpack_output_stream.h", "spdy/core/hpack/hpack_static_table.h", "spdy/core/http2_frame_decoder_adapter.h", + "spdy/core/http2_header_block.h", "spdy/core/http2_header_block_hpack_listener.h", "spdy/core/metadata_extension.h", "spdy/core/no_op_headers_handler.h", @@ -670,12 +671,12 @@ "spdy/core/hpack/hpack_output_stream.cc", "spdy/core/hpack/hpack_static_table.cc", "spdy/core/http2_frame_decoder_adapter.cc", + "spdy/core/http2_header_block.cc", "spdy/core/metadata_extension.cc", "spdy/core/recording_headers_handler.cc", "spdy/core/spdy_alt_svc_wire_format.cc", "spdy/core/spdy_frame_builder.cc", "spdy/core/spdy_framer.cc", - "spdy/core/spdy_header_block.cc", "spdy/core/spdy_header_storage.cc", "spdy/core/spdy_no_op_visitor.cc", "spdy/core/spdy_pinnable_buffer_piece.cc", @@ -1266,11 +1267,11 @@ "spdy/core/hpack/hpack_output_stream_test.cc", "spdy/core/hpack/hpack_round_trip_test.cc", "spdy/core/hpack/hpack_static_table_test.cc", + "spdy/core/http2_header_block_test.cc", "spdy/core/metadata_extension_test.cc", "spdy/core/spdy_alt_svc_wire_format_test.cc", "spdy/core/spdy_frame_builder_test.cc", "spdy/core/spdy_framer_test.cc", - "spdy/core/spdy_header_block_test.cc", "spdy/core/spdy_header_storage_test.cc", "spdy/core/spdy_intrusive_list_test.cc", "spdy/core/spdy_pinnable_buffer_piece_test.cc",
diff --git a/build/source_list.gni b/build/source_list.gni index 3deabbd..a89cff2 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -371,6 +371,7 @@ "src/quiche/spdy/core/hpack/hpack_output_stream.h", "src/quiche/spdy/core/hpack/hpack_static_table.h", "src/quiche/spdy/core/http2_frame_decoder_adapter.h", + "src/quiche/spdy/core/http2_header_block.h", "src/quiche/spdy/core/http2_header_block_hpack_listener.h", "src/quiche/spdy/core/metadata_extension.h", "src/quiche/spdy/core/no_op_headers_handler.h", @@ -670,12 +671,12 @@ "src/quiche/spdy/core/hpack/hpack_output_stream.cc", "src/quiche/spdy/core/hpack/hpack_static_table.cc", "src/quiche/spdy/core/http2_frame_decoder_adapter.cc", + "src/quiche/spdy/core/http2_header_block.cc", "src/quiche/spdy/core/metadata_extension.cc", "src/quiche/spdy/core/recording_headers_handler.cc", "src/quiche/spdy/core/spdy_alt_svc_wire_format.cc", "src/quiche/spdy/core/spdy_frame_builder.cc", "src/quiche/spdy/core/spdy_framer.cc", - "src/quiche/spdy/core/spdy_header_block.cc", "src/quiche/spdy/core/spdy_header_storage.cc", "src/quiche/spdy/core/spdy_no_op_visitor.cc", "src/quiche/spdy/core/spdy_pinnable_buffer_piece.cc", @@ -1266,11 +1267,11 @@ "src/quiche/spdy/core/hpack/hpack_output_stream_test.cc", "src/quiche/spdy/core/hpack/hpack_round_trip_test.cc", "src/quiche/spdy/core/hpack/hpack_static_table_test.cc", + "src/quiche/spdy/core/http2_header_block_test.cc", "src/quiche/spdy/core/metadata_extension_test.cc", "src/quiche/spdy/core/spdy_alt_svc_wire_format_test.cc", "src/quiche/spdy/core/spdy_frame_builder_test.cc", "src/quiche/spdy/core/spdy_framer_test.cc", - "src/quiche/spdy/core/spdy_header_block_test.cc", "src/quiche/spdy/core/spdy_header_storage_test.cc", "src/quiche/spdy/core/spdy_intrusive_list_test.cc", "src/quiche/spdy/core/spdy_pinnable_buffer_piece_test.cc",
diff --git a/build/source_list.json b/build/source_list.json index f3ebe33..4d7c2f9 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -370,6 +370,7 @@ "quiche/spdy/core/hpack/hpack_output_stream.h", "quiche/spdy/core/hpack/hpack_static_table.h", "quiche/spdy/core/http2_frame_decoder_adapter.h", + "quiche/spdy/core/http2_header_block.h", "quiche/spdy/core/http2_header_block_hpack_listener.h", "quiche/spdy/core/metadata_extension.h", "quiche/spdy/core/no_op_headers_handler.h", @@ -669,12 +670,12 @@ "quiche/spdy/core/hpack/hpack_output_stream.cc", "quiche/spdy/core/hpack/hpack_static_table.cc", "quiche/spdy/core/http2_frame_decoder_adapter.cc", + "quiche/spdy/core/http2_header_block.cc", "quiche/spdy/core/metadata_extension.cc", "quiche/spdy/core/recording_headers_handler.cc", "quiche/spdy/core/spdy_alt_svc_wire_format.cc", "quiche/spdy/core/spdy_frame_builder.cc", "quiche/spdy/core/spdy_framer.cc", - "quiche/spdy/core/spdy_header_block.cc", "quiche/spdy/core/spdy_header_storage.cc", "quiche/spdy/core/spdy_no_op_visitor.cc", "quiche/spdy/core/spdy_pinnable_buffer_piece.cc", @@ -1265,11 +1266,11 @@ "quiche/spdy/core/hpack/hpack_output_stream_test.cc", "quiche/spdy/core/hpack/hpack_round_trip_test.cc", "quiche/spdy/core/hpack/hpack_static_table_test.cc", + "quiche/spdy/core/http2_header_block_test.cc", "quiche/spdy/core/metadata_extension_test.cc", "quiche/spdy/core/spdy_alt_svc_wire_format_test.cc", "quiche/spdy/core/spdy_frame_builder_test.cc", "quiche/spdy/core/spdy_framer_test.cc", - "quiche/spdy/core/spdy_header_block_test.cc", "quiche/spdy/core/spdy_header_storage_test.cc", "quiche/spdy/core/spdy_intrusive_list_test.cc", "quiche/spdy/core/spdy_pinnable_buffer_piece_test.cc",
diff --git a/quiche/spdy/core/spdy_header_block.cc b/quiche/spdy/core/http2_header_block.cc similarity index 99% rename from quiche/spdy/core/spdy_header_block.cc rename to quiche/spdy/core/http2_header_block.cc index fe11260..5004ba9 100644 --- a/quiche/spdy/core/spdy_header_block.cc +++ b/quiche/spdy/core/http2_header_block.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_header_block.h" +#include "quiche/spdy/core/http2_header_block.h" #include <string.h>
diff --git a/quiche/spdy/core/http2_header_block.h b/quiche/spdy/core/http2_header_block.h new file mode 100644 index 0000000..62e4d1d --- /dev/null +++ b/quiche/spdy/core/http2_header_block.h
@@ -0,0 +1,291 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_H_ +#define QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_H_ + +#include <stddef.h> + +#include <functional> +#include <list> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/attributes.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/quiche_linked_hash_map.h" +#include "quiche/common/quiche_text_utils.h" +#include "quiche/spdy/core/spdy_header_storage.h" + +namespace spdy { + +namespace test { +class Http2HeaderBlockPeer; +class ValueProxyPeer; +} // namespace test + +#ifndef SPDY_HEADER_DEBUG +#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) +#define SPDY_HEADER_DEBUG 1 +#else // !defined(NDEBUG) || defined(ADDRESS_SANITIZER) +#define SPDY_HEADER_DEBUG 0 +#endif // !defined(NDEBUG) || defined(ADDRESS_SANITIZER) +#endif // SPDY_HEADER_DEBUG + +// This class provides a key-value map that can be used to store SPDY header +// names and values. This data structure preserves insertion order. +// +// Under the hood, this data structure uses large, contiguous blocks of memory +// to store names and values. Lookups may be performed with absl::string_view +// keys, and values are returned as absl::string_views (via ValueProxy, below). +// Value absl::string_views are valid as long as the Http2HeaderBlock exists; +// allocated memory is never freed until Http2HeaderBlock's destruction. +// +// This implementation does not make much of an effort to minimize wasted space. +// It's expected that keys are rarely deleted from a Http2HeaderBlock. +class QUICHE_EXPORT_PRIVATE Http2HeaderBlock { + private: + // Stores a list of value fragments that can be joined later with a + // key-dependent separator. + class QUICHE_EXPORT_PRIVATE HeaderValue { + public: + HeaderValue(SpdyHeaderStorage* storage, absl::string_view key, + absl::string_view initial_value); + + // Moves are allowed. + HeaderValue(HeaderValue&& other); + HeaderValue& operator=(HeaderValue&& other); + + void set_storage(SpdyHeaderStorage* storage); + + // Copies are not. + HeaderValue(const HeaderValue& other) = delete; + HeaderValue& operator=(const HeaderValue& other) = delete; + + ~HeaderValue(); + + // Consumes at most |fragment.size()| bytes of memory. + void Append(absl::string_view fragment); + + absl::string_view value() const { return as_pair().second; } + const std::pair<absl::string_view, absl::string_view>& as_pair() const; + + // Size estimate including separators. Used when keys are erased from + // Http2HeaderBlock. + size_t SizeEstimate() const { return size_; } + + private: + // May allocate a large contiguous region of memory to hold the concatenated + // fragments and separators. + absl::string_view ConsolidatedValue() const; + + mutable SpdyHeaderStorage* storage_; + mutable std::vector<absl::string_view> fragments_; + // The first element is the key; the second is the consolidated value. + mutable std::pair<absl::string_view, absl::string_view> pair_; + size_t size_ = 0; + size_t separator_size_ = 0; + }; + + typedef quiche::QuicheLinkedHashMap<absl::string_view, HeaderValue, + quiche::StringPieceCaseHash, + quiche::StringPieceCaseEqual> + MapType; + + public: + typedef std::pair<absl::string_view, absl::string_view> value_type; + + // Provides iteration over a sequence of std::pair<absl::string_view, + // absl::string_view>, even though the underlying MapType::value_type is + // different. Dereferencing the iterator will result in memory allocation for + // multi-value headers. + class QUICHE_EXPORT_PRIVATE iterator { + public: + // The following type definitions fulfill the requirements for iterator + // implementations. + typedef std::pair<absl::string_view, absl::string_view> value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef MapType::iterator::difference_type difference_type; + + // In practice, this iterator only offers access to const value_type. + typedef const value_type& const_reference; + typedef const value_type* const_pointer; + + explicit iterator(MapType::const_iterator it); + iterator(const iterator& other); + ~iterator(); + + // This will result in memory allocation if the value consists of multiple + // fragments. + const_reference operator*() const { +#if SPDY_HEADER_DEBUG + QUICHE_CHECK(!dereference_forbidden_); +#endif // SPDY_HEADER_DEBUG + return it_->second.as_pair(); + } + + const_pointer operator->() const { return &(this->operator*()); } + bool operator==(const iterator& it) const { return it_ == it.it_; } + bool operator!=(const iterator& it) const { return !(*this == it); } + + iterator& operator++() { + it_++; + return *this; + } + + iterator operator++(int) { + auto ret = *this; + this->operator++(); + return ret; + } + +#if SPDY_HEADER_DEBUG + void forbid_dereference() { dereference_forbidden_ = true; } +#endif // SPDY_HEADER_DEBUG + + private: + MapType::const_iterator it_; +#if SPDY_HEADER_DEBUG + bool dereference_forbidden_ = false; +#endif // SPDY_HEADER_DEBUG + }; + typedef iterator const_iterator; + + Http2HeaderBlock(); + Http2HeaderBlock(const Http2HeaderBlock& other) = delete; + Http2HeaderBlock(Http2HeaderBlock&& other); + ~Http2HeaderBlock(); + + Http2HeaderBlock& operator=(const Http2HeaderBlock& other) = delete; + Http2HeaderBlock& operator=(Http2HeaderBlock&& other); + Http2HeaderBlock Clone() const; + + bool operator==(const Http2HeaderBlock& other) const; + bool operator!=(const Http2HeaderBlock& other) const; + + // Provides a human readable multi-line representation of the stored header + // keys and values. + std::string DebugString() const; + + iterator begin() { return wrap_iterator(map_.begin()); } + iterator end() { return wrap_iterator(map_.end()); } + const_iterator begin() const { return wrap_const_iterator(map_.begin()); } + const_iterator end() const { return wrap_const_iterator(map_.end()); } + bool empty() const { return map_.empty(); } + size_t size() const { return map_.size(); } + iterator find(absl::string_view key) { return wrap_iterator(map_.find(key)); } + const_iterator find(absl::string_view key) const { + return wrap_const_iterator(map_.find(key)); + } + bool contains(absl::string_view key) const { return find(key) != end(); } + void erase(absl::string_view key); + + // Clears both our MapType member and the memory used to hold headers. + void clear(); + + // The next few methods copy data into our backing storage. + + // If key already exists in the block, replaces the value of that key. Else + // adds a new header to the end of the block. + void insert(const value_type& value); + + // If a header with the key is already present, then append the value to the + // existing header value, NUL ("\0") separated unless the key is cookie, in + // which case the separator is "; ". + // If there is no such key, a new header with the key and value is added. + void AppendValueOrAddHeader(const absl::string_view key, + const absl::string_view value); + + // This object provides automatic conversions that allow Http2HeaderBlock to + // be nearly a drop-in replacement for + // SpdyLinkedHashMap<std::string, std::string>. + // It reads data from or writes data to a SpdyHeaderStorage. + class QUICHE_EXPORT_PRIVATE ValueProxy { + public: + ~ValueProxy(); + + // Moves are allowed. + ValueProxy(ValueProxy&& other); + ValueProxy& operator=(ValueProxy&& other); + + // Copies are not. + ValueProxy(const ValueProxy& other) = delete; + ValueProxy& operator=(const ValueProxy& other) = delete; + + // Assignment modifies the underlying Http2HeaderBlock. + ValueProxy& operator=(absl::string_view value); + + // Provides easy comparison against absl::string_view. + bool operator==(absl::string_view value) const; + + std::string as_string() const; + + private: + friend class Http2HeaderBlock; + friend class test::ValueProxyPeer; + + ValueProxy(Http2HeaderBlock* block, + Http2HeaderBlock::MapType::iterator lookup_result, + const absl::string_view key, + size_t* spdy_header_block_value_size); + + Http2HeaderBlock* block_; + Http2HeaderBlock::MapType::iterator lookup_result_; + absl::string_view key_; + size_t* spdy_header_block_value_size_; + bool valid_; + }; + + // Allows either lookup or mutation of the value associated with a key. + ABSL_MUST_USE_RESULT ValueProxy operator[](const absl::string_view key); + + size_t TotalBytesUsed() const { return key_size_ + value_size_; } + + private: + friend class test::Http2HeaderBlockPeer; + + inline iterator wrap_iterator(MapType::const_iterator inner_iterator) const { +#if SPDY_HEADER_DEBUG + iterator outer_iterator(inner_iterator); + if (inner_iterator == map_.end()) { + outer_iterator.forbid_dereference(); + } + return outer_iterator; +#else // SPDY_HEADER_DEBUG + return iterator(inner_iterator); +#endif // SPDY_HEADER_DEBUG + } + + inline const_iterator wrap_const_iterator( + MapType::const_iterator inner_iterator) const { +#if SPDY_HEADER_DEBUG + const_iterator outer_iterator(inner_iterator); + if (inner_iterator == map_.end()) { + outer_iterator.forbid_dereference(); + } + return outer_iterator; +#else // SPDY_HEADER_DEBUG + return iterator(inner_iterator); +#endif // SPDY_HEADER_DEBUG + } + + void AppendHeader(const absl::string_view key, const absl::string_view value); + absl::string_view WriteKey(const absl::string_view key); + size_t bytes_allocated() const; + + // absl::string_views held by |map_| point to memory owned by |storage_|. + MapType map_; + SpdyHeaderStorage storage_; + + size_t key_size_ = 0; + size_t value_size_ = 0; +}; + +} // namespace spdy + +#endif // QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_H_
diff --git a/quiche/spdy/core/spdy_header_block_test.cc b/quiche/spdy/core/http2_header_block_test.cc similarity index 99% rename from quiche/spdy/core/spdy_header_block_test.cc rename to quiche/spdy/core/http2_header_block_test.cc index 6fc604d..4624d7b 100644 --- a/quiche/spdy/core/spdy_header_block_test.cc +++ b/quiche/spdy/core/http2_header_block_test.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_header_block.h" +#include "quiche/spdy/core/http2_header_block.h" #include <memory> #include <utility>
diff --git a/quiche/spdy/core/spdy_header_block.h b/quiche/spdy/core/spdy_header_block.h index 21bde19..62c4109 100644 --- a/quiche/spdy/core/spdy_header_block.h +++ b/quiche/spdy/core/spdy_header_block.h
@@ -5,287 +5,10 @@ #ifndef QUICHE_SPDY_CORE_SPDY_HEADER_BLOCK_H_ #define QUICHE_SPDY_CORE_SPDY_HEADER_BLOCK_H_ -#include <stddef.h> - -#include <functional> -#include <list> -#include <string> -#include <utility> -#include <vector> - -#include "absl/base/attributes.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/common/quiche_linked_hash_map.h" -#include "quiche/common/quiche_text_utils.h" -#include "quiche/spdy/core/spdy_header_storage.h" +#include "quiche/spdy/core/http2_header_block.h" namespace spdy { -namespace test { -class Http2HeaderBlockPeer; -class ValueProxyPeer; -} // namespace test - -#ifndef SPDY_HEADER_DEBUG -#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) -#define SPDY_HEADER_DEBUG 1 -#else // !defined(NDEBUG) || defined(ADDRESS_SANITIZER) -#define SPDY_HEADER_DEBUG 0 -#endif // !defined(NDEBUG) || defined(ADDRESS_SANITIZER) -#endif // SPDY_HEADER_DEBUG - -// This class provides a key-value map that can be used to store SPDY header -// names and values. This data structure preserves insertion order. -// -// Under the hood, this data structure uses large, contiguous blocks of memory -// to store names and values. Lookups may be performed with absl::string_view -// keys, and values are returned as absl::string_views (via ValueProxy, below). -// Value absl::string_views are valid as long as the Http2HeaderBlock exists; -// allocated memory is never freed until Http2HeaderBlock's destruction. -// -// This implementation does not make much of an effort to minimize wasted space. -// It's expected that keys are rarely deleted from a Http2HeaderBlock. -class QUICHE_EXPORT_PRIVATE Http2HeaderBlock { - private: - // Stores a list of value fragments that can be joined later with a - // key-dependent separator. - class QUICHE_EXPORT_PRIVATE HeaderValue { - public: - HeaderValue(SpdyHeaderStorage* storage, absl::string_view key, - absl::string_view initial_value); - - // Moves are allowed. - HeaderValue(HeaderValue&& other); - HeaderValue& operator=(HeaderValue&& other); - - void set_storage(SpdyHeaderStorage* storage); - - // Copies are not. - HeaderValue(const HeaderValue& other) = delete; - HeaderValue& operator=(const HeaderValue& other) = delete; - - ~HeaderValue(); - - // Consumes at most |fragment.size()| bytes of memory. - void Append(absl::string_view fragment); - - absl::string_view value() const { return as_pair().second; } - const std::pair<absl::string_view, absl::string_view>& as_pair() const; - - // Size estimate including separators. Used when keys are erased from - // Http2HeaderBlock. - size_t SizeEstimate() const { return size_; } - - private: - // May allocate a large contiguous region of memory to hold the concatenated - // fragments and separators. - absl::string_view ConsolidatedValue() const; - - mutable SpdyHeaderStorage* storage_; - mutable std::vector<absl::string_view> fragments_; - // The first element is the key; the second is the consolidated value. - mutable std::pair<absl::string_view, absl::string_view> pair_; - size_t size_ = 0; - size_t separator_size_ = 0; - }; - - typedef quiche::QuicheLinkedHashMap<absl::string_view, HeaderValue, - quiche::StringPieceCaseHash, - quiche::StringPieceCaseEqual> - MapType; - - public: - typedef std::pair<absl::string_view, absl::string_view> value_type; - - // Provides iteration over a sequence of std::pair<absl::string_view, - // absl::string_view>, even though the underlying MapType::value_type is - // different. Dereferencing the iterator will result in memory allocation for - // multi-value headers. - class QUICHE_EXPORT_PRIVATE iterator { - public: - // The following type definitions fulfill the requirements for iterator - // implementations. - typedef std::pair<absl::string_view, absl::string_view> value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef MapType::iterator::difference_type difference_type; - - // In practice, this iterator only offers access to const value_type. - typedef const value_type& const_reference; - typedef const value_type* const_pointer; - - explicit iterator(MapType::const_iterator it); - iterator(const iterator& other); - ~iterator(); - - // This will result in memory allocation if the value consists of multiple - // fragments. - const_reference operator*() const { -#if SPDY_HEADER_DEBUG - QUICHE_CHECK(!dereference_forbidden_); -#endif // SPDY_HEADER_DEBUG - return it_->second.as_pair(); - } - - const_pointer operator->() const { return &(this->operator*()); } - bool operator==(const iterator& it) const { return it_ == it.it_; } - bool operator!=(const iterator& it) const { return !(*this == it); } - - iterator& operator++() { - it_++; - return *this; - } - - iterator operator++(int) { - auto ret = *this; - this->operator++(); - return ret; - } - -#if SPDY_HEADER_DEBUG - void forbid_dereference() { dereference_forbidden_ = true; } -#endif // SPDY_HEADER_DEBUG - - private: - MapType::const_iterator it_; -#if SPDY_HEADER_DEBUG - bool dereference_forbidden_ = false; -#endif // SPDY_HEADER_DEBUG - }; - typedef iterator const_iterator; - - Http2HeaderBlock(); - Http2HeaderBlock(const Http2HeaderBlock& other) = delete; - Http2HeaderBlock(Http2HeaderBlock&& other); - ~Http2HeaderBlock(); - - Http2HeaderBlock& operator=(const Http2HeaderBlock& other) = delete; - Http2HeaderBlock& operator=(Http2HeaderBlock&& other); - Http2HeaderBlock Clone() const; - - bool operator==(const Http2HeaderBlock& other) const; - bool operator!=(const Http2HeaderBlock& other) const; - - // Provides a human readable multi-line representation of the stored header - // keys and values. - std::string DebugString() const; - - iterator begin() { return wrap_iterator(map_.begin()); } - iterator end() { return wrap_iterator(map_.end()); } - const_iterator begin() const { return wrap_const_iterator(map_.begin()); } - const_iterator end() const { return wrap_const_iterator(map_.end()); } - bool empty() const { return map_.empty(); } - size_t size() const { return map_.size(); } - iterator find(absl::string_view key) { return wrap_iterator(map_.find(key)); } - const_iterator find(absl::string_view key) const { - return wrap_const_iterator(map_.find(key)); - } - bool contains(absl::string_view key) const { return find(key) != end(); } - void erase(absl::string_view key); - - // Clears both our MapType member and the memory used to hold headers. - void clear(); - - // The next few methods copy data into our backing storage. - - // If key already exists in the block, replaces the value of that key. Else - // adds a new header to the end of the block. - void insert(const value_type& value); - - // If a header with the key is already present, then append the value to the - // existing header value, NUL ("\0") separated unless the key is cookie, in - // which case the separator is "; ". - // If there is no such key, a new header with the key and value is added. - void AppendValueOrAddHeader(const absl::string_view key, - const absl::string_view value); - - // This object provides automatic conversions that allow Http2HeaderBlock to - // be nearly a drop-in replacement for - // SpdyLinkedHashMap<std::string, std::string>. - // It reads data from or writes data to a SpdyHeaderStorage. - class QUICHE_EXPORT_PRIVATE ValueProxy { - public: - ~ValueProxy(); - - // Moves are allowed. - ValueProxy(ValueProxy&& other); - ValueProxy& operator=(ValueProxy&& other); - - // Copies are not. - ValueProxy(const ValueProxy& other) = delete; - ValueProxy& operator=(const ValueProxy& other) = delete; - - // Assignment modifies the underlying Http2HeaderBlock. - ValueProxy& operator=(absl::string_view value); - - // Provides easy comparison against absl::string_view. - bool operator==(absl::string_view value) const; - - std::string as_string() const; - - private: - friend class Http2HeaderBlock; - friend class test::ValueProxyPeer; - - ValueProxy(Http2HeaderBlock* block, - Http2HeaderBlock::MapType::iterator lookup_result, - const absl::string_view key, - size_t* spdy_header_block_value_size); - - Http2HeaderBlock* block_; - Http2HeaderBlock::MapType::iterator lookup_result_; - absl::string_view key_; - size_t* spdy_header_block_value_size_; - bool valid_; - }; - - // Allows either lookup or mutation of the value associated with a key. - ABSL_MUST_USE_RESULT ValueProxy operator[](const absl::string_view key); - - size_t TotalBytesUsed() const { return key_size_ + value_size_; } - - private: - friend class test::Http2HeaderBlockPeer; - - inline iterator wrap_iterator(MapType::const_iterator inner_iterator) const { -#if SPDY_HEADER_DEBUG - iterator outer_iterator(inner_iterator); - if (inner_iterator == map_.end()) { - outer_iterator.forbid_dereference(); - } - return outer_iterator; -#else // SPDY_HEADER_DEBUG - return iterator(inner_iterator); -#endif // SPDY_HEADER_DEBUG - } - - inline const_iterator wrap_const_iterator( - MapType::const_iterator inner_iterator) const { -#if SPDY_HEADER_DEBUG - const_iterator outer_iterator(inner_iterator); - if (inner_iterator == map_.end()) { - outer_iterator.forbid_dereference(); - } - return outer_iterator; -#else // SPDY_HEADER_DEBUG - return iterator(inner_iterator); -#endif // SPDY_HEADER_DEBUG - } - - void AppendHeader(const absl::string_view key, const absl::string_view value); - absl::string_view WriteKey(const absl::string_view key); - size_t bytes_allocated() const; - - // absl::string_views held by |map_| point to memory owned by |storage_|. - MapType map_; - SpdyHeaderStorage storage_; - - size_t key_size_ = 0; - size_t value_size_ = 0; -}; - // TODO(b/156770486): Remove this alias when the rename is complete. using SpdyHeaderBlock = Http2HeaderBlock;