1 // Copyright 2016 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.
4
5 #include "quiche/http2/hpack/varint/hpack_varint_encoder.h"
6
7 #include <limits>
8
9 #include "quiche/common/platform/api/quiche_logging.h"
10
11 namespace http2 {
12
13 // static
Encode(uint8_t high_bits,uint8_t prefix_length,uint64_t varint,std::string * output)14 void HpackVarintEncoder::Encode(uint8_t high_bits, uint8_t prefix_length,
15 uint64_t varint, std::string* output) {
16 QUICHE_DCHECK_LE(1u, prefix_length);
17 QUICHE_DCHECK_LE(prefix_length, 8u);
18
19 // prefix_mask defines the sequence of low-order bits of the first byte
20 // that encode the prefix of the value. It is also the marker in those bits
21 // of the first byte indicating that at least one extension byte is needed.
22 const uint8_t prefix_mask = (1 << prefix_length) - 1;
23 QUICHE_DCHECK_EQ(0, high_bits & prefix_mask);
24
25 if (varint < prefix_mask) {
26 // The integer fits into the prefix in its entirety.
27 unsigned char first_byte = high_bits | static_cast<unsigned char>(varint);
28 output->push_back(first_byte);
29 return;
30 }
31
32 // Extension bytes are needed.
33 unsigned char first_byte = high_bits | prefix_mask;
34 output->push_back(first_byte);
35
36 varint -= prefix_mask;
37 while (varint >= 128) {
38 // Encode the next seven bits, with continuation bit set to one.
39 output->push_back(0b10000000 | (varint % 128));
40 varint >>= 7;
41 }
42
43 // Encode final seven bits, with continuation bit set to zero.
44 output->push_back(varint);
45 }
46
47 } // namespace http2
48