| 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
|
|
|