improve str_to_buf and buf_to_str helpers
[openocd.git] / src / helper / binarybuffer.c
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "log.h"
28 #include "binarybuffer.h"
29
30 const unsigned char bit_reverse_table256[] =
31 {
32 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
33 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
34 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
35 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
36 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
37 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
38 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
39 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
40 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
41 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
42 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
43 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
44 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
45 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
46 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
47 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
48 };
49
50
51 uint8_t* buf_cpy(const uint8_t *from, uint8_t *to, int size)
52 {
53 if (from == NULL)
54 return NULL;
55
56 for (unsigned i = 0, num_bytes = CEIL(size, 8); i < num_bytes; i++)
57 to[i] = from[i];
58
59 /* mask out bits that don't belong to the buffer */
60 if (size % 8)
61 {
62 to[size / 8] &= (0xff >> (8 - (size % 8)));
63 }
64
65 return to;
66 }
67
68 int buf_cmp(const uint8_t *buf1, const uint8_t *buf2, int size)
69 {
70 if (!buf1 || !buf2)
71 return 1;
72
73 for (unsigned i = 0, num_bytes = CEIL(size, 8); i < num_bytes; i++)
74 {
75 /* last byte */
76 /* mask out bits that don't really belong to the buffer if size isn't a multiple of 8 bits */
77 if ((size % 8) && (i == num_bytes -1))
78 {
79 if ((buf1[i] & ((1 << (size % 8)) - 1)) != (buf2[i] & ((1 << (size % 8)) - 1)))
80 return 1;
81 }
82 else
83 {
84 if (buf1[i] != buf2[i])
85 return 1;
86 }
87 }
88
89 return 0;
90 }
91
92 int buf_cmp_mask(const uint8_t *buf1, const uint8_t *buf2, const uint8_t *mask, int size)
93 {
94 for (unsigned i = 0, num_bytes = CEIL(size, 8); i < num_bytes; i++)
95 {
96 /* last byte */
97 /* mask out bits that don't really belong to the buffer if size isn't a multiple of 8 bits */
98 if ((size % 8) && (i == num_bytes -1))
99 {
100 if ((buf1[i] & ((1 << (size % 8)) - 1) & mask[i]) !=
101 (buf2[i] & ((1 << (size % 8)) - 1) & mask[i]))
102 return 1;
103 }
104 else
105 {
106 if ((buf1[i] & mask[i]) != (buf2[i] & mask[i]))
107 return 1;
108 }
109 }
110
111 return 0;
112 }
113
114 uint8_t* buf_set_ones(uint8_t *buf, int count)
115 {
116 for (unsigned i = 0, num_bytes = CEIL(count, 8); i < num_bytes; i++)
117 {
118 if (count >= 8)
119 buf[i] = 0xff;
120 else
121 buf[i] = (1 << count) - 1;
122
123 count -= 8;
124 }
125
126 return buf;
127 }
128
129 uint8_t* buf_set_buf(const uint8_t *src, int src_start, uint8_t *dst, int dst_start, int len)
130 {
131 int src_idx = src_start, dst_idx = dst_start;
132
133 for (int i = 0; i < len; i++)
134 {
135 if (((src[src_idx / 8] >> (src_idx % 8)) & 1) == 1)
136 dst[dst_idx / 8] |= 1 << (dst_idx % 8);
137 else
138 dst[dst_idx / 8] &= ~(1 << (dst_idx % 8));
139 dst_idx++;
140 src_idx++;
141 }
142
143 return dst;
144 }
145
146 uint32_t flip_u32(uint32_t value, unsigned int num)
147 {
148 uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
149 (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
150 (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
151 (bit_reverse_table256[(value >> 24) & 0xff]);
152
153 if (num < 32)
154 c = c >> (32 - num);
155
156 return c;
157 }
158
159 int ceil_f_to_u32(float x)
160 {
161 if (x < 0) /* return zero for negative numbers */
162 return 0;
163
164 uint32_t y = x; /* cut off fraction */
165
166 if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
167 y++;
168
169 return y;
170 }
171
172 char* buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
173 {
174 float factor;
175 switch (radix) {
176 case 16:
177 factor = 2.0; /* log(256) / log(16) = 2.0 */
178 break;
179 case 10:
180 factor = 2.40824; /* log(256) / log(10) = 2.40824 */
181 break;
182 case 8:
183 factor = 2.66667; /* log(256) / log(8) = 2.66667 */
184 break;
185 default:
186 return NULL;
187 }
188
189 unsigned str_len = ceil_f_to_u32(CEIL(buf_len, 8) * factor);
190 char *str = calloc(str_len + 1, 1);
191
192 const uint8_t *buf = _buf;
193 int b256_len = CEIL(buf_len, 8);
194 for (int i = b256_len - 1; i >= 0; i--)
195 {
196 uint32_t tmp = buf[i];
197 if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
198 tmp &= (0xff >> (8 - (buf_len % 8)));
199
200 /* base-256 digits */
201 for (unsigned j = str_len; j > 0; j--)
202 {
203 tmp += (uint32_t)str[j-1] * 256;
204 str[j-1] = (uint8_t)(tmp % radix);
205 tmp /= radix;
206 }
207 }
208
209 const char *DIGITS = "0123456789ABCDEF";
210 for (unsigned j = 0; j < str_len; j++)
211 str[j] = DIGITS[(int)str[j]];
212
213 return str;
214 }
215
216 /// identify radix, and skip radix-prefix (0, 0x or 0X)
217 static void str_radix_guess(const char **_str, unsigned *_str_len,
218 unsigned *_radix)
219 {
220 unsigned radix = *_radix;
221 if (0 != radix)
222 return;
223 const char *str = *_str;
224 unsigned str_len = *_str_len;
225 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
226 {
227 radix = 16;
228 str += 2;
229 str_len -= 2;
230 }
231 else if ((str[0] == '0') && (str_len != 1))
232 {
233 radix = 8;
234 str += 1;
235 str_len -= 1;
236 }
237 else
238 {
239 radix = 10;
240 }
241 *_str = str;
242 *_str_len = str_len;
243 *_radix = radix;
244 }
245
246 int str_to_buf(const char *str, unsigned str_len,
247 void *_buf, unsigned buf_len, unsigned radix)
248 {
249 str_radix_guess(&str, &str_len, &radix);
250
251 float factor;
252 if (radix == 16)
253 factor = 0.5; /* log(16) / log(256) = 0.5 */
254 else if (radix == 10)
255 factor = 0.41524; /* log(10) / log(256) = 0.41524 */
256 else if (radix == 8)
257 factor = 0.375; /* log(8) / log(256) = 0.375 */
258 else
259 return 0;
260
261 /* copy to zero-terminated buffer */
262 char *charbuf = malloc(str_len + 1);
263 memcpy(charbuf, str, str_len);
264 charbuf[str_len] = '\0';
265
266 /* number of digits in base-256 notation */
267 unsigned b256_len = ceil_f_to_u32(str_len * factor);
268 uint8_t *b256_buf = calloc(b256_len, 1);
269
270 /* go through zero terminated buffer */
271 /* input digits (ASCII) */
272 unsigned i;
273 for (i = 0; charbuf[i]; i++)
274 {
275 uint32_t tmp = charbuf[i];
276 if ((tmp >= '0') && (tmp <= '9'))
277 tmp = (tmp - '0');
278 else if ((tmp >= 'a') && (tmp <= 'f'))
279 tmp = (tmp - 'a' + 10);
280 else if ((tmp >= 'A') && (tmp <= 'F'))
281 tmp = (tmp - 'A' + 10);
282 else continue; /* skip characters other than [0-9,a-f,A-F] */
283
284 if (tmp >= radix)
285 continue; /* skip digits invalid for the current radix */
286
287 /* base-256 digits */
288 for (unsigned j = 0; j < b256_len; j++)
289 {
290 tmp += (uint32_t)b256_buf[j] * radix;
291 b256_buf[j] = (uint8_t)(tmp & 0xFF);
292 tmp >>= 8;
293 }
294
295 }
296
297 uint8_t *buf = _buf;
298 for (unsigned j = 0; j < CEIL(buf_len, 8); j++)
299 {
300 if (j < b256_len)
301 buf[j] = b256_buf[j];
302 else
303 buf[j] = 0;
304 }
305
306 /* mask out bits that don't belong to the buffer */
307 if (buf_len % 8)
308 buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
309
310 free(b256_buf);
311 free(charbuf);
312
313 return i;
314 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)