| Index: net/spdy/hpack_encoder.cc
|
| diff --git a/net/spdy/hpack_encoder.cc b/net/spdy/hpack_encoder.cc
|
| index a70af8669f2e597ea7b3300857996a28353357e6..322817229f799a8a3547b5bbed2fd09300fe473f 100644
|
| --- a/net/spdy/hpack_encoder.cc
|
| +++ b/net/spdy/hpack_encoder.cc
|
| @@ -16,18 +16,6 @@ namespace net {
|
| using base::StringPiece;
|
| using std::string;
|
|
|
| -namespace {
|
| -
|
| -const uint8 kNoState = 0;
|
| -// Set on a referenced HpackEntry which is part of the current header set.
|
| -const uint8 kReferencedImplicitOn = 1;
|
| -// Set on a referenced HpackEntry which is not part of the current header set.
|
| -const uint8 kReferencedExplicitOff = 2;
|
| -// Set on a entries added to the reference set during this encoding.
|
| -const uint8 kReferencedThisEncoding = 3;
|
| -
|
| -} // namespace
|
| -
|
| HpackEncoder::HpackEncoder(const HpackHuffmanTable& table)
|
| : output_stream_(),
|
| allow_huffman_compression_(true),
|
| @@ -39,59 +27,30 @@ HpackEncoder::~HpackEncoder() {}
|
|
|
| bool HpackEncoder::EncodeHeaderSet(const std::map<string, string>& header_set,
|
| string* output) {
|
| - // Walk the set of entries to encode, which are not already implied by the
|
| - // header table's reference set. They must be explicitly emitted.
|
| - Representations explicit_set(DetermineEncodingDelta(header_set));
|
| - for (Representations::const_iterator it = explicit_set.begin();
|
| - it != explicit_set.end(); ++it) {
|
| - // Try to find an exact match. Note that dynamic entries are preferred
|
| - // by the header table index.
|
| - HpackEntry* entry = header_table_.GetByNameAndValue(it->first, it->second);
|
| - if (entry != NULL && !entry->IsStatic()) {
|
| - // Already in the dynamic table. Simply toggle on.
|
| - CHECK_EQ(kNoState, entry->state());
|
| - EmitDynamicIndex(entry);
|
| - continue;
|
| - }
|
| -
|
| - // Walk the set of entries to be evicted by this insertion.
|
| - HpackHeaderTable::EntryTable::iterator evict_begin, evict_end, evict_it;
|
| - header_table_.EvictionSet(it->first, it->second, &evict_begin, &evict_end);
|
| -
|
| - for (evict_it = evict_begin; evict_it != evict_end; ++evict_it) {
|
| - HpackEntry* evictee = &(*evict_it);
|
| -
|
| - if (evict_it->state() == kReferencedImplicitOn) {
|
| - // Issue twice to explicitly emit.
|
| - EmitDynamicIndex(evictee);
|
| - EmitDynamicIndex(evictee);
|
| - } else if (evictee->state() == kReferencedExplicitOff) {
|
| - // Eviction saves us from having to explicitly toggle off.
|
| - evictee->set_state(kNoState);
|
| - } else if (evictee->state() == kReferencedThisEncoding) {
|
| - // Already emitted. No action required.
|
| - evictee->set_state(kNoState);
|
| - }
|
| - }
|
| - if (entry != NULL) {
|
| - EmitStaticIndex(entry);
|
| + // Flatten & crumble headers into an ordered list of representations.
|
| + Representations full_set;
|
| + for (std::map<string, string>::const_iterator it = header_set.begin();
|
| + it != header_set.end(); ++it) {
|
| + if (it->first == "cookie") {
|
| + // |CookieToCrumbs()| produces ordered crumbs.
|
| + CookieToCrumbs(*it, &full_set);
|
| } else {
|
| - EmitIndexedLiteral(*it);
|
| + // Note std::map guarantees representations are ordered.
|
| + full_set.push_back(make_pair(
|
| + StringPiece(it->first), StringPiece(it->second)));
|
| }
|
| }
|
| - // Walk the reference set, toggling off as needed and clearing encoding state.
|
| - for (HpackHeaderTable::OrderedEntrySet::const_iterator it =
|
| - header_table_.reference_set().begin();
|
| - it != header_table_.reference_set().end();) {
|
| - HpackEntry* entry = *(it++); // Step to prevent invalidation.
|
| - CHECK_NE(kNoState, entry->state());
|
|
|
| - if (entry->state() == kReferencedExplicitOff) {
|
| - // Explicitly toggle off.
|
| - EmitDynamicIndex(entry);
|
| - }
|
| - entry->set_state(kNoState);
|
| + // Walk this ordered list and encode entries.
|
| + for (Representations::const_iterator it = full_set.begin();
|
| + it != full_set.end(); ++it) {
|
| + HpackEntry* entry = header_table_.GetByNameAndValue(it->first, it->second);
|
| + if (entry != NULL)
|
| + EmitIndex(entry);
|
| + else
|
| + EmitIndexedLiteral(*it);
|
| }
|
| +
|
| output_stream_.TakeString(output);
|
| return true;
|
| }
|
| @@ -111,42 +70,15 @@ bool HpackEncoder::EncodeHeaderSetWithoutCompression(
|
| return true;
|
| }
|
|
|
| -void HpackEncoder::EmitDynamicIndex(HpackEntry* entry) {
|
| - DCHECK(!entry->IsStatic());
|
| - output_stream_.AppendPrefix(kIndexedOpcode);
|
| - output_stream_.AppendUint32(header_table_.IndexOf(entry));
|
| -
|
| - entry->set_state(kNoState);
|
| - if (header_table_.Toggle(entry)) {
|
| - // Was added to the reference set.
|
| - entry->set_state(kReferencedThisEncoding);
|
| - }
|
| -}
|
| -
|
| -void HpackEncoder::EmitStaticIndex(HpackEntry* entry) {
|
| - DCHECK(entry->IsStatic());
|
| +void HpackEncoder::EmitIndex(HpackEntry* entry) {
|
| output_stream_.AppendPrefix(kIndexedOpcode);
|
| output_stream_.AppendUint32(header_table_.IndexOf(entry));
|
| -
|
| - HpackEntry* new_entry = header_table_.TryAddEntry(entry->name(),
|
| - entry->value());
|
| - if (new_entry) {
|
| - // This is a static entry: no need to pin.
|
| - header_table_.Toggle(new_entry);
|
| - new_entry->set_state(kReferencedThisEncoding);
|
| - }
|
| }
|
|
|
| void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
|
| output_stream_.AppendPrefix(kLiteralIncrementalIndexOpcode);
|
| EmitLiteral(representation);
|
| -
|
| - HpackEntry* new_entry = header_table_.TryAddEntry(representation.first,
|
| - representation.second);
|
| - if (new_entry) {
|
| - header_table_.Toggle(new_entry);
|
| - new_entry->set_state(kReferencedThisEncoding);
|
| - }
|
| + header_table_.TryAddEntry(representation.first, representation.second);
|
| }
|
|
|
| void HpackEncoder::EmitNonIndexedLiteral(
|
| @@ -183,61 +115,6 @@ void HpackEncoder::EmitString(StringPiece str) {
|
| UpdateCharacterCounts(str);
|
| }
|
|
|
| -// static
|
| -HpackEncoder::Representations HpackEncoder::DetermineEncodingDelta(
|
| - const std::map<string, string>& header_set) {
|
| - // Flatten & crumble headers into an ordered list of representations.
|
| - Representations full_set;
|
| - for (std::map<string, string>::const_iterator it = header_set.begin();
|
| - it != header_set.end(); ++it) {
|
| - if (it->first == "cookie") {
|
| - // |CookieToCrumbs()| produces ordered crumbs.
|
| - CookieToCrumbs(*it, &full_set);
|
| - } else {
|
| - // Note std::map guarantees representations are ordered.
|
| - full_set.push_back(make_pair(
|
| - StringPiece(it->first), StringPiece(it->second)));
|
| - }
|
| - }
|
| - // Perform a linear merge of ordered representations with the (also ordered)
|
| - // reference set. Mark each referenced entry with current membership state,
|
| - // and gather representations which must be explicitly emitted.
|
| - Representations::const_iterator r_it = full_set.begin();
|
| - HpackHeaderTable::OrderedEntrySet::const_iterator s_it =
|
| - header_table_.reference_set().begin();
|
| -
|
| - Representations explicit_set;
|
| - while (r_it != full_set.end() &&
|
| - s_it != header_table_.reference_set().end()) {
|
| - // Compare on name, then value.
|
| - int result = r_it->first.compare((*s_it)->name());
|
| - if (result == 0) {
|
| - result = r_it->second.compare((*s_it)->value());
|
| - }
|
| -
|
| - if (result < 0) {
|
| - explicit_set.push_back(*r_it);
|
| - ++r_it;
|
| - } else if (result > 0) {
|
| - (*s_it)->set_state(kReferencedExplicitOff);
|
| - ++s_it;
|
| - } else {
|
| - (*s_it)->set_state(kReferencedImplicitOn);
|
| - ++s_it;
|
| - ++r_it;
|
| - }
|
| - }
|
| - while (r_it != full_set.end()) {
|
| - explicit_set.push_back(*r_it);
|
| - ++r_it;
|
| - }
|
| - while (s_it != header_table_.reference_set().end()) {
|
| - (*s_it)->set_state(kReferencedExplicitOff);
|
| - ++s_it;
|
| - }
|
| - return explicit_set;
|
| -}
|
| -
|
| void HpackEncoder::SetCharCountsStorage(std::vector<size_t>* char_counts,
|
| size_t* total_char_counts) {
|
| CHECK_LE(256u, char_counts->size());
|
|
|