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