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