Index: net/spdy/http2_compressor.cc |
diff --git a/net/spdy/http2_compressor.cc b/net/spdy/http2_compressor.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2b79530583001a49246221c05c913a9f204fb463 |
--- /dev/null |
+++ b/net/spdy/http2_compressor.cc |
@@ -0,0 +1,119 @@ |
+// Copyright (c) 2013 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/http2_compressor.h" |
+ |
+#include "base/logging.h" |
+ |
+namespace net { |
+ |
+Http2Encoder::Http2Encoder() {} |
+ |
+void Http2Encoder::EncodeOctet(uint8 octet) { |
+ buffer_.append(1, octet); |
+} |
+ |
+void Http2Encoder::EncodeInteger(uint8 op_code, uint8 N, uint32 I) { |
+ DCHECK_LT(N, 8u); |
+ DCHECK_LT(static_cast<uint16>(op_code), 1u << (8 - N)); |
+ |
+ uint8 next_marker = (1 << N) - 1; |
+ |
+ if (I < next_marker) { |
+ EncodeOctet((op_code << N) | I); |
+ return; |
+ } |
+ |
+ if (N > 0) { |
+ EncodeOctet((op_code << N) | next_marker); |
+ } |
+ |
+ I -= next_marker; |
+ while (I >= 128) { |
+ EncodeOctet(I % 128 | 128); |
+ I /= 128; |
+ } |
+ EncodeOctet(I); |
+} |
+ |
+void Http2Encoder::EncodeOctetSequence(base::StringPiece str) { |
+ uint32 size_to_encode = static_cast<uint32>(str.size()); |
+ DCHECK_EQ(static_cast<size_t>(size_to_encode), str.size()); |
+ EncodeInteger(0, 0, size_to_encode); |
+ buffer_.append(str.data(), str.size()); |
+} |
+ |
+void Http2Encoder::EncodeIndexedHeader(uint32 index) { |
+ EncodeInteger(kIndexOpcode, kIndexN, index); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderNoIndexingWithIndex( |
+ uint32 index, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralNoIndexOpcode, kLiteralNoIndexN, index + 1); |
+ EncodeOctetSequence(value); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderNoIndexingWithName( |
+ base::StringPiece name, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralNoIndexOpcode, kLiteralNoIndexN, 0); |
+ EncodeOctetSequence(name); |
+ EncodeOctetSequence(value); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderWithIncrementalIndexingWithIndex( |
+ uint32 index, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralIncrementalOpcode, kLiteralIncrementalN, index + 1); |
+ EncodeOctetSequence(value); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderWithIncrementalIndexingWithName( |
+ base::StringPiece name, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralIncrementalOpcode, kLiteralIncrementalN, 0); |
+ EncodeOctetSequence(name); |
+ EncodeOctetSequence(value); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderWithSubstitutionIndexingWithIndex( |
+ uint32 index, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralSubstitutionOpcode, kLiteralSubstitutionN, index + 1); |
+ EncodeOctetSequence(value); |
+} |
+ |
+void Http2Encoder::EncodeLiteralHeaderWithSubstitutionIndexingWithName( |
+ base::StringPiece name, |
+ base::StringPiece value) { |
+ EncodeInteger(kLiteralSubstitutionOpcode, kLiteralSubstitutionN, 0); |
+ EncodeOctetSequence(name); |
+ EncodeOctetSequence(value); |
+} |
+ |
+std::string Http2Encoder::Flush() { |
+ std::string out; |
+ out.swap(buffer_); |
+ return out; |
+} |
+ |
+Http2Compressor::Http2Compressor() : encoding_context_(HTTP2_REQUEST) {} |
+ |
+Http2Compressor::~Http2Compressor() {} |
+ |
+std::string Http2Compressor::EncodeNameValueBlock( |
+ const SpdyNameValueBlock& name_value_block) { |
+ Http2Encoder encoder; |
+ for (SpdyNameValueBlock::const_iterator it = name_value_block.begin(); |
+ it != name_value_block.end(); ++it) { |
+ encoder.EncodeLiteralHeaderNoIndexingWithName(it->first, it->second); |
+ } |
+ |
+ // TODO(akalin): Process unemitted entries in reference set. |
+ |
+ return encoder.Flush(); |
+} |
+ |
+} // namespace net |