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/hpack_output_stream.h"
7 #include "base/logging.h"
11 using base::StringPiece
;
14 HpackOutputStream::HpackOutputStream() : bit_offset_(0) {}
16 HpackOutputStream::~HpackOutputStream() {}
18 void HpackOutputStream::AppendBits(uint8 bits
, size_t bit_size
) {
19 DCHECK_GT(bit_size
, 0u);
20 DCHECK_LE(bit_size
, 8u);
21 DCHECK_EQ(bits
>> bit_size
, 0);
22 size_t new_bit_offset
= bit_offset_
+ bit_size
;
23 if (bit_offset_
== 0) {
24 // Buffer ends on a byte boundary.
25 DCHECK_LE(bit_size
, 8u);
26 buffer_
.append(1, bits
<< (8 - bit_size
));
27 } else if (new_bit_offset
<= 8) {
28 // Buffer does not end on a byte boundary but the given bits fit
29 // in the remainder of the last byte.
30 *buffer_
.rbegin() |= bits
<< (8 - new_bit_offset
);
32 // Buffer does not end on a byte boundary and the given bits do
33 // not fit in the remainder of the last byte.
34 *buffer_
.rbegin() |= bits
>> (new_bit_offset
- 8);
35 buffer_
.append(1, bits
<< (16 - new_bit_offset
));
37 bit_offset_
= new_bit_offset
% 8;
40 void HpackOutputStream::AppendPrefix(HpackPrefix prefix
) {
41 AppendBits(prefix
.bits
, prefix
.bit_size
);
44 void HpackOutputStream::AppendBytes(StringPiece buffer
) {
45 DCHECK_EQ(bit_offset_
, 0u);
46 buffer_
.append(buffer
.data(), buffer
.size());
49 void HpackOutputStream::AppendUint32(uint32 I
) {
50 // The algorithm below is adapted from the pseudocode in 6.1.
51 size_t N
= 8 - bit_offset_
;
52 uint8 max_first_byte
= static_cast<uint8
>((1 << N
) - 1);
53 if (I
< max_first_byte
) {
54 AppendBits(static_cast<uint8
>(I
), N
);
56 AppendBits(max_first_byte
, N
);
58 while ((I
& ~0x7f) != 0) {
59 buffer_
.append(1, (I
& 0x7f) | 0x80);
62 AppendBits(static_cast<uint8
>(I
), 8);
66 void HpackOutputStream::TakeString(string
* output
) {
67 // This must hold, since all public functions cause the buffer to
68 // end on a byte boundary.
69 DCHECK_EQ(bit_offset_
, 0u);
70 buffer_
.swap(*output
);