aboutsummaryrefslogtreecommitdiff
path: root/pw_varint/varint_c.c
blob: 9194b4e349cccbd6b601fdebb816f87dea4ab732 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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);
}