bin_encoder.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
22 
23 #include <stdint.h>
24 #include <string.h>
25 
26 #include <grpc/support/log.h>
27 
29 
30 static const char alphabet[] =
31  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 
33 struct b64_huff_sym {
36 };
37 static const b64_huff_sym huff_alphabet[64] = {
38  {0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7},
39  {0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7},
40  {0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7},
41  {0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8},
42  {0x73, 7}, {0xfd, 8}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6},
43  {0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7},
44  {0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6},
45  {0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7},
46  {0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x0, 5}, {0x1, 5},
47  {0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6},
48  {0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}};
49 
50 static const uint8_t tail_xtra[3] = {0, 2, 3};
51 
53  size_t input_length = GRPC_SLICE_LENGTH(input);
54  size_t input_triplets = input_length / 3;
55  size_t tail_case = input_length % 3;
56  size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
57  grpc_slice output = GRPC_SLICE_MALLOC(output_length);
59  char* out = reinterpret_cast<char*> GRPC_SLICE_START_PTR(output);
60  size_t i;
61 
62  /* encode full triplets */
63  for (i = 0; i < input_triplets; i++) {
64  out[0] = alphabet[in[0] >> 2];
65  out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
66  out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
67  out[3] = alphabet[in[2] & 0x3f];
68  out += 4;
69  in += 3;
70  }
71 
72  /* encode the remaining bytes */
73  switch (tail_case) {
74  case 0:
75  break;
76  case 1:
77  out[0] = alphabet[in[0] >> 2];
78  out[1] = alphabet[(in[0] & 0x3) << 4];
79  out += 2;
80  in += 1;
81  break;
82  case 2:
83  out[0] = alphabet[in[0] >> 2];
84  out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
85  out[2] = alphabet[(in[1] & 0xf) << 2];
86  out += 3;
87  in += 2;
88  break;
89  }
90 
93  return output;
94 }
95 
97  size_t nbits;
98  const uint8_t* in;
99  uint8_t* out;
101  uint32_t temp = 0;
102  uint32_t temp_length = 0;
103 
104  nbits = 0;
106  ++in) {
107  nbits += grpc_chttp2_huffsyms[*in].length;
108  }
109 
110  output = GRPC_SLICE_MALLOC(nbits / 8 + (nbits % 8 != 0));
113  ++in) {
114  int sym = *in;
117  temp_length += grpc_chttp2_huffsyms[sym].length;
118 
119  while (temp_length > 8) {
120  temp_length -= 8;
121  *out++ = static_cast<uint8_t>(temp >> temp_length);
122  }
123  }
124 
125  if (temp_length) {
126  /* NB: the following integer arithmetic operation needs to be in its
127  * expanded form due to the "integral promotion" performed (see section
128  * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
129  * is then required to avoid the compiler warning */
130  *out++ =
131  static_cast<uint8_t>(static_cast<uint8_t>(temp << (8u - temp_length)) |
132  static_cast<uint8_t>(0xffu >> temp_length));
133  }
134 
136 
137  return output;
138 }
139 
140 struct huff_out {
144 };
145 static void enc_flush_some(huff_out* out) {
146  while (out->temp_length > 8) {
147  out->temp_length -= 8;
148  *out->out++ = static_cast<uint8_t>(out->temp >> out->temp_length);
149  }
150 }
151 
152 static void enc_add2(huff_out* out, uint8_t a, uint8_t b) {
155  out->temp = (out->temp << (sa.length + sb.length)) |
156  (static_cast<uint32_t>(sa.bits) << sb.length) | sb.bits;
157  out->temp_length +=
158  static_cast<uint32_t>(sa.length) + static_cast<uint32_t>(sb.length);
160 }
161 
162 static void enc_add1(huff_out* out, uint8_t a) {
164  out->temp = (out->temp << sa.length) | sa.bits;
165  out->temp_length += sa.length;
167 }
168 
170  const grpc_slice& input) {
171  size_t input_length = GRPC_SLICE_LENGTH(input);
172  size_t input_triplets = input_length / 3;
173  size_t tail_case = input_length % 3;
174  size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
175  size_t max_output_bits = 11 * output_syms;
176  size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
177  grpc_slice output = GRPC_SLICE_MALLOC(max_output_length);
179  uint8_t* start_out = GRPC_SLICE_START_PTR(output);
180  huff_out out;
181  size_t i;
182 
183  out.temp = 0;
184  out.temp_length = 0;
185  out.out = start_out;
186 
187  /* encode full triplets */
188  for (i = 0; i < input_triplets; i++) {
189  const uint8_t low_to_high = static_cast<uint8_t>((in[0] & 0x3) << 4);
190  const uint8_t high_to_low = in[1] >> 4;
191  enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
192 
193  const uint8_t a = static_cast<uint8_t>((in[1] & 0xf) << 2);
194  const uint8_t b = (in[2] >> 6);
195  enc_add2(&out, a | b, in[2] & 0x3f);
196  in += 3;
197  }
198 
199  /* encode the remaining bytes */
200  switch (tail_case) {
201  case 0:
202  break;
203  case 1:
204  enc_add2(&out, in[0] >> 2, static_cast<uint8_t>((in[0] & 0x3) << 4));
205  in += 1;
206  break;
207  case 2: {
208  const uint8_t low_to_high = static_cast<uint8_t>((in[0] & 0x3) << 4);
209  const uint8_t high_to_low = in[1] >> 4;
210  enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
211  enc_add1(&out, static_cast<uint8_t>((in[1] & 0xf) << 2));
212  in += 2;
213  break;
214  }
215  }
216 
217  if (out.temp_length) {
218  /* NB: the following integer arithmetic operation needs to be in its
219  * expanded form due to the "integral promotion" performed (see section
220  * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
221  * is then required to avoid the compiler warning */
222  *out.out++ = static_cast<uint8_t>(
223  static_cast<uint8_t>(out.temp << (8u - out.temp_length)) |
224  static_cast<uint8_t>(0xffu >> out.temp_length));
225  }
226 
228  GRPC_SLICE_SET_LENGTH(output, out.out - start_out);
229 
231  return output;
232 }
fix_build_deps.temp
temp
Definition: fix_build_deps.py:488
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
log.h
enc_add1
static void enc_add1(huff_out *out, uint8_t a)
Definition: bin_encoder.cc:162
grpc_chttp2_base64_encode_and_huffman_compress
grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(const grpc_slice &input)
Definition: bin_encoder.cc:169
huff_out::out
uint8_t * out
Definition: bin_encoder.cc:143
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
string.h
GRPC_SLICE_MALLOC
#define GRPC_SLICE_MALLOC(len)
Definition: include/grpc/slice.h:70
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
enc_add2
static void enc_add2(huff_out *out, uint8_t a, uint8_t b)
Definition: bin_encoder.cc:152
GRPC_SLICE_SET_LENGTH
#define GRPC_SLICE_SET_LENGTH(slice, newlen)
Definition: include/grpc/impl/codegen/slice.h:107
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
alphabet
static const char alphabet[]
Definition: bin_encoder.cc:30
b64_huff_sym
Definition: bin_encoder.cc:33
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
grpc_chttp2_huffsym::bits
unsigned bits
Definition: huffsyms.h:27
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
huff_out::temp
uint32_t temp
Definition: bin_encoder.cc:141
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
b64_huff_sym::length
uint8_t length
Definition: bin_encoder.cc:35
enc_flush_some
static void enc_flush_some(huff_out *out)
Definition: bin_encoder.cc:145
GRPC_SLICE_START_PTR
#define GRPC_SLICE_START_PTR(slice)
Definition: include/grpc/impl/codegen/slice.h:101
huff_out
Definition: bin_encoder.cc:140
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
grpc_chttp2_huffsym::length
unsigned length
Definition: huffsyms.h:28
grpc_chttp2_huffsyms
const grpc_chttp2_huffsym grpc_chttp2_huffsyms[GRPC_CHTTP2_NUM_HUFFSYMS]
Definition: huffsyms.cc:26
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
GRPC_SLICE_END_PTR
#define GRPC_SLICE_END_PTR(slice)
Definition: include/grpc/impl/codegen/slice.h:110
huff_out::temp_length
uint32_t temp_length
Definition: bin_encoder.cc:142
stdint.h
GRPC_SLICE_LENGTH
#define GRPC_SLICE_LENGTH(slice)
Definition: include/grpc/impl/codegen/slice.h:104
huff_alphabet
static const b64_huff_sym huff_alphabet[64]
Definition: bin_encoder.cc:37
grpc_chttp2_base64_encode
grpc_slice grpc_chttp2_base64_encode(const grpc_slice &input)
Definition: bin_encoder.cc:52
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
grpc_chttp2_huffman_compress
grpc_slice grpc_chttp2_huffman_compress(const grpc_slice &input)
Definition: bin_encoder.cc:96
huffsyms.h
b64_huff_sym::bits
uint16_t bits
Definition: bin_encoder.cc:34
tail_xtra
static const uint8_t tail_xtra[3]
Definition: bin_encoder.cc:50
bin_encoder.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:37