Index: net/spdy/hpack_encoder.cc |
diff --git a/net/spdy/hpack_encoder.cc b/net/spdy/hpack_encoder.cc |
deleted file mode 100644 |
index bc56efefbc883b040054e7f6416f4b24f97899dc..0000000000000000000000000000000000000000 |
--- a/net/spdy/hpack_encoder.cc |
+++ /dev/null |
@@ -1,206 +0,0 @@ |
-// Copyright 2014 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. |
- |
-#include "net/spdy/hpack_encoder.h" |
- |
-#include <algorithm> |
- |
-#include "base/logging.h" |
-#include "net/spdy/hpack_header_table.h" |
-#include "net/spdy/hpack_huffman_table.h" |
-#include "net/spdy/hpack_output_stream.h" |
- |
-namespace net { |
- |
-using base::StringPiece; |
-using std::string; |
- |
-HpackEncoder::HpackEncoder(const HpackHuffmanTable& table) |
- : output_stream_(), |
- allow_huffman_compression_(true), |
- huffman_table_(table), |
- char_counts_(NULL), |
- total_char_counts_(NULL) {} |
- |
-HpackEncoder::~HpackEncoder() {} |
- |
-bool HpackEncoder::EncodeHeaderSet(const std::map<string, string>& header_set, |
- string* output) { |
- // Separate header set into pseudo-headers and regular headers. |
- Representations pseudo_headers; |
- Representations regular_headers; |
- for (std::map<string, string>::const_iterator it = header_set.begin(); |
- it != header_set.end(); ++it) { |
- if (it->first == "cookie") { |
- // Note that there can only be one "cookie" header, because header_set is |
- // a map. |
- CookieToCrumbs(*it, ®ular_headers); |
- } else if (it->first[0] == kPseudoHeaderPrefix) { |
- DecomposeRepresentation(*it, &pseudo_headers); |
- } else { |
- DecomposeRepresentation(*it, ®ular_headers); |
- } |
- } |
- |
- // Encode pseudo-headers. |
- for (Representations::const_iterator it = pseudo_headers.begin(); |
- it != pseudo_headers.end(); ++it) { |
- const HpackEntry* entry = |
- header_table_.GetByNameAndValue(it->first, it->second); |
- if (entry != NULL) { |
- EmitIndex(entry); |
- } else { |
- if (it->first == ":authority") { |
- // :authority is always present and rarely changes, and has moderate |
- // length, therefore it makes a lot of sense to index (insert in the |
- // header table). |
- EmitIndexedLiteral(*it); |
- } else { |
- // Most common pseudo-header fields are represented in the static table, |
- // while uncommon ones are small, so do not index them. |
- EmitNonIndexedLiteral(*it); |
- } |
- } |
- } |
- |
- // Encode regular headers. |
- for (Representations::const_iterator it = regular_headers.begin(); |
- it != regular_headers.end(); ++it) { |
- const HpackEntry* entry = |
- header_table_.GetByNameAndValue(it->first, it->second); |
- if (entry != NULL) { |
- EmitIndex(entry); |
- } else { |
- EmitIndexedLiteral(*it); |
- } |
- } |
- |
- output_stream_.TakeString(output); |
- return true; |
-} |
- |
-bool HpackEncoder::EncodeHeaderSetWithoutCompression( |
- const std::map<string, string>& header_set, |
- string* output) { |
- |
- allow_huffman_compression_ = false; |
- for (std::map<string, string>::const_iterator it = header_set.begin(); |
- it != header_set.end(); ++it) { |
- // Note that cookies are not crumbled in this case. |
- EmitNonIndexedLiteral(*it); |
- } |
- allow_huffman_compression_ = true; |
- output_stream_.TakeString(output); |
- return true; |
-} |
- |
-void HpackEncoder::EmitIndex(const HpackEntry* entry) { |
- output_stream_.AppendPrefix(kIndexedOpcode); |
- output_stream_.AppendUint32(header_table_.IndexOf(entry)); |
-} |
- |
-void HpackEncoder::EmitIndexedLiteral(const Representation& representation) { |
- output_stream_.AppendPrefix(kLiteralIncrementalIndexOpcode); |
- EmitLiteral(representation); |
- header_table_.TryAddEntry(representation.first, representation.second); |
-} |
- |
-void HpackEncoder::EmitNonIndexedLiteral( |
- const Representation& representation) { |
- output_stream_.AppendPrefix(kLiteralNoIndexOpcode); |
- output_stream_.AppendUint32(0); |
- EmitString(representation.first); |
- EmitString(representation.second); |
-} |
- |
-void HpackEncoder::EmitLiteral(const Representation& representation) { |
- const HpackEntry* name_entry = header_table_.GetByName(representation.first); |
- if (name_entry != NULL) { |
- output_stream_.AppendUint32(header_table_.IndexOf(name_entry)); |
- } else { |
- output_stream_.AppendUint32(0); |
- EmitString(representation.first); |
- } |
- EmitString(representation.second); |
-} |
- |
-void HpackEncoder::EmitString(StringPiece str) { |
- size_t encoded_size = (!allow_huffman_compression_ ? str.size() |
- : huffman_table_.EncodedSize(str)); |
- if (encoded_size < str.size()) { |
- output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded); |
- output_stream_.AppendUint32(encoded_size); |
- huffman_table_.EncodeString(str, &output_stream_); |
- } else { |
- output_stream_.AppendPrefix(kStringLiteralIdentityEncoded); |
- output_stream_.AppendUint32(str.size()); |
- output_stream_.AppendBytes(str); |
- } |
- UpdateCharacterCounts(str); |
-} |
- |
-void HpackEncoder::SetCharCountsStorage(std::vector<size_t>* char_counts, |
- size_t* total_char_counts) { |
- CHECK_LE(256u, char_counts->size()); |
- char_counts_ = char_counts; |
- total_char_counts_ = total_char_counts; |
-} |
- |
-void HpackEncoder::UpdateCharacterCounts(base::StringPiece str) { |
- if (char_counts_ == NULL || total_char_counts_ == NULL) { |
- return; |
- } |
- for (StringPiece::const_iterator it = str.begin(); it != str.end(); ++it) { |
- ++(*char_counts_)[static_cast<uint8>(*it)]; |
- } |
- (*total_char_counts_) += str.size(); |
-} |
- |
-// static |
-void HpackEncoder::CookieToCrumbs(const Representation& cookie, |
- Representations* out) { |
- size_t prior_size = out->size(); |
- |
- // See Section 8.1.2.5. "Compressing the Cookie Header Field" in the HTTP/2 |
- // specification at https://tools.ietf.org/html/draft-ietf-httpbis-http2-14. |
- // Cookie values are split into individually-encoded HPACK representations. |
- for (size_t pos = 0;;) { |
- size_t end = cookie.second.find(";", pos); |
- |
- if (end == StringPiece::npos) { |
- out->push_back(make_pair( |
- cookie.first, |
- cookie.second.substr(pos))); |
- break; |
- } |
- out->push_back(make_pair( |
- cookie.first, |
- cookie.second.substr(pos, end - pos))); |
- |
- // Consume next space if present. |
- pos = end + 1; |
- if (pos != cookie.second.size() && cookie.second[pos] == ' ') { |
- pos++; |
- } |
- } |
- // Sort crumbs and remove duplicates. |
- std::sort(out->begin() + prior_size, out->end()); |
- out->erase(std::unique(out->begin() + prior_size, out->end()), |
- out->end()); |
-} |
- |
-// static |
-void HpackEncoder::DecomposeRepresentation(const Representation& header_field, |
- Representations* out) { |
- size_t pos = 0; |
- size_t end = 0; |
- while (end != StringPiece::npos) { |
- end = header_field.second.find('\0', pos); |
- out->push_back(make_pair(header_field.first, |
- header_field.second.substr(pos, end - pos))); |
- pos = end + 1; |
- } |
-} |
- |
-} // namespace net |