Remove NavigationRequestInfo::is_showing.
[chromium-blink-merge.git] / net / spdy / hpack_encoder.cc
blob735e8c0b48019799255f94a880427d6bd51087a7
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/hpack_encoder.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "net/spdy/hpack_header_table.h"
11 #include "net/spdy/hpack_huffman_table.h"
12 #include "net/spdy/hpack_output_stream.h"
14 namespace net {
16 using base::StringPiece;
17 using std::string;
19 HpackEncoder::HpackEncoder(const HpackHuffmanTable& table)
20 : output_stream_(),
21 allow_huffman_compression_(true),
22 huffman_table_(table),
23 char_counts_(NULL),
24 total_char_counts_(NULL) {}
26 HpackEncoder::~HpackEncoder() {}
28 bool HpackEncoder::EncodeHeaderSet(const std::map<string, string>& header_set,
29 string* output) {
30 // Flatten & crumble headers into an ordered list of representations.
31 Representations full_set;
32 for (std::map<string, string>::const_iterator it = header_set.begin();
33 it != header_set.end(); ++it) {
34 if (it->first == "cookie") {
35 // |CookieToCrumbs()| produces ordered crumbs.
36 CookieToCrumbs(*it, &full_set);
37 } else {
38 // Note std::map guarantees representations are ordered.
39 full_set.push_back(make_pair(
40 StringPiece(it->first), StringPiece(it->second)));
44 // Walk this ordered list and encode entries.
45 for (Representations::const_iterator it = full_set.begin();
46 it != full_set.end(); ++it) {
47 HpackEntry* entry = header_table_.GetByNameAndValue(it->first, it->second);
48 if (entry != NULL) {
49 EmitIndex(entry);
50 } else {
51 // TODO(bnc): if another entry in the header table is about to be evicted
52 // but it appears in the header list, emit that by index first.
53 EmitIndexedLiteral(*it);
57 output_stream_.TakeString(output);
58 return true;
61 bool HpackEncoder::EncodeHeaderSetWithoutCompression(
62 const std::map<string, string>& header_set,
63 string* output) {
65 allow_huffman_compression_ = false;
66 for (std::map<string, string>::const_iterator it = header_set.begin();
67 it != header_set.end(); ++it) {
68 // Note that cookies are not crumbled in this case.
69 EmitNonIndexedLiteral(*it);
71 allow_huffman_compression_ = true;
72 output_stream_.TakeString(output);
73 return true;
76 void HpackEncoder::EmitIndex(HpackEntry* entry) {
77 output_stream_.AppendPrefix(kIndexedOpcode);
78 output_stream_.AppendUint32(header_table_.IndexOf(entry));
81 void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
82 output_stream_.AppendPrefix(kLiteralIncrementalIndexOpcode);
83 EmitLiteral(representation);
84 header_table_.TryAddEntry(representation.first, representation.second);
87 void HpackEncoder::EmitNonIndexedLiteral(
88 const Representation& representation) {
89 output_stream_.AppendPrefix(kLiteralNoIndexOpcode);
90 output_stream_.AppendUint32(0);
91 EmitString(representation.first);
92 EmitString(representation.second);
95 void HpackEncoder::EmitLiteral(const Representation& representation) {
96 const HpackEntry* name_entry = header_table_.GetByName(representation.first);
97 if (name_entry != NULL) {
98 output_stream_.AppendUint32(header_table_.IndexOf(name_entry));
99 } else {
100 output_stream_.AppendUint32(0);
101 EmitString(representation.first);
103 EmitString(representation.second);
106 void HpackEncoder::EmitString(StringPiece str) {
107 size_t encoded_size = (!allow_huffman_compression_ ? str.size()
108 : huffman_table_.EncodedSize(str));
109 if (encoded_size < str.size()) {
110 output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded);
111 output_stream_.AppendUint32(encoded_size);
112 huffman_table_.EncodeString(str, &output_stream_);
113 } else {
114 output_stream_.AppendPrefix(kStringLiteralIdentityEncoded);
115 output_stream_.AppendUint32(str.size());
116 output_stream_.AppendBytes(str);
118 UpdateCharacterCounts(str);
121 void HpackEncoder::SetCharCountsStorage(std::vector<size_t>* char_counts,
122 size_t* total_char_counts) {
123 CHECK_LE(256u, char_counts->size());
124 char_counts_ = char_counts;
125 total_char_counts_ = total_char_counts;
128 void HpackEncoder::UpdateCharacterCounts(base::StringPiece str) {
129 if (char_counts_ == NULL || total_char_counts_ == NULL) {
130 return;
132 for (StringPiece::const_iterator it = str.begin(); it != str.end(); ++it) {
133 ++(*char_counts_)[static_cast<uint8>(*it)];
135 (*total_char_counts_) += str.size();
138 // static
139 void HpackEncoder::CookieToCrumbs(const Representation& cookie,
140 Representations* out) {
141 size_t prior_size = out->size();
143 // See Section 8.1.3.4 "Compressing the Cookie Header Field" in the HTTP/2
144 // specification at http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
145 // Cookie values are split into individually-encoded HPACK representations.
146 for (size_t pos = 0;;) {
147 size_t end = cookie.second.find(";", pos);
149 if (end == StringPiece::npos) {
150 out->push_back(make_pair(
151 cookie.first,
152 cookie.second.substr(pos)));
153 break;
155 out->push_back(make_pair(
156 cookie.first,
157 cookie.second.substr(pos, end - pos)));
159 // Consume next space if present.
160 pos = end + 1;
161 if (pos != cookie.second.size() && cookie.second[pos] == ' ') {
162 pos++;
165 // Sort crumbs and remove duplicates.
166 std::sort(out->begin() + prior_size, out->end());
167 out->erase(std::unique(out->begin() + prior_size, out->end()),
168 out->end());
171 } // namespace net