Embedded SDK
Embedded SDK
varint.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * (c) 2020 Ledger SAS.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #include <stdint.h> // uint*_t
18 #include <stddef.h> // size_t
19 #include <stdbool.h> // bool
20 
21 #include "varint.h"
22 #include "write.h"
23 #include "read.h"
24 
25 uint8_t varint_size(uint64_t value)
26 {
27  if (value <= 0xFC) {
28  return 1;
29  }
30 
31  if (value <= UINT16_MAX) {
32  return 3;
33  }
34 
35  if (value <= UINT32_MAX) {
36  return 5;
37  }
38 
39  return 9; // <= UINT64_MAX
40 }
41 
42 int varint_read(const uint8_t *in, size_t in_len, uint64_t *value)
43 {
44  if (in_len < 1) {
45  return -1;
46  }
47 
48  uint8_t prefix = in[0];
49 
50  if (prefix == 0xFD) {
51  if (in_len < 3) {
52  return -1;
53  }
54  *value = (uint64_t) read_u16_le(in, 1);
55  return 3;
56  }
57 
58  if (prefix == 0xFE) {
59  if (in_len < 5) {
60  return -1;
61  }
62  *value = (uint64_t) read_u32_le(in, 1);
63  return 5;
64  }
65 
66  if (prefix == 0xFF) {
67  if (in_len < 9) {
68  return -1;
69  }
70  *value = (uint64_t) read_u64_le(in, 1);
71  return 9;
72  }
73 
74  *value = (uint64_t) prefix; // prefix <= 0xFC
75 
76  return 1;
77 }
78 
79 int varint_write(uint8_t *out, size_t offset, uint64_t value)
80 {
81  uint8_t varint_len = varint_size(value);
82 
83  switch (varint_len) {
84  case 1:
85  out[offset] = (uint8_t) value;
86  break;
87  case 3:
88  out[offset++] = 0xFD;
89  write_u16_le(out, offset, (uint16_t) value);
90  break;
91  case 5:
92  out[offset++] = 0xFE;
93  write_u32_le(out, offset, (uint32_t) value);
94  break;
95  case 9:
96  out[offset++] = 0xFF;
97  write_u64_le(out, offset, (uint64_t) value);
98  break;
99  default:
100  return -1;
101  }
102 
103  return varint_len;
104 }
uint32_t read_u32_le(const uint8_t *ptr, size_t offset)
Definition: read.c:52
uint64_t read_u64_le(const uint8_t *ptr, size_t offset)
Definition: read.c:60
uint16_t read_u16_le(const uint8_t *ptr, size_t offset)
Definition: read.c:46
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53
uint8_t varint_size(uint64_t value)
Definition: varint.c:25
int varint_write(uint8_t *out, size_t offset, uint64_t value)
Definition: varint.c:79
int varint_read(const uint8_t *in, size_t in_len, uint64_t *value)
Definition: varint.c:42
void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value)
Definition: write.c:46
void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value)
Definition: write.c:60
void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value)
Definition: write.c:52