xref: /aosp_15_r20/external/pigweed/pw_varint/varint_c.c (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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