| Index: net/http2/hpack/huffman/http2_hpack_huffman_decoder.h
 | 
| diff --git a/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h b/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..7b8edd10c6372decd8252ea97a8dfa220c15e941
 | 
| --- /dev/null
 | 
| +++ b/net/http2/hpack/huffman/http2_hpack_huffman_decoder.h
 | 
| @@ -0,0 +1,149 @@
 | 
| +// Copyright 2016 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.
 | 
| +
 | 
| +#ifndef NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
 | 
| +#define NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
 | 
| +
 | 
| +// HpackHuffmanDecoder is an incremental decoder of strings that have been
 | 
| +// encoded using the Huffman table defined in the HPACK spec.
 | 
| +// By incremental, we mean that the HpackHuffmanDecoder::Decode method does
 | 
| +// not require the entire string to be provided, and can instead decode the
 | 
| +// string as fragments of it become available (e.g. as HPACK block fragments
 | 
| +// are received for decoding by HpackEntryDecoder).
 | 
| +
 | 
| +#include <stddef.h>
 | 
| +
 | 
| +#include <iosfwd>
 | 
| +#include <string>
 | 
| +
 | 
| +#include "base/strings/string_piece.h"
 | 
| +#include "net/base/net_export.h"
 | 
| +
 | 
| +namespace net {
 | 
| +
 | 
| +// HuffmanAccumulator is used to store bits during decoding, e.g. next N bits
 | 
| +// that have not yet been decoded, but have been extracted from the encoded
 | 
| +// string).  An advantage of using a uint64 for the accumulator
 | 
| +// is that it has room for the bits of the longest code plus the bits of a full
 | 
| +// byte; that means that when adding more bits to the accumulator, it can always
 | 
| +// be done in whole bytes. For example, if we currently have 26 bits in the
 | 
| +// accumulator, and need more to decode the current symbol, we can add a whole
 | 
| +// byte to the accumulator, and not have to do juggling with adding 6 bits (to
 | 
| +// reach 30), and then keep track of the last two bits we've not been able to
 | 
| +// add to the accumulator.
 | 
| +typedef uint64_t HuffmanAccumulator;
 | 
| +typedef size_t HuffmanAccumulatorBitCount;
 | 
| +
 | 
| +// HuffmanBitBuffer stores the leading edge of bits to be decoded. The high
 | 
| +// order bit of accumulator_ is the next bit to be decoded.
 | 
| +class NET_EXPORT_PRIVATE HuffmanBitBuffer {
 | 
| + public:
 | 
| +  HuffmanBitBuffer();
 | 
| +
 | 
| +  // Prepare for decoding a new Huffman encoded string.
 | 
| +  void Reset();
 | 
| +
 | 
| +  // Add as many whole bytes to the accumulator (accumulator_) as possible,
 | 
| +  // returning the number of bytes added.
 | 
| +  size_t AppendBytes(base::StringPiece input);
 | 
| +
 | 
| +  // Get the bits of the accumulator.
 | 
| +  HuffmanAccumulator value() const { return accumulator_; }
 | 
| +
 | 
| +  // Number of bits of the encoded string that are in the accumulator
 | 
| +  // (accumulator_).
 | 
| +  HuffmanAccumulatorBitCount count() const { return count_; }
 | 
| +
 | 
| +  // Are there no bits in the accumulator?
 | 
| +  bool IsEmpty() const { return count_ == 0; }
 | 
| +
 | 
| +  // Number of additional bits that can be added to the accumulator.
 | 
| +  HuffmanAccumulatorBitCount free_count() const;
 | 
| +
 | 
| +  // Consume the leading |code_length| bits of the accumulator.
 | 
| +  void ConsumeBits(HuffmanAccumulatorBitCount code_length);
 | 
| +
 | 
| +  // Are the contents valid for the end of a Huffman encoded string? The RFC
 | 
| +  // states that EOS (end-of-string) symbol must not be explicitly encoded in
 | 
| +  // the bit stream, but any unused bits in the final byte must be set to the
 | 
| +  // prefix of the EOS symbol, which is all 1 bits. So there can be at most 7
 | 
| +  // such bits.
 | 
| +  // Returns true if the bit buffer is empty, or contains at most 7 bits, all
 | 
| +  // of them 1. Otherwise returns false.
 | 
| +  bool InputProperlyTerminated() const;
 | 
| +
 | 
| +  std::string DebugString() const;
 | 
| +
 | 
| + private:
 | 
| +  HuffmanAccumulator accumulator_;
 | 
| +  HuffmanAccumulatorBitCount count_;
 | 
| +};
 | 
| +
 | 
| +inline std::ostream& operator<<(std::ostream& out, const HuffmanBitBuffer& v) {
 | 
| +  return out << v.DebugString();
 | 
| +}
 | 
| +
 | 
| +class NET_EXPORT_PRIVATE HpackHuffmanDecoder {
 | 
| + public:
 | 
| +  HpackHuffmanDecoder();
 | 
| +  ~HpackHuffmanDecoder();
 | 
| +
 | 
| +  // Prepare for decoding a new Huffman encoded string.
 | 
| +  void Reset() { bit_buffer_.Reset(); }
 | 
| +
 | 
| +  // Decode the portion of a HPACK Huffman encoded string that is in |input|,
 | 
| +  // appending the decoded symbols into |*output|, stopping when more bits are
 | 
| +  // needed to determine the next symbol, which/ means that the input has been
 | 
| +  // drained, and also that the bit_buffer_ is empty or that the bits that are
 | 
| +  // in it are not a whole symbol.
 | 
| +  // If |input| is the start of a string, the caller must first call Reset.
 | 
| +  // If |input| includes the end of the encoded string, the caller must call
 | 
| +  // InputProperlyTerminated after Decode has returned true in order to
 | 
| +  // determine if the encoded string was properly terminated.
 | 
| +  // Returns false if something went wrong (e.g. the encoding contains the code
 | 
| +  // EOS symbol). Otherwise returns true, in which case input has been fully
 | 
| +  // decoded or buffered; in particular, if the low-order bit of the final byte
 | 
| +  // of the input is not the last bit of an encoded symbol, then bit_buffer_
 | 
| +  // will contain the leading bits of the code for that symbol, but not the
 | 
| +  // final bits of that code.
 | 
| +  // Note that output should be empty, but that it is not cleared by Decode().
 | 
| +  bool Decode(base::StringPiece input, std::string* output);
 | 
| +
 | 
| +  // Is what remains in the bit_buffer_ valid at the end of an encoded string?
 | 
| +  // Call after passing the the final portion of a Huffman string to Decode,
 | 
| +  // and getting true as the result.
 | 
| +  bool InputProperlyTerminated() const {
 | 
| +    return bit_buffer_.InputProperlyTerminated();
 | 
| +  }
 | 
| +
 | 
| +  bool IsEmptyForTest() const { return bit_buffer_.IsEmpty(); }
 | 
| +
 | 
| +  std::string DebugString() const;
 | 
| +
 | 
| +  //////////////////////////////////////////////////////////////////////////////
 | 
| +  // Alternate implementations of Decode:
 | 
| +
 | 
| +  // As above, implemented using a tree of if statements to determine the code
 | 
| +  // length, etc., which are returned as a tree. See PrefixToInfo. This is the
 | 
| +  // original implementation, current as of 2016-8-8.
 | 
| +  bool DecodeWithIfTreeAndStruct(base::StringPiece input, std::string* output);
 | 
| +
 | 
| +  // Based on DecodeWithIfTreeAndStruct, but adds an optimization for the common
 | 
| +  // case of short codes (5, 6 or 7), which make up a large fraction of the
 | 
| +  // frequency distribution on which the HPACK table was based.
 | 
| +  // TODO(jamessynge): Be precise about that fraction.
 | 
| +  bool DecodeShortCodesFirst(base::StringPiece input, std::string* output);
 | 
| +
 | 
| + private:
 | 
| +  HuffmanBitBuffer bit_buffer_;
 | 
| +};
 | 
| +
 | 
| +inline std::ostream& operator<<(std::ostream& out,
 | 
| +                                const HpackHuffmanDecoder& v) {
 | 
| +  return out << v.DebugString();
 | 
| +}
 | 
| +
 | 
| +}  // namespace net
 | 
| +
 | 
| +#endif  // NET_HTTP2_HPACK_HUFFMAN_HTTP2_HPACK_HUFFMAN_DECODER_H_
 | 
| 
 |