1*61c4878aSAndroid Build Coastguard Worker // Copyright 2023 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker #include "pw_varint/varint.h"
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker #define VARINT_ENCODE_FUNCTION_BODY(bits) \
18*61c4878aSAndroid Build Coastguard Worker size_t written = 0; \
19*61c4878aSAndroid Build Coastguard Worker uint8_t* buffer = (uint8_t*)output; \
20*61c4878aSAndroid Build Coastguard Worker \
21*61c4878aSAndroid Build Coastguard Worker do { \
22*61c4878aSAndroid Build Coastguard Worker if (written >= output_size_bytes) { \
23*61c4878aSAndroid Build Coastguard Worker return 0u; \
24*61c4878aSAndroid Build Coastguard Worker } \
25*61c4878aSAndroid Build Coastguard Worker buffer[written++] = pw_varint_EncodeOneByte##bits(&integer); \
26*61c4878aSAndroid Build Coastguard Worker } while (integer != 0u); \
27*61c4878aSAndroid Build Coastguard Worker \
28*61c4878aSAndroid Build Coastguard Worker buffer[written - 1] &= 0x7f; \
29*61c4878aSAndroid Build Coastguard Worker return written
30*61c4878aSAndroid Build Coastguard Worker
pw_varint_Encode32(uint32_t integer,void * output,size_t output_size_bytes)31*61c4878aSAndroid Build Coastguard Worker size_t pw_varint_Encode32(uint32_t integer,
32*61c4878aSAndroid Build Coastguard Worker void* output,
33*61c4878aSAndroid Build Coastguard Worker size_t output_size_bytes) {
34*61c4878aSAndroid Build Coastguard Worker VARINT_ENCODE_FUNCTION_BODY(32);
35*61c4878aSAndroid Build Coastguard Worker }
36*61c4878aSAndroid Build Coastguard Worker
pw_varint_Encode64(uint64_t integer,void * output,size_t output_size_bytes)37*61c4878aSAndroid Build Coastguard Worker size_t pw_varint_Encode64(uint64_t integer,
38*61c4878aSAndroid Build Coastguard Worker void* output,
39*61c4878aSAndroid Build Coastguard Worker size_t output_size_bytes) {
40*61c4878aSAndroid Build Coastguard Worker VARINT_ENCODE_FUNCTION_BODY(64);
41*61c4878aSAndroid Build Coastguard Worker }
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker #define VARINT_DECODE_FUNCTION_BODY(bits) \
44*61c4878aSAndroid Build Coastguard Worker uint##bits##_t value = 0; \
45*61c4878aSAndroid Build Coastguard Worker size_t count = 0; \
46*61c4878aSAndroid Build Coastguard Worker const uint8_t* buffer = (const uint8_t*)(input); \
47*61c4878aSAndroid Build Coastguard Worker \
48*61c4878aSAndroid Build Coastguard Worker /* Only read to the end of the buffer or largest possible encoded size. */ \
49*61c4878aSAndroid Build Coastguard Worker const size_t max_count = \
50*61c4878aSAndroid Build Coastguard Worker input_size_bytes < PW_VARINT_MAX_INT##bits##_SIZE_BYTES \
51*61c4878aSAndroid Build Coastguard Worker ? input_size_bytes \
52*61c4878aSAndroid Build Coastguard Worker : PW_VARINT_MAX_INT##bits##_SIZE_BYTES; \
53*61c4878aSAndroid Build Coastguard Worker \
54*61c4878aSAndroid Build Coastguard Worker bool keep_going; \
55*61c4878aSAndroid Build Coastguard Worker do { \
56*61c4878aSAndroid Build Coastguard Worker if (count >= max_count) { \
57*61c4878aSAndroid Build Coastguard Worker return 0; \
58*61c4878aSAndroid Build Coastguard Worker } \
59*61c4878aSAndroid Build Coastguard Worker \
60*61c4878aSAndroid Build Coastguard Worker keep_going = pw_varint_DecodeOneByte##bits(buffer[count], count, &value); \
61*61c4878aSAndroid Build Coastguard Worker count += 1; \
62*61c4878aSAndroid Build Coastguard Worker } while (keep_going); \
63*61c4878aSAndroid Build Coastguard Worker \
64*61c4878aSAndroid Build Coastguard Worker *output = value; \
65*61c4878aSAndroid Build Coastguard Worker return count
66*61c4878aSAndroid Build Coastguard Worker
pw_varint_Decode32(const void * input,size_t input_size_bytes,uint32_t * output)67*61c4878aSAndroid Build Coastguard Worker size_t pw_varint_Decode32(const void* input,
68*61c4878aSAndroid Build Coastguard Worker size_t input_size_bytes,
69*61c4878aSAndroid Build Coastguard Worker uint32_t* output) {
70*61c4878aSAndroid Build Coastguard Worker VARINT_DECODE_FUNCTION_BODY(32);
71*61c4878aSAndroid Build Coastguard Worker }
72*61c4878aSAndroid Build Coastguard Worker
pw_varint_Decode64(const void * input,size_t input_size_bytes,uint64_t * output)73*61c4878aSAndroid Build Coastguard Worker size_t pw_varint_Decode64(const void* input,
74*61c4878aSAndroid Build Coastguard Worker size_t input_size_bytes,
75*61c4878aSAndroid Build Coastguard Worker uint64_t* output) {
76*61c4878aSAndroid Build Coastguard Worker VARINT_DECODE_FUNCTION_BODY(64);
77*61c4878aSAndroid Build Coastguard Worker }
78