Embedded SDK
Embedded SDK
format.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 <stddef.h> // size_t
18 #include <stdint.h> // int*_t, uint*_t
19 #include <string.h> // strncpy, memmove
20 #include <stdbool.h> // bool
21 
22 #include "format.h"
23 
24 bool format_i64(char *dst, size_t dst_len, const int64_t value)
25 {
26  char temp[] = "-9223372036854775808";
27 
28  char *ptr = temp;
29  int64_t num = value;
30  int sign = 1;
31 
32  if (value < 0) {
33  sign = -1;
34  }
35 
36  while (num != 0) {
37  *ptr++ = '0' + (num % 10) * sign;
38  num /= 10;
39  }
40 
41  if (value < 0) {
42  *ptr++ = '-';
43  }
44  else if (value == 0) {
45  *ptr++ = '0';
46  }
47 
48  int distance = (ptr - temp) + 1;
49 
50  if ((int) dst_len < distance) {
51  return false;
52  }
53 
54  size_t index = 0;
55 
56  while (--ptr >= temp) {
57  dst[index++] = *ptr;
58  }
59 
60  dst[index] = '\0';
61 
62  return true;
63 }
64 
65 bool format_u64(char *out, size_t outLen, uint64_t in)
66 {
67  size_t i = 0;
68 
69  if (outLen == 0) {
70  return false;
71  }
72  outLen--;
73 
74  while (in > 9) {
75  out[i] = in % 10 + '0';
76  in /= 10;
77  i++;
78  if (i + 1 > outLen) {
79  return false;
80  }
81  }
82  out[i] = in + '0';
83  out[i + 1] = '\0';
84 
85  uint8_t j = 0;
86  char tmp;
87 
88  // revert the string
89  while (j < i) {
90  // swap out[j] and out[i]
91  tmp = out[j];
92  out[j] = out[i];
93  out[i] = tmp;
94 
95  i--;
96  j++;
97  }
98  return true;
99 }
100 
101 bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals)
102 {
103  char buffer[21] = {0};
104 
105  if (!format_u64(buffer, sizeof(buffer), value)) {
106  return false;
107  }
108 
109  size_t digits = strlen(buffer);
110 
111  if (digits <= decimals) {
112  if (dst_len <= 2 + decimals - digits) {
113  return false;
114  }
115  *dst++ = '0';
116  *dst++ = '.';
117  for (uint16_t i = 0; i < decimals - digits; i++, dst++) {
118  *dst = '0';
119  }
120  dst_len -= 2 + decimals - digits;
121  strncpy(dst, buffer, dst_len);
122  }
123  else {
124  if (dst_len <= digits + 1 + decimals) {
125  return false;
126  }
127 
128  const size_t shift = digits - decimals;
129  memmove(dst, buffer, shift);
130  dst[shift] = '.';
131  strncpy(dst + shift + 1, buffer + shift, decimals);
132  }
133 
134  return true;
135 }
136 
137 bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals)
138 {
139  if (!format_fpu64(dst, dst_len, value, decimals)) {
140  return false;
141  }
142 
143  size_t len = strlen(dst);
144 
145  while (len > 0 && (dst[len - 1] == '0' || dst[len - 1] == '.')) {
146  if (dst[len - 1] == '.') {
147  dst[len - 1] = '\0';
148  return true;
149  }
150  len--;
151  }
152  dst[len] = '\0';
153  return true;
154 }
155 
156 int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len)
157 {
158  if (out_len < 2 * in_len + 1) {
159  return -1;
160  }
161 
162  const char hex[] = "0123456789ABCDEF";
163  size_t i = 0;
164  int written = 0;
165 
166  while (i < in_len && (i * 2 + (2 + 1)) <= out_len) {
167  uint8_t high_nibble = (in[i] & 0xF0) >> 4;
168  *out = hex[high_nibble];
169  out++;
170 
171  uint8_t low_nibble = in[i] & 0x0F;
172  *out = hex[low_nibble];
173  out++;
174 
175  i++;
176  written += 2;
177  }
178 
179  *out = '\0';
180 
181  return written + 1;
182 }
bool format_u64(char *out, size_t outLen, uint64_t in)
Definition: format.c:65
int format_hex(const uint8_t *in, size_t in_len, char *out, size_t out_len)
Definition: format.c:156
bool format_fpu64_trimmed(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals)
Definition: format.c:137
bool format_i64(char *dst, size_t dst_len, const int64_t value)
Definition: format.c:24
bool format_fpu64(char *dst, size_t dst_len, const uint64_t value, uint8_t decimals)
Definition: format.c:101
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53