Rename spdy::Http2HeaderBlock into quiche::HttpHeaderBlock. Http2HeaderBlock is used in HTTP/3 code too, thus this naming makes more sense. PiperOrigin-RevId: 568272632
diff --git a/build/source_list.bzl b/build/source_list.bzl index 4174621..bdb0b9e 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -11,6 +11,8 @@ quiche_core_hdrs = [ "common/btree_scheduler.h", "common/capsule.h", + "common/http/http_header_block.h", + "common/http/http_header_storage.h", "common/masque/connect_udp_datagram_payload.h", "common/platform/api/quiche_bug_tracker.h", "common/platform/api/quiche_client_stats.h", @@ -47,6 +49,7 @@ "common/quiche_mem_slice_storage.h", "common/quiche_protocol_flags_list.h", "common/quiche_random.h", + "common/quiche_simple_arena.h", "common/quiche_status_utils.h", "common/quiche_stream.h", "common/quiche_text_utils.h", @@ -376,7 +379,6 @@ "spdy/core/http2_frame_decoder_adapter.h", "spdy/core/http2_header_block.h", "spdy/core/http2_header_block_hpack_listener.h", - "spdy/core/http2_header_storage.h", "spdy/core/metadata_extension.h", "spdy/core/no_op_headers_handler.h", "spdy/core/recording_headers_handler.h", @@ -390,13 +392,14 @@ "spdy/core/spdy_pinnable_buffer_piece.h", "spdy/core/spdy_prefixed_buffer_reader.h", "spdy/core/spdy_protocol.h", - "spdy/core/spdy_simple_arena.h", "spdy/core/zero_copy_output_buffer.h", "web_transport/complete_buffer_visitor.h", "web_transport/web_transport.h", ] quiche_core_srcs = [ "common/capsule.cc", + "common/http/http_header_block.cc", + "common/http/http_header_storage.cc", "common/masque/connect_udp_datagram_payload.cc", "common/platform/api/quiche_hostname_utils.cc", "common/platform/api/quiche_mutex.cc", @@ -408,6 +411,7 @@ "common/quiche_ip_address_family.cc", "common/quiche_mem_slice_storage.cc", "common/quiche_random.cc", + "common/quiche_simple_arena.cc", "common/quiche_text_utils.cc", "common/simple_buffer_allocator.cc", "common/structured_headers.cc", @@ -671,8 +675,6 @@ "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/http2_header_storage.cc", "spdy/core/metadata_extension.cc", "spdy/core/recording_headers_handler.cc", "spdy/core/spdy_alt_svc_wire_format.cc", @@ -682,7 +684,6 @@ "spdy/core/spdy_pinnable_buffer_piece.cc", "spdy/core/spdy_prefixed_buffer_reader.cc", "spdy/core/spdy_protocol.cc", - "spdy/core/spdy_simple_arena.cc", "web_transport/complete_buffer_visitor.cc", ] quiche_tool_support_hdrs = [ @@ -1050,6 +1051,8 @@ "binary_http/binary_http_message_test.cc", "common/btree_scheduler_test.cc", "common/capsule_test.cc", + "common/http/http_header_block_test.cc", + "common/http/http_header_storage_test.cc", "common/masque/connect_udp_datagram_payload_test.cc", "common/platform/api/quiche_file_utils_test.cc", "common/platform/api/quiche_hostname_utils_test.cc", @@ -1070,6 +1073,7 @@ "common/quiche_linked_hash_map_test.cc", "common/quiche_mem_slice_storage_test.cc", "common/quiche_random_test.cc", + "common/quiche_simple_arena_test.cc", "common/quiche_text_utils_test.cc", "common/simple_buffer_allocator_test.cc", "common/structured_headers_generated_test.cc", @@ -1299,8 +1303,6 @@ "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/http2_header_storage_test.cc", "spdy/core/metadata_extension_test.cc", "spdy/core/spdy_alt_svc_wire_format_test.cc", "spdy/core/spdy_frame_builder_test.cc", @@ -1309,7 +1311,6 @@ "spdy/core/spdy_pinnable_buffer_piece_test.cc", "spdy/core/spdy_prefixed_buffer_reader_test.cc", "spdy/core/spdy_protocol_test.cc", - "spdy/core/spdy_simple_arena_test.cc", ] io_tests_hdrs = [ ]
diff --git a/build/source_list.gni b/build/source_list.gni index 2681949..ce279c6 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -11,6 +11,8 @@ quiche_core_hdrs = [ "src/quiche/common/btree_scheduler.h", "src/quiche/common/capsule.h", + "src/quiche/common/http/http_header_block.h", + "src/quiche/common/http/http_header_storage.h", "src/quiche/common/masque/connect_udp_datagram_payload.h", "src/quiche/common/platform/api/quiche_bug_tracker.h", "src/quiche/common/platform/api/quiche_client_stats.h", @@ -47,6 +49,7 @@ "src/quiche/common/quiche_mem_slice_storage.h", "src/quiche/common/quiche_protocol_flags_list.h", "src/quiche/common/quiche_random.h", + "src/quiche/common/quiche_simple_arena.h", "src/quiche/common/quiche_status_utils.h", "src/quiche/common/quiche_stream.h", "src/quiche/common/quiche_text_utils.h", @@ -376,7 +379,6 @@ "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/http2_header_storage.h", "src/quiche/spdy/core/metadata_extension.h", "src/quiche/spdy/core/no_op_headers_handler.h", "src/quiche/spdy/core/recording_headers_handler.h", @@ -390,13 +392,14 @@ "src/quiche/spdy/core/spdy_pinnable_buffer_piece.h", "src/quiche/spdy/core/spdy_prefixed_buffer_reader.h", "src/quiche/spdy/core/spdy_protocol.h", - "src/quiche/spdy/core/spdy_simple_arena.h", "src/quiche/spdy/core/zero_copy_output_buffer.h", "src/quiche/web_transport/complete_buffer_visitor.h", "src/quiche/web_transport/web_transport.h", ] quiche_core_srcs = [ "src/quiche/common/capsule.cc", + "src/quiche/common/http/http_header_block.cc", + "src/quiche/common/http/http_header_storage.cc", "src/quiche/common/masque/connect_udp_datagram_payload.cc", "src/quiche/common/platform/api/quiche_hostname_utils.cc", "src/quiche/common/platform/api/quiche_mutex.cc", @@ -408,6 +411,7 @@ "src/quiche/common/quiche_ip_address_family.cc", "src/quiche/common/quiche_mem_slice_storage.cc", "src/quiche/common/quiche_random.cc", + "src/quiche/common/quiche_simple_arena.cc", "src/quiche/common/quiche_text_utils.cc", "src/quiche/common/simple_buffer_allocator.cc", "src/quiche/common/structured_headers.cc", @@ -671,8 +675,6 @@ "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/http2_header_storage.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", @@ -682,7 +684,6 @@ "src/quiche/spdy/core/spdy_pinnable_buffer_piece.cc", "src/quiche/spdy/core/spdy_prefixed_buffer_reader.cc", "src/quiche/spdy/core/spdy_protocol.cc", - "src/quiche/spdy/core/spdy_simple_arena.cc", "src/quiche/web_transport/complete_buffer_visitor.cc", ] quiche_tool_support_hdrs = [ @@ -1051,6 +1052,8 @@ "src/quiche/binary_http/binary_http_message_test.cc", "src/quiche/common/btree_scheduler_test.cc", "src/quiche/common/capsule_test.cc", + "src/quiche/common/http/http_header_block_test.cc", + "src/quiche/common/http/http_header_storage_test.cc", "src/quiche/common/masque/connect_udp_datagram_payload_test.cc", "src/quiche/common/platform/api/quiche_file_utils_test.cc", "src/quiche/common/platform/api/quiche_hostname_utils_test.cc", @@ -1071,6 +1074,7 @@ "src/quiche/common/quiche_linked_hash_map_test.cc", "src/quiche/common/quiche_mem_slice_storage_test.cc", "src/quiche/common/quiche_random_test.cc", + "src/quiche/common/quiche_simple_arena_test.cc", "src/quiche/common/quiche_text_utils_test.cc", "src/quiche/common/simple_buffer_allocator_test.cc", "src/quiche/common/structured_headers_generated_test.cc", @@ -1300,8 +1304,6 @@ "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/http2_header_storage_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", @@ -1310,7 +1312,6 @@ "src/quiche/spdy/core/spdy_pinnable_buffer_piece_test.cc", "src/quiche/spdy/core/spdy_prefixed_buffer_reader_test.cc", "src/quiche/spdy/core/spdy_protocol_test.cc", - "src/quiche/spdy/core/spdy_simple_arena_test.cc", ] io_tests_hdrs = [
diff --git a/build/source_list.json b/build/source_list.json index ad9e6d4..5dffaf9 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -10,6 +10,8 @@ "quiche_core_hdrs": [ "quiche/common/btree_scheduler.h", "quiche/common/capsule.h", + "quiche/common/http/http_header_block.h", + "quiche/common/http/http_header_storage.h", "quiche/common/masque/connect_udp_datagram_payload.h", "quiche/common/platform/api/quiche_bug_tracker.h", "quiche/common/platform/api/quiche_client_stats.h", @@ -46,6 +48,7 @@ "quiche/common/quiche_mem_slice_storage.h", "quiche/common/quiche_protocol_flags_list.h", "quiche/common/quiche_random.h", + "quiche/common/quiche_simple_arena.h", "quiche/common/quiche_status_utils.h", "quiche/common/quiche_stream.h", "quiche/common/quiche_text_utils.h", @@ -375,7 +378,6 @@ "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/http2_header_storage.h", "quiche/spdy/core/metadata_extension.h", "quiche/spdy/core/no_op_headers_handler.h", "quiche/spdy/core/recording_headers_handler.h", @@ -389,13 +391,14 @@ "quiche/spdy/core/spdy_pinnable_buffer_piece.h", "quiche/spdy/core/spdy_prefixed_buffer_reader.h", "quiche/spdy/core/spdy_protocol.h", - "quiche/spdy/core/spdy_simple_arena.h", "quiche/spdy/core/zero_copy_output_buffer.h", "quiche/web_transport/complete_buffer_visitor.h", "quiche/web_transport/web_transport.h" ], "quiche_core_srcs": [ "quiche/common/capsule.cc", + "quiche/common/http/http_header_block.cc", + "quiche/common/http/http_header_storage.cc", "quiche/common/masque/connect_udp_datagram_payload.cc", "quiche/common/platform/api/quiche_hostname_utils.cc", "quiche/common/platform/api/quiche_mutex.cc", @@ -407,6 +410,7 @@ "quiche/common/quiche_ip_address_family.cc", "quiche/common/quiche_mem_slice_storage.cc", "quiche/common/quiche_random.cc", + "quiche/common/quiche_simple_arena.cc", "quiche/common/quiche_text_utils.cc", "quiche/common/simple_buffer_allocator.cc", "quiche/common/structured_headers.cc", @@ -670,8 +674,6 @@ "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/http2_header_storage.cc", "quiche/spdy/core/metadata_extension.cc", "quiche/spdy/core/recording_headers_handler.cc", "quiche/spdy/core/spdy_alt_svc_wire_format.cc", @@ -681,7 +683,6 @@ "quiche/spdy/core/spdy_pinnable_buffer_piece.cc", "quiche/spdy/core/spdy_prefixed_buffer_reader.cc", "quiche/spdy/core/spdy_protocol.cc", - "quiche/spdy/core/spdy_simple_arena.cc", "quiche/web_transport/complete_buffer_visitor.cc" ], "quiche_tool_support_hdrs": [ @@ -1050,6 +1051,8 @@ "quiche/binary_http/binary_http_message_test.cc", "quiche/common/btree_scheduler_test.cc", "quiche/common/capsule_test.cc", + "quiche/common/http/http_header_block_test.cc", + "quiche/common/http/http_header_storage_test.cc", "quiche/common/masque/connect_udp_datagram_payload_test.cc", "quiche/common/platform/api/quiche_file_utils_test.cc", "quiche/common/platform/api/quiche_hostname_utils_test.cc", @@ -1070,6 +1073,7 @@ "quiche/common/quiche_linked_hash_map_test.cc", "quiche/common/quiche_mem_slice_storage_test.cc", "quiche/common/quiche_random_test.cc", + "quiche/common/quiche_simple_arena_test.cc", "quiche/common/quiche_text_utils_test.cc", "quiche/common/simple_buffer_allocator_test.cc", "quiche/common/structured_headers_generated_test.cc", @@ -1299,8 +1303,6 @@ "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/http2_header_storage_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", @@ -1308,8 +1310,7 @@ "quiche/spdy/core/spdy_intrusive_list_test.cc", "quiche/spdy/core/spdy_pinnable_buffer_piece_test.cc", "quiche/spdy/core/spdy_prefixed_buffer_reader_test.cc", - "quiche/spdy/core/spdy_protocol_test.cc", - "quiche/spdy/core/spdy_simple_arena_test.cc" + "quiche/spdy/core/spdy_protocol_test.cc" ], "io_tests_hdrs": [
diff --git a/quiche/spdy/core/http2_header_block.cc b/quiche/common/http/http_header_block.cc similarity index 71% rename from quiche/spdy/core/http2_header_block.cc rename to quiche/common/http/http_header_block.cc index 8dddae5..eea94ff 100644 --- a/quiche/spdy/core/http2_header_block.cc +++ b/quiche/common/http/http_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/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include <string.h> @@ -12,7 +12,7 @@ #include "absl/strings/str_cat.h" #include "quiche/common/platform/api/quiche_logging.h" -namespace spdy { +namespace quiche { namespace { // By default, linked_hash_map's internal map allocates space for 100 map @@ -37,23 +37,23 @@ } // namespace -Http2HeaderBlock::HeaderValue::HeaderValue(Http2HeaderStorage* storage, - absl::string_view key, - absl::string_view initial_value) +HttpHeaderBlock::HeaderValue::HeaderValue(HttpHeaderStorage* storage, + absl::string_view key, + absl::string_view initial_value) : storage_(storage), fragments_({initial_value}), pair_({key, {}}), size_(initial_value.size()), separator_size_(SeparatorForKey(key).size()) {} -Http2HeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other) +HttpHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other) : storage_(other.storage_), fragments_(std::move(other.fragments_)), pair_(std::move(other.pair_)), size_(other.size_), separator_size_(other.separator_size_) {} -Http2HeaderBlock::HeaderValue& Http2HeaderBlock::HeaderValue::operator=( +HttpHeaderBlock::HeaderValue& HttpHeaderBlock::HeaderValue::operator=( HeaderValue&& other) { storage_ = other.storage_; fragments_ = std::move(other.fragments_); @@ -63,13 +63,13 @@ return *this; } -void Http2HeaderBlock::HeaderValue::set_storage(Http2HeaderStorage* storage) { +void HttpHeaderBlock::HeaderValue::set_storage(HttpHeaderStorage* storage) { storage_ = storage; } -Http2HeaderBlock::HeaderValue::~HeaderValue() = default; +HttpHeaderBlock::HeaderValue::~HeaderValue() = default; -absl::string_view Http2HeaderBlock::HeaderValue::ConsolidatedValue() const { +absl::string_view HttpHeaderBlock::HeaderValue::ConsolidatedValue() const { if (fragments_.empty()) { return absl::string_view(); } @@ -80,25 +80,25 @@ return fragments_[0]; } -void Http2HeaderBlock::HeaderValue::Append(absl::string_view fragment) { +void HttpHeaderBlock::HeaderValue::Append(absl::string_view fragment) { size_ += (fragment.size() + separator_size_); fragments_.push_back(fragment); } const std::pair<absl::string_view, absl::string_view>& -Http2HeaderBlock::HeaderValue::as_pair() const { +HttpHeaderBlock::HeaderValue::as_pair() const { pair_.second = ConsolidatedValue(); return pair_; } -Http2HeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {} +HttpHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {} -Http2HeaderBlock::iterator::iterator(const iterator& other) = default; +HttpHeaderBlock::iterator::iterator(const iterator& other) = default; -Http2HeaderBlock::iterator::~iterator() = default; +HttpHeaderBlock::iterator::~iterator() = default; -Http2HeaderBlock::ValueProxy::ValueProxy( - Http2HeaderBlock* block, Http2HeaderBlock::MapType::iterator lookup_result, +HttpHeaderBlock::ValueProxy::ValueProxy( + HttpHeaderBlock* block, HttpHeaderBlock::MapType::iterator lookup_result, const absl::string_view key, size_t* spdy_header_block_value_size) : block_(block), lookup_result_(lookup_result), @@ -106,7 +106,7 @@ spdy_header_block_value_size_(spdy_header_block_value_size), valid_(true) {} -Http2HeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other) +HttpHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other) : block_(other.block_), lookup_result_(other.lookup_result_), key_(other.key_), @@ -115,8 +115,8 @@ other.valid_ = false; } -Http2HeaderBlock::ValueProxy& Http2HeaderBlock::ValueProxy::operator=( - Http2HeaderBlock::ValueProxy&& other) { +HttpHeaderBlock::ValueProxy& HttpHeaderBlock::ValueProxy::operator=( + HttpHeaderBlock::ValueProxy&& other) { block_ = other.block_; lookup_result_ = other.lookup_result_; key_ = other.key_; @@ -126,20 +126,20 @@ return *this; } -Http2HeaderBlock::ValueProxy::~ValueProxy() { +HttpHeaderBlock::ValueProxy::~ValueProxy() { // If the ValueProxy is destroyed while lookup_result_ == block_->end(), - // the assignment operator was never used, and the block's Http2HeaderStorage + // the assignment operator was never used, and the block's HttpHeaderStorage // can reclaim the memory used by the key. This makes lookup-only access to - // Http2HeaderBlock through operator[] memory-neutral. + // HttpHeaderBlock through operator[] memory-neutral. if (valid_ && lookup_result_ == block_->map_.end()) { block_->storage_.Rewind(key_); } } -Http2HeaderBlock::ValueProxy& Http2HeaderBlock::ValueProxy::operator=( +HttpHeaderBlock::ValueProxy& HttpHeaderBlock::ValueProxy::operator=( absl::string_view value) { *spdy_header_block_value_size_ += value.size(); - Http2HeaderStorage* storage = &block_->storage_; + HttpHeaderStorage* storage = &block_->storage_; if (lookup_result_ == block_->map_.end()) { QUICHE_DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")"; lookup_result_ = @@ -155,7 +155,7 @@ return *this; } -bool Http2HeaderBlock::ValueProxy::operator==(absl::string_view value) const { +bool HttpHeaderBlock::ValueProxy::operator==(absl::string_view value) const { if (lookup_result_ == block_->map_.end()) { return false; } else { @@ -163,7 +163,7 @@ } } -std::string Http2HeaderBlock::ValueProxy::as_string() const { +std::string HttpHeaderBlock::ValueProxy::as_string() const { if (lookup_result_ == block_->map_.end()) { return ""; } else { @@ -171,9 +171,9 @@ } } -Http2HeaderBlock::Http2HeaderBlock() : map_(kInitialMapBuckets) {} +HttpHeaderBlock::HttpHeaderBlock() : map_(kInitialMapBuckets) {} -Http2HeaderBlock::Http2HeaderBlock(Http2HeaderBlock&& other) +HttpHeaderBlock::HttpHeaderBlock(HttpHeaderBlock&& other) : map_(kInitialMapBuckets) { map_.swap(other.map_); storage_ = std::move(other.storage_); @@ -184,9 +184,9 @@ value_size_ = other.value_size_; } -Http2HeaderBlock::~Http2HeaderBlock() = default; +HttpHeaderBlock::~HttpHeaderBlock() = default; -Http2HeaderBlock& Http2HeaderBlock::operator=(Http2HeaderBlock&& other) { +HttpHeaderBlock& HttpHeaderBlock::operator=(HttpHeaderBlock&& other) { map_.swap(other.map_); storage_ = std::move(other.storage_); for (auto& p : map_) { @@ -197,23 +197,23 @@ return *this; } -Http2HeaderBlock Http2HeaderBlock::Clone() const { - Http2HeaderBlock copy; +HttpHeaderBlock HttpHeaderBlock::Clone() const { + HttpHeaderBlock copy; for (const auto& p : *this) { copy.AppendHeader(p.first, p.second); } return copy; } -bool Http2HeaderBlock::operator==(const Http2HeaderBlock& other) const { +bool HttpHeaderBlock::operator==(const HttpHeaderBlock& other) const { return size() == other.size() && std::equal(begin(), end(), other.begin()); } -bool Http2HeaderBlock::operator!=(const Http2HeaderBlock& other) const { +bool HttpHeaderBlock::operator!=(const HttpHeaderBlock& other) const { return !(operator==(other)); } -std::string Http2HeaderBlock::DebugString() const { +std::string HttpHeaderBlock::DebugString() const { if (empty()) { return "{}"; } @@ -226,7 +226,7 @@ return output; } -void Http2HeaderBlock::erase(absl::string_view key) { +void HttpHeaderBlock::erase(absl::string_view key) { auto iter = map_.find(key); if (iter != map_.end()) { QUICHE_DVLOG(1) << "Erasing header with name: " << key; @@ -236,14 +236,14 @@ } } -void Http2HeaderBlock::clear() { +void HttpHeaderBlock::clear() { key_size_ = 0; value_size_ = 0; map_.clear(); storage_.Clear(); } -void Http2HeaderBlock::insert(const Http2HeaderBlock::value_type& value) { +void HttpHeaderBlock::insert(const HttpHeaderBlock::value_type& value) { // TODO(birenroy): Write new value in place of old value, if it fits. value_size_ += value.second.size(); @@ -261,7 +261,7 @@ } } -Http2HeaderBlock::ValueProxy Http2HeaderBlock::operator[]( +HttpHeaderBlock::ValueProxy HttpHeaderBlock::operator[]( const absl::string_view key) { QUICHE_DVLOG(2) << "Operator[] saw key: " << key; absl::string_view out_key; @@ -279,8 +279,8 @@ return ValueProxy(this, iter, out_key, &value_size_); } -void Http2HeaderBlock::AppendValueOrAddHeader(const absl::string_view key, - const absl::string_view value) { +void HttpHeaderBlock::AppendValueOrAddHeader(const absl::string_view key, + const absl::string_view value) { value_size_ += value.size(); auto iter = map_.find(key); @@ -296,20 +296,20 @@ iter->second.Append(storage_.Write(value)); } -void Http2HeaderBlock::AppendHeader(const absl::string_view key, - const absl::string_view value) { +void HttpHeaderBlock::AppendHeader(const absl::string_view key, + const absl::string_view value) { auto backed_key = WriteKey(key); map_.emplace(std::make_pair( backed_key, HeaderValue(&storage_, backed_key, storage_.Write(value)))); } -absl::string_view Http2HeaderBlock::WriteKey(const absl::string_view key) { +absl::string_view HttpHeaderBlock::WriteKey(const absl::string_view key) { key_size_ += key.size(); return storage_.Write(key); } -size_t Http2HeaderBlock::bytes_allocated() const { +size_t HttpHeaderBlock::bytes_allocated() const { return storage_.bytes_allocated(); } -} // namespace spdy +} // namespace quiche
diff --git a/quiche/common/http/http_header_block.h b/quiche/common/http/http_header_block.h new file mode 100644 index 0000000..bebf481 --- /dev/null +++ b/quiche/common/http/http_header_block.h
@@ -0,0 +1,296 @@ +// 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_COMMON_HTTP_HTTP_HEADER_BLOCK_H_ +#define QUICHE_COMMON_HTTP_HTTP_HEADER_BLOCK_H_ + +#include <stddef.h> + +#include <functional> +#include <list> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/attributes.h" +#include "absl/strings/string_view.h" +#include "quiche/common/http/http_header_storage.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" + +namespace quiche { + +namespace test { +class HttpHeaderBlockPeer; +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 HttpHeaderBlock exists; +// allocated memory is never freed until HttpHeaderBlock'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 HttpHeaderBlock. +class QUICHE_EXPORT HttpHeaderBlock { + private: + // Stores a list of value fragments that can be joined later with a + // key-dependent separator. + class QUICHE_EXPORT HeaderValue { + public: + HeaderValue(HttpHeaderStorage* storage, absl::string_view key, + absl::string_view initial_value); + + // Moves are allowed. + HeaderValue(HeaderValue&& other); + HeaderValue& operator=(HeaderValue&& other); + + void set_storage(HttpHeaderStorage* 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 + // HttpHeaderBlock. + 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 HttpHeaderStorage* 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 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; + + HttpHeaderBlock(); + HttpHeaderBlock(const HttpHeaderBlock& other) = delete; + HttpHeaderBlock(HttpHeaderBlock&& other); + ~HttpHeaderBlock(); + + HttpHeaderBlock& operator=(const HttpHeaderBlock& other) = delete; + HttpHeaderBlock& operator=(HttpHeaderBlock&& other); + HttpHeaderBlock Clone() const; + + bool operator==(const HttpHeaderBlock& other) const; + bool operator!=(const HttpHeaderBlock& 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 HttpHeaderBlock to + // be nearly a drop-in replacement for a linked hash map with string keys and + // values. It reads data from or writes data to a HttpHeaderStorage. + class QUICHE_EXPORT 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 HttpHeaderBlock. + 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 HttpHeaderBlock; + friend class test::ValueProxyPeer; + + ValueProxy(HttpHeaderBlock* block, + HttpHeaderBlock::MapType::iterator lookup_result, + const absl::string_view key, + size_t* spdy_header_block_value_size); + + HttpHeaderBlock* block_; + HttpHeaderBlock::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::HttpHeaderBlockPeer; + + 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_; + HttpHeaderStorage storage_; + + size_t key_size_ = 0; + size_t value_size_ = 0; +}; + +inline bool operator==(absl::string_view lhs, + const HttpHeaderBlock::ValueProxy& rhs) { + return rhs == lhs; +} + +} // namespace quiche + +#endif // QUICHE_COMMON_HTTP_HTTP_HEADER_BLOCK_H_
diff --git a/quiche/spdy/core/http2_header_block_test.cc b/quiche/common/http/http_header_block_test.cc similarity index 76% rename from quiche/spdy/core/http2_header_block_test.cc rename to quiche/common/http/http_header_block_test.cc index ff6cfab..7efc197 100644 --- a/quiche/spdy/core/http2_header_block_test.cc +++ b/quiche/common/http/http_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/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include <memory> #include <utility> @@ -12,12 +12,12 @@ using ::testing::ElementsAre; -namespace spdy { +namespace quiche { namespace test { class ValueProxyPeer { public: - static absl::string_view key(Http2HeaderBlock::ValueProxy* p) { + static absl::string_view key(HttpHeaderBlock::ValueProxy* p) { return p->key_; } }; @@ -27,9 +27,9 @@ return std::make_pair(k, v); } -// This test verifies that Http2HeaderBlock behaves correctly when empty. -TEST(Http2HeaderBlockTest, EmptyBlock) { - Http2HeaderBlock block; +// This test verifies that HttpHeaderBlock behaves correctly when empty. +TEST(HttpHeaderBlockTest, EmptyBlock) { + HttpHeaderBlock block; EXPECT_TRUE(block.empty()); EXPECT_EQ(0u, block.size()); EXPECT_EQ(block.end(), block.find("foo")); @@ -40,8 +40,8 @@ block.erase("bar"); } -TEST(Http2HeaderBlockTest, KeyMemoryReclaimedOnLookup) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, KeyMemoryReclaimedOnLookup) { + HttpHeaderBlock block; absl::string_view copied_key1; { auto proxy1 = block["some key name"]; @@ -63,7 +63,7 @@ block["some other key name"] = "some value"; } // Nothing should blow up when proxy1 is destructed, and we should be able to - // modify and access the Http2HeaderBlock. + // modify and access the HttpHeaderBlock. block["key"] = "value"; EXPECT_EQ("value", block["key"]); EXPECT_EQ("some value", block["some other key name"]); @@ -71,8 +71,8 @@ } // This test verifies that headers can be set in a variety of ways. -TEST(Http2HeaderBlockTest, AddHeaders) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, AddHeaders) { + HttpHeaderBlock block; block["foo"] = std::string(300, 'x'); block["bar"] = "baz"; block["qux"] = "qux1"; @@ -91,29 +91,29 @@ EXPECT_EQ(block.end(), block.find("key")); } -// This test verifies that Http2HeaderBlock can be copied using Clone(). -TEST(Http2HeaderBlockTest, CopyBlocks) { - Http2HeaderBlock block1; +// This test verifies that HttpHeaderBlock can be copied using Clone(). +TEST(HttpHeaderBlockTest, CopyBlocks) { + HttpHeaderBlock block1; block1["foo"] = std::string(300, 'x'); block1["bar"] = "baz"; block1.insert(std::make_pair("qux", "qux1")); - Http2HeaderBlock block2 = block1.Clone(); - Http2HeaderBlock block3(block1.Clone()); + HttpHeaderBlock block2 = block1.Clone(); + HttpHeaderBlock block3(block1.Clone()); EXPECT_EQ(block1, block2); EXPECT_EQ(block1, block3); } -TEST(Http2HeaderBlockTest, Equality) { +TEST(HttpHeaderBlockTest, Equality) { // Test equality and inequality operators. - Http2HeaderBlock block1; + HttpHeaderBlock block1; block1["foo"] = "bar"; - Http2HeaderBlock block2; + HttpHeaderBlock block2; block2["foo"] = "bar"; - Http2HeaderBlock block3; + HttpHeaderBlock block3; block3["baz"] = "qux"; EXPECT_EQ(block1, block2); @@ -123,28 +123,28 @@ EXPECT_NE(block1, block2); } -Http2HeaderBlock ReturnTestHeaderBlock() { - Http2HeaderBlock block; +HttpHeaderBlock ReturnTestHeaderBlock() { + HttpHeaderBlock block; block["foo"] = "bar"; block.insert(std::make_pair("foo2", "baz")); return block; } // Test that certain methods do not crash on moved-from instances. -TEST(Http2HeaderBlockTest, MovedFromIsValid) { - Http2HeaderBlock block1; +TEST(HttpHeaderBlockTest, MovedFromIsValid) { + HttpHeaderBlock block1; block1["foo"] = "bar"; - Http2HeaderBlock block2(std::move(block1)); + HttpHeaderBlock block2(std::move(block1)); EXPECT_THAT(block2, ElementsAre(Pair("foo", "bar"))); block1["baz"] = "qux"; // NOLINT testing post-move behavior - Http2HeaderBlock block3(std::move(block1)); + HttpHeaderBlock block3(std::move(block1)); block1["foo"] = "bar"; // NOLINT testing post-move behavior - Http2HeaderBlock block4(std::move(block1)); + HttpHeaderBlock block4(std::move(block1)); block1.clear(); // NOLINT testing post-move behavior EXPECT_TRUE(block1.empty()); @@ -152,7 +152,7 @@ block1["foo"] = "bar"; EXPECT_THAT(block1, ElementsAre(Pair("foo", "bar"))); - Http2HeaderBlock block5 = ReturnTestHeaderBlock(); + HttpHeaderBlock block5 = ReturnTestHeaderBlock(); block5.AppendValueOrAddHeader("foo", "bar2"); EXPECT_THAT(block5, ElementsAre(Pair("foo", std::string("bar\0bar2", 8)), Pair("foo2", "baz"))); @@ -160,8 +160,8 @@ // This test verifies that headers can be appended to no matter how they were // added originally. -TEST(Http2HeaderBlockTest, AppendHeaders) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, AppendHeaders) { + HttpHeaderBlock block; block["foo"] = "foo"; block.AppendValueOrAddHeader("foo", "bar"); EXPECT_EQ(Pair("foo", std::string("foo\0bar", 7)), *block.find("foo")); @@ -199,8 +199,8 @@ EXPECT_EQ(std::string("yummy\0scrumptious", 17), block["set-cookie"]); } -TEST(Http2HeaderBlockTest, CompareValueToStringPiece) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, CompareValueToStringPiece) { + HttpHeaderBlock block; block["foo"] = "foo"; block.AppendValueOrAddHeader("foo", "bar"); const auto& val = block["foo"]; @@ -220,10 +220,10 @@ EXPECT_FALSE(val2 == absl::string_view("")); } -// This test demonstrates that the Http2HeaderBlock data structure does not +// This test demonstrates that the HttpHeaderBlock data structure does not // place any limitations on the characters present in the header names. -TEST(Http2HeaderBlockTest, UpperCaseNames) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, UpperCaseNames) { + HttpHeaderBlock block; block["Foo"] = "foo"; block.AppendValueOrAddHeader("Foo", "bar"); EXPECT_NE(block.end(), block.find("foo")); @@ -237,7 +237,7 @@ } namespace { -size_t Http2HeaderBlockSize(const Http2HeaderBlock& block) { +size_t HttpHeaderBlockSize(const HttpHeaderBlock& block) { size_t size = 0; for (const auto& pair : block) { size += pair.first.size() + pair.second.size(); @@ -246,38 +246,38 @@ } } // namespace -// Tests Http2HeaderBlock SizeEstimate(). -TEST(Http2HeaderBlockTest, TotalBytesUsed) { - Http2HeaderBlock block; +// Tests HttpHeaderBlock SizeEstimate(). +TEST(HttpHeaderBlockTest, TotalBytesUsed) { + HttpHeaderBlock block; const size_t value_size = 300; block["foo"] = std::string(value_size, 'x'); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); block.insert(std::make_pair("key", std::string(value_size, 'x'))); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); block.AppendValueOrAddHeader("abc", std::string(value_size, 'x')); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); // Replace value for existing key. block["foo"] = std::string(value_size, 'x'); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); block.insert(std::make_pair("key", std::string(value_size, 'x'))); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); // Add value for existing key. block.AppendValueOrAddHeader("abc", std::string(value_size, 'x')); - EXPECT_EQ(block.TotalBytesUsed(), Http2HeaderBlockSize(block)); + EXPECT_EQ(block.TotalBytesUsed(), HttpHeaderBlockSize(block)); - // Copies/clones Http2HeaderBlock. + // Copies/clones HttpHeaderBlock. size_t block_size = block.TotalBytesUsed(); - Http2HeaderBlock block_copy = std::move(block); + HttpHeaderBlock block_copy = std::move(block); EXPECT_EQ(block_size, block_copy.TotalBytesUsed()); // Erases key. block_copy.erase("foo"); - EXPECT_EQ(block_copy.TotalBytesUsed(), Http2HeaderBlockSize(block_copy)); + EXPECT_EQ(block_copy.TotalBytesUsed(), HttpHeaderBlockSize(block_copy)); block_copy.erase("key"); - EXPECT_EQ(block_copy.TotalBytesUsed(), Http2HeaderBlockSize(block_copy)); + EXPECT_EQ(block_copy.TotalBytesUsed(), HttpHeaderBlockSize(block_copy)); block_copy.erase("abc"); - EXPECT_EQ(block_copy.TotalBytesUsed(), Http2HeaderBlockSize(block_copy)); + EXPECT_EQ(block_copy.TotalBytesUsed(), HttpHeaderBlockSize(block_copy)); } // The order of header fields is preserved. Note that all pseudo-header fields @@ -286,8 +286,8 @@ // https://www.rfc-editor.org/rfc/rfc9114.html#name-http-control-data. It is // the responsibility of the higher layer to add header fields in the correct // order. -TEST(Http2HeaderBlockTest, OrderPreserved) { - Http2HeaderBlock block; +TEST(HttpHeaderBlockTest, OrderPreserved) { + HttpHeaderBlock block; block[":method"] = "GET"; block["foo"] = "bar"; block[":path"] = "/"; @@ -297,4 +297,4 @@ } } // namespace test -} // namespace spdy +} // namespace quiche
diff --git a/quiche/spdy/core/http2_header_storage.cc b/quiche/common/http/http_header_storage.cc similarity index 75% rename from quiche/spdy/core/http2_header_storage.cc rename to quiche/common/http/http_header_storage.cc index 653a628..d15c40e 100644 --- a/quiche/spdy/core/http2_header_storage.cc +++ b/quiche/common/http/http_header_storage.cc
@@ -1,28 +1,28 @@ -#include "quiche/spdy/core/http2_header_storage.h" +#include "quiche/common/http/http_header_storage.h" #include <cstring> #include "quiche/common/platform/api/quiche_logging.h" -namespace spdy { +namespace quiche { namespace { -// Http2HeaderStorage allocates blocks of this size by default. +// HttpHeaderStorage allocates blocks of this size by default. const size_t kDefaultStorageBlockSize = 2048; } // namespace -Http2HeaderStorage::Http2HeaderStorage() : arena_(kDefaultStorageBlockSize) {} +HttpHeaderStorage::HttpHeaderStorage() : arena_(kDefaultStorageBlockSize) {} -absl::string_view Http2HeaderStorage::Write(const absl::string_view s) { +absl::string_view HttpHeaderStorage::Write(const absl::string_view s) { return absl::string_view(arena_.Memdup(s.data(), s.size()), s.size()); } -void Http2HeaderStorage::Rewind(const absl::string_view s) { +void HttpHeaderStorage::Rewind(const absl::string_view s) { arena_.Free(const_cast<char*>(s.data()), s.size()); } -absl::string_view Http2HeaderStorage::WriteFragments( +absl::string_view HttpHeaderStorage::WriteFragments( const std::vector<absl::string_view>& fragments, absl::string_view separator) { if (fragments.empty()) { @@ -56,4 +56,4 @@ return dst - original_dst; } -} // namespace spdy +} // namespace quiche
diff --git a/quiche/spdy/core/http2_header_storage.h b/quiche/common/http/http_header_storage.h similarity index 65% rename from quiche/spdy/core/http2_header_storage.h rename to quiche/common/http/http_header_storage.h index bc275b3..036fc1c 100644 --- a/quiche/spdy/core/http2_header_storage.h +++ b/quiche/common/http/http_header_storage.h
@@ -1,30 +1,30 @@ -#ifndef QUICHE_SPDY_CORE_HTTP2_HEADER_STORAGE_H_ -#define QUICHE_SPDY_CORE_HTTP2_HEADER_STORAGE_H_ +#ifndef QUICHE_COMMON_HTTP_HTTP_HEADER_STORAGE_H_ +#define QUICHE_COMMON_HTTP_HTTP_HEADER_STORAGE_H_ #include "absl/strings/string_view.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/spdy_simple_arena.h" +#include "quiche/common/quiche_simple_arena.h" -namespace spdy { +namespace quiche { // This class provides a backing store for absl::string_views. It previously // used custom allocation logic, but now uses an UnsafeArena instead. It has the -// property that absl::string_views that refer to data in Http2HeaderStorage are -// never invalidated until the Http2HeaderStorage is deleted or Clear() is +// property that absl::string_views that refer to data in HttpHeaderStorage are +// never invalidated until the HttpHeaderStorage is deleted or Clear() is // called. // // Write operations always append to the last block. If there is not enough // space to perform the write, a new block is allocated, and any unused space // is wasted. -class QUICHE_EXPORT Http2HeaderStorage { +class QUICHE_EXPORT HttpHeaderStorage { public: - Http2HeaderStorage(); + HttpHeaderStorage(); - Http2HeaderStorage(const Http2HeaderStorage&) = delete; - Http2HeaderStorage& operator=(const Http2HeaderStorage&) = delete; + HttpHeaderStorage(const HttpHeaderStorage&) = delete; + HttpHeaderStorage& operator=(const HttpHeaderStorage&) = delete; - Http2HeaderStorage(Http2HeaderStorage&& other) = default; - Http2HeaderStorage& operator=(Http2HeaderStorage&& other) = default; + HttpHeaderStorage(HttpHeaderStorage&& other) = default; + HttpHeaderStorage& operator=(HttpHeaderStorage&& other) = default; absl::string_view Write(absl::string_view s); @@ -44,7 +44,7 @@ size_t bytes_allocated() const { return arena_.status().bytes_allocated(); } private: - SpdySimpleArena arena_; + QuicheSimpleArena arena_; }; // Writes |fragments| to |dst|, joined by |separator|. |dst| must be large @@ -53,6 +53,6 @@ const std::vector<absl::string_view>& fragments, absl::string_view separator); -} // namespace spdy +} // namespace quiche -#endif // QUICHE_SPDY_CORE_HTTP2_HEADER_STORAGE_H_ +#endif // QUICHE_COMMON_HTTP_HTTP_HEADER_STORAGE_H_
diff --git a/quiche/spdy/core/http2_header_storage_test.cc b/quiche/common/http/http_header_storage_test.cc similarity index 89% rename from quiche/spdy/core/http2_header_storage_test.cc rename to quiche/common/http/http_header_storage_test.cc index bfe9b5e..daf19bd 100644 --- a/quiche/spdy/core/http2_header_storage_test.cc +++ b/quiche/common/http/http_header_storage_test.cc
@@ -1,8 +1,8 @@ -#include "quiche/spdy/core/http2_header_storage.h" +#include "quiche/common/http/http_header_storage.h" #include "quiche/common/platform/api/quiche_test.h" -namespace spdy { +namespace quiche { namespace test { TEST(JoinTest, JoinEmpty) { @@ -32,4 +32,4 @@ } } // namespace test -} // namespace spdy +} // namespace quiche
diff --git a/quiche/spdy/core/spdy_simple_arena.cc b/quiche/common/quiche_simple_arena.cc similarity index 63% rename from quiche/spdy/core/spdy_simple_arena.cc rename to quiche/common/quiche_simple_arena.cc index 0b3b798..b8706a7 100644 --- a/quiche/spdy/core/spdy_simple_arena.cc +++ b/quiche/common/quiche_simple_arena.cc
@@ -2,23 +2,25 @@ // 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_simple_arena.h" +#include "quiche/common/quiche_simple_arena.h" #include <algorithm> #include <cstring> #include "quiche/common/platform/api/quiche_logging.h" -namespace spdy { +namespace quiche { -SpdySimpleArena::SpdySimpleArena(size_t block_size) : block_size_(block_size) {} +QuicheSimpleArena::QuicheSimpleArena(size_t block_size) + : block_size_(block_size) {} -SpdySimpleArena::~SpdySimpleArena() = default; +QuicheSimpleArena::~QuicheSimpleArena() = default; -SpdySimpleArena::SpdySimpleArena(SpdySimpleArena&& other) = default; -SpdySimpleArena& SpdySimpleArena::operator=(SpdySimpleArena&& other) = default; +QuicheSimpleArena::QuicheSimpleArena(QuicheSimpleArena&& other) = default; +QuicheSimpleArena& QuicheSimpleArena::operator=(QuicheSimpleArena&& other) = + default; -char* SpdySimpleArena::Alloc(size_t size) { +char* QuicheSimpleArena::Alloc(size_t size) { Reserve(size); Block& b = blocks_.back(); QUICHE_DCHECK_GE(b.size, b.used + size); @@ -27,7 +29,8 @@ return out; } -char* SpdySimpleArena::Realloc(char* original, size_t oldsize, size_t newsize) { +char* QuicheSimpleArena::Realloc(char* original, size_t oldsize, + size_t newsize) { QUICHE_DCHECK(!blocks_.empty()); Block& last = blocks_.back(); if (last.data.get() <= original && original < last.data.get() + last.size) { @@ -47,13 +50,13 @@ return out; } -char* SpdySimpleArena::Memdup(const char* data, size_t size) { +char* QuicheSimpleArena::Memdup(const char* data, size_t size) { char* out = Alloc(size); memcpy(out, data, size); return out; } -void SpdySimpleArena::Free(char* data, size_t size) { +void QuicheSimpleArena::Free(char* data, size_t size) { if (blocks_.empty()) { return; } @@ -65,12 +68,12 @@ } } -void SpdySimpleArena::Reset() { +void QuicheSimpleArena::Reset() { blocks_.clear(); status_.bytes_allocated_ = 0; } -void SpdySimpleArena::Reserve(size_t additional_space) { +void QuicheSimpleArena::Reserve(size_t additional_space) { if (blocks_.empty()) { AllocBlock(std::max(additional_space, block_size_)); } else { @@ -81,26 +84,27 @@ } } -void SpdySimpleArena::AllocBlock(size_t size) { +void QuicheSimpleArena::AllocBlock(size_t size) { blocks_.push_back(Block(size)); status_.bytes_allocated_ += size; } -SpdySimpleArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {} +QuicheSimpleArena::Block::Block(size_t s) + : data(new char[s]), size(s), used(0) {} -SpdySimpleArena::Block::~Block() = default; +QuicheSimpleArena::Block::~Block() = default; -SpdySimpleArena::Block::Block(SpdySimpleArena::Block&& other) +QuicheSimpleArena::Block::Block(QuicheSimpleArena::Block&& other) : size(other.size), used(other.used) { data = std::move(other.data); } -SpdySimpleArena::Block& SpdySimpleArena::Block::operator=( - SpdySimpleArena::Block&& other) { +QuicheSimpleArena::Block& QuicheSimpleArena::Block::operator=( + QuicheSimpleArena::Block&& other) { size = other.size; used = other.used; data = std::move(other.data); return *this; } -} // namespace spdy +} // namespace quiche
diff --git a/quiche/spdy/core/spdy_simple_arena.h b/quiche/common/quiche_simple_arena.h similarity index 70% rename from quiche/spdy/core/spdy_simple_arena.h rename to quiche/common/quiche_simple_arena.h index dae6879..79e899a 100644 --- a/quiche/spdy/core/spdy_simple_arena.h +++ b/quiche/common/quiche_simple_arena.h
@@ -2,23 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_SPDY_SIMPLE_ARENA_H_ -#define QUICHE_SPDY_CORE_SPDY_SIMPLE_ARENA_H_ +#ifndef QUICHE_COMMON_QUICHE_SIMPLE_ARENA_H_ +#define QUICHE_COMMON_QUICHE_SIMPLE_ARENA_H_ #include <memory> #include <vector> #include "quiche/common/platform/api/quiche_export.h" -namespace spdy { +namespace quiche { // Allocates large blocks of memory, and doles them out in smaller chunks. // Not thread-safe. -class QUICHE_EXPORT SpdySimpleArena { +class QUICHE_EXPORT QuicheSimpleArena { public: class QUICHE_EXPORT Status { private: - friend class SpdySimpleArena; + friend class QuicheSimpleArena; size_t bytes_allocated_; public: @@ -27,17 +27,17 @@ }; // Blocks allocated by this arena will be at least |block_size| bytes. - explicit SpdySimpleArena(size_t block_size); - ~SpdySimpleArena(); + explicit QuicheSimpleArena(size_t block_size); + ~QuicheSimpleArena(); // Copy and assign are not allowed. - SpdySimpleArena() = delete; - SpdySimpleArena(const SpdySimpleArena&) = delete; - SpdySimpleArena& operator=(const SpdySimpleArena&) = delete; + QuicheSimpleArena() = delete; + QuicheSimpleArena(const QuicheSimpleArena&) = delete; + QuicheSimpleArena& operator=(const QuicheSimpleArena&) = delete; // Move is allowed. - SpdySimpleArena(SpdySimpleArena&& other); - SpdySimpleArena& operator=(SpdySimpleArena&& other); + QuicheSimpleArena(QuicheSimpleArena&& other); + QuicheSimpleArena& operator=(QuicheSimpleArena&& other); char* Alloc(size_t size); char* Realloc(char* original, size_t oldsize, size_t newsize); @@ -72,6 +72,6 @@ Status status_; }; -} // namespace spdy +} // namespace quiche -#endif // QUICHE_SPDY_CORE_SPDY_SIMPLE_ARENA_H_ +#endif // QUICHE_COMMON_QUICHE_SIMPLE_ARENA_H_
diff --git a/quiche/spdy/core/spdy_simple_arena_test.cc b/quiche/common/quiche_simple_arena_test.cc similarity index 83% rename from quiche/spdy/core/spdy_simple_arena_test.cc rename to quiche/common/quiche_simple_arena_test.cc index 9708375..91ab2e4 100644 --- a/quiche/spdy/core/spdy_simple_arena_test.cc +++ b/quiche/common/quiche_simple_arena_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_simple_arena.h" +#include "quiche/common/quiche_simple_arena.h" #include <string> #include <vector> @@ -10,19 +10,19 @@ #include "absl/strings/string_view.h" #include "quiche/common/platform/api/quiche_test.h" -namespace spdy { +namespace quiche { namespace { size_t kDefaultBlockSize = 2048; const char kTestString[] = "This is a decently long test string."; -TEST(SpdySimpleArenaTest, NoAllocationOnConstruction) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, NoAllocationOnConstruction) { + QuicheSimpleArena arena(kDefaultBlockSize); EXPECT_EQ(0u, arena.status().bytes_allocated()); } -TEST(SpdySimpleArenaTest, Memdup) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, Memdup) { + QuicheSimpleArena arena(kDefaultBlockSize); const size_t length = strlen(kTestString); char* c = arena.Memdup(kTestString, length); EXPECT_NE(nullptr, c); @@ -30,8 +30,8 @@ EXPECT_EQ(absl::string_view(c, length), kTestString); } -TEST(SpdySimpleArenaTest, MemdupLargeString) { - SpdySimpleArena arena(10 /* block size */); +TEST(QuicheSimpleArenaTest, MemdupLargeString) { + QuicheSimpleArena arena(10 /* block size */); const size_t length = strlen(kTestString); char* c = arena.Memdup(kTestString, length); EXPECT_NE(nullptr, c); @@ -39,8 +39,8 @@ EXPECT_EQ(absl::string_view(c, length), kTestString); } -TEST(SpdySimpleArenaTest, MultipleBlocks) { - SpdySimpleArena arena(40 /* block size */); +TEST(QuicheSimpleArenaTest, MultipleBlocks) { + QuicheSimpleArena arena(40 /* block size */); std::vector<std::string> strings = { "One decently long string.", "Another string.", "A third string that will surely go in a different block."}; @@ -55,8 +55,8 @@ } } -TEST(SpdySimpleArenaTest, UseAfterReset) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, UseAfterReset) { + QuicheSimpleArena arena(kDefaultBlockSize); const size_t length = strlen(kTestString); char* c = arena.Memdup(kTestString, length); arena.Reset(); @@ -66,8 +66,8 @@ EXPECT_EQ(absl::string_view(c, length), kTestString); } -TEST(SpdySimpleArenaTest, Free) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, Free) { + QuicheSimpleArena arena(kDefaultBlockSize); const size_t length = strlen(kTestString); // Freeing memory not owned by the arena should be a no-op, and freeing // before any allocations from the arena should be a no-op. @@ -92,8 +92,8 @@ EXPECT_EQ(c4, c5); } -TEST(SpdySimpleArenaTest, Alloc) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, Alloc) { + QuicheSimpleArena arena(kDefaultBlockSize); const size_t length = strlen(kTestString); char* c1 = arena.Alloc(length); char* c2 = arena.Alloc(2 * length); @@ -105,8 +105,8 @@ EXPECT_EQ(absl::string_view(c4, length), kTestString); } -TEST(SpdySimpleArenaTest, Realloc) { - SpdySimpleArena arena(kDefaultBlockSize); +TEST(QuicheSimpleArenaTest, Realloc) { + QuicheSimpleArena arena(kDefaultBlockSize); const size_t length = strlen(kTestString); // Simple realloc that fits in the block. char* c1 = arena.Memdup(kTestString, length); @@ -138,4 +138,4 @@ } } // namespace -} // namespace spdy +} // namespace quiche
diff --git a/quiche/spdy/core/hpack/hpack_encoder_test.cc b/quiche/spdy/core/hpack/hpack_encoder_test.cc index fe80ffe..b342780 100644 --- a/quiche/spdy/core/hpack/hpack_encoder_test.cc +++ b/quiche/spdy/core/hpack/hpack_encoder_test.cc
@@ -10,8 +10,8 @@ #include "quiche/http2/hpack/huffman/hpack_huffman_encoder.h" #include "quiche/http2/test_tools/http2_random.h" #include "quiche/common/platform/api/quiche_test.h" +#include "quiche/common/quiche_simple_arena.h" #include "quiche/spdy/core/hpack/hpack_static_table.h" -#include "quiche/spdy/core/spdy_simple_arena.h" namespace spdy { @@ -267,7 +267,7 @@ size_t cookie_c_index_; size_t dynamic_table_insertions_; - SpdySimpleArena headers_storage_; + quiche::QuicheSimpleArena headers_storage_; std::vector<std::pair<absl::string_view, absl::string_view>> headers_observed_;
diff --git a/quiche/spdy/core/http2_header_block.h b/quiche/spdy/core/http2_header_block.h index e0da8f5..09e17a9 100644 --- a/quiche/spdy/core/http2_header_block.h +++ b/quiche/spdy/core/http2_header_block.h
@@ -5,287 +5,10 @@ #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/http2_header_storage.h" +#include "quiche/common/http/http_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 Http2HeaderBlock { - private: - // Stores a list of value fragments that can be joined later with a - // key-dependent separator. - class QUICHE_EXPORT HeaderValue { - public: - HeaderValue(Http2HeaderStorage* storage, absl::string_view key, - absl::string_view initial_value); - - // Moves are allowed. - HeaderValue(HeaderValue&& other); - HeaderValue& operator=(HeaderValue&& other); - - void set_storage(Http2HeaderStorage* 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 Http2HeaderStorage* 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 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 Http2HeaderStorage. - class QUICHE_EXPORT 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_; - Http2HeaderStorage storage_; - - size_t key_size_ = 0; - size_t value_size_ = 0; -}; - +using Http2HeaderBlock = ::quiche::HttpHeaderBlock; } // namespace spdy #endif // QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_H_