aboutsummaryrefslogtreecommitdiff
path: root/pw_varint/varint_c.c
diff options
context:
space:
mode:
Diffstat (limited to 'pw_varint/varint_c.c')
-rw-r--r--pw_varint/varint_c.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/pw_varint/varint_c.c b/pw_varint/varint_c.c
new file mode 100644
index 000000000..9194b4e34
--- /dev/null
+++ b/pw_varint/varint_c.c
@@ -0,0 +1,77 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "pw_varint/varint.h"
+
+#define VARINT_ENCODE_FUNCTION_BODY(bits) \
+ size_t written = 0; \
+ uint8_t* buffer = (uint8_t*)output; \
+ \
+ do { \
+ if (written >= output_size_bytes) { \
+ return 0u; \
+ } \
+ buffer[written++] = pw_varint_EncodeOneByte##bits(&integer); \
+ } while (integer != 0u); \
+ \
+ buffer[written - 1] &= 0x7f; \
+ return written
+
+size_t pw_varint_Encode32(uint32_t integer,
+ void* output,
+ size_t output_size_bytes) {
+ VARINT_ENCODE_FUNCTION_BODY(32);
+}
+
+size_t pw_varint_Encode64(uint64_t integer,
+ void* output,
+ size_t output_size_bytes) {
+ VARINT_ENCODE_FUNCTION_BODY(64);
+}
+
+#define VARINT_DECODE_FUNCTION_BODY(bits) \
+ uint##bits##_t value = 0; \
+ size_t count = 0; \
+ const uint8_t* buffer = (const uint8_t*)(input); \
+ \
+ /* Only read to the end of the buffer or largest possible encoded size. */ \
+ const size_t max_count = \
+ input_size_bytes < PW_VARINT_MAX_INT##bits##_SIZE_BYTES \
+ ? input_size_bytes \
+ : PW_VARINT_MAX_INT##bits##_SIZE_BYTES; \
+ \
+ bool keep_going; \
+ do { \
+ if (count >= max_count) { \
+ return 0; \
+ } \
+ \
+ keep_going = pw_varint_DecodeOneByte##bits(buffer[count], count, &value); \
+ count += 1; \
+ } while (keep_going); \
+ \
+ *output = value; \
+ return count
+
+size_t pw_varint_Decode32(const void* input,
+ size_t input_size_bytes,
+ uint32_t* output) {
+ VARINT_DECODE_FUNCTION_BODY(32);
+}
+
+size_t pw_varint_Decode64(const void* input,
+ size_t input_size_bytes,
+ uint64_t* output) {
+ VARINT_DECODE_FUNCTION_BODY(64);
+}