improve buf_cpy helper
[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 void* buf_cpy(const void *from, void *_to, unsigned size)
52 {
53 if (NULL == from || NULL == _to)
54 return NULL;
55
56 // copy entire buffer
57 memcpy(_to, from, CEIL(size, 8));
58
59 /* mask out bits that don't belong to the buffer */
60 unsigned trailing_bits = size % 8;
61 if (trailing_bits)
62 {
63 uint8_t *to = _to;
64 to[size / 8] &= (1 << trailing_bits) - 1;
65 }
66 return _to;
67 }
68
69 static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
70 {
71 return (a & m) != (b & m);
72 }
73 static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
74 {
75 uint8_t mask = (1 << trailing) - 1;
76 return buf_cmp_masked(a, b, mask & m);
77 }
78
79 bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
80 {
81 if (!_buf1 || !_buf2)
82 return _buf1 != _buf2;
83
84 unsigned last = size / 8;
85 if (memcmp(_buf1, _buf2, last) != 0)
86 return false;
87
88 unsigned trailing = size % 8;
89 if (!trailing)
90 return false;
91
92 const uint8_t *buf1 = _buf1, *buf2 = _buf2;
93 return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
94 }
95
96 bool buf_cmp_mask(const void *_buf1, const void *_buf2,
97 const void *_mask, unsigned size)
98 {
99 if (!_buf1 || !_buf2)
100 return _buf1 != _buf2 || _buf1 != _mask;
101
102 const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
103 unsigned last = size / 8;
104 for (unsigned i = 0; i < last; i++)
105 {
106 if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
107 return true;
108 }
109 unsigned trailing = size % 8;
110 if (!trailing)
111 return false;
112 return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
113 }
114
115
116 uint8_t* buf_set_ones(uint8_t *buf, int count)
117 {
118 for (unsigned i = 0, num_bytes = CEIL(count, 8); i < num_bytes; i++)
119 {
120 if (count >= 8)
121 buf[i] = 0xff;
122 else
123 buf[i] = (1 << count) - 1;
124
125 count -= 8;
126 }
127
128 return buf;
129 }
130
131 uint8_t* buf_set_buf(const uint8_t *src, int src_start, uint8_t *dst, int dst_start, int len)
132 {
133 int src_idx = src_start, dst_idx = dst_start;
134
135 for (int i = 0; i < len; i++)
136 {
137 if (((src[src_idx / 8] >> (src_idx % 8)) & 1) == 1)
138 dst[dst_idx / 8] |= 1 << (dst_idx % 8);
139 else
140 dst[dst_idx / 8] &= ~(1 << (dst_idx % 8));
141 dst_idx++;
142 src_idx++;
143 }
144
145 return dst;
146 }
147
148 uint32_t flip_u32(uint32_t value, unsigned int num)
149 {
150 uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
151 (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
152 (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
153 (bit_reverse_table256[(value >> 24) & 0xff]);
154
155 if (num < 32)
156 c = c >> (32 - num);
157
158 return c;
159 }
160
161 int ceil_f_to_u32(float x)
162 {
163 if (x < 0) /* return zero for negative numbers */
164 return 0;
165
166 uint32_t y = x; /* cut off fraction */
167
168 if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
169 y++;
170
171 return y;
172 }
173
174 char* buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
175 {
176 float factor;
177 switch (radix) {
178 case 16:
179 factor = 2.0; /* log(256) / log(16) = 2.0 */
180 break;
181 case 10:
182 factor = 2.40824; /* log(256) / log(10) = 2.40824 */
183 break;
184 case 8:
185 factor = 2.66667; /* log(256) / log(8) = 2.66667 */
186 break;
187 default:
188 return NULL;
189 }
190
191 unsigned str_len = ceil_f_to_u32(CEIL(buf_len, 8) * factor);
192 char *str = calloc(str_len + 1, 1);
193
194 const uint8_t *buf = _buf;
195 int b256_len = CEIL(buf_len, 8);
196 for (int i = b256_len - 1; i >= 0; i--)
197 {
198 uint32_t tmp = buf[i];
199 if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
200 tmp &= (0xff >> (8 - (buf_len % 8)));
201
202 /* base-256 digits */
203 for (unsigned j = str_len; j > 0; j--)
204 {
205 tmp += (uint32_t)str[j-1] * 256;
206 str[j-1] = (uint8_t)(tmp % radix);
207 tmp /= radix;
208 }
209 }
210
211 const char *DIGITS = "0123456789ABCDEF";
212 for (unsigned j = 0; j < str_len; j++)
213 str[j] = DIGITS[(int)str[j]];
214
215 return str;
216 }
217
218 /// identify radix, and skip radix-prefix (0, 0x or 0X)
219 static void str_radix_guess(const char **_str, unsigned *_str_len,
220 unsigned *_radix)
221 {
222 unsigned radix = *_radix;
223 if (0 != radix)
224 return;
225 const char *str = *_str;
226 unsigned str_len = *_str_len;
227 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
228 {
229 radix = 16;
230 str += 2;
231 str_len -= 2;
232 }
233 else if ((str[0] == '0') && (str_len != 1))
234 {
235 radix = 8;
236 str += 1;
237 str_len -= 1;
238 }
239 else
240 {
241 radix = 10;
242 }
243 *_str = str;
244 *_str_len = str_len;
245 *_radix = radix;
246 }
247
248 int str_to_buf(const char *str, unsigned str_len,
249 void *_buf, unsigned buf_len, unsigned radix)
250 {
251 str_radix_guess(&str, &str_len, &radix);
252
253 float factor;
254 if (radix == 16)
255 factor = 0.5; /* log(16) / log(256) = 0.5 */
256 else if (radix == 10)
257 factor = 0.41524; /* log(10) / log(256) = 0.41524 */
258 else if (radix == 8)
259 factor = 0.375; /* log(8) / log(256) = 0.375 */
260 else
261 return 0;
262
263 /* copy to zero-terminated buffer */
264 char *charbuf = malloc(str_len + 1);
265 memcpy(charbuf, str, str_len);
266 charbuf[str_len] = '\0';
267
268 /* number of digits in base-256 notation */
269 unsigned b256_len = ceil_f_to_u32(str_len * factor);
270 uint8_t *b256_buf = calloc(b256_len, 1);
271
272 /* go through zero terminated buffer */
273 /* input digits (ASCII) */
274 unsigned i;
275 for (i = 0; charbuf[i]; i++)
276 {
277 uint32_t tmp = charbuf[i];
278 if ((tmp >= '0') && (tmp <= '9'))
279 tmp = (tmp - '0');
280 else if ((tmp >= 'a') && (tmp <= 'f'))
281 tmp = (tmp - 'a' + 10);
282 else if ((tmp >= 'A') && (tmp <= 'F'))
283 tmp = (tmp - 'A' + 10);
284 else continue; /* skip characters other than [0-9,a-f,A-F] */
285
286 if (tmp >= radix)
287 continue; /* skip digits invalid for the current radix */
288
289 /* base-256 digits */
290 for (unsigned j = 0; j < b256_len; j++)
291 {
292 tmp += (uint32_t)b256_buf[j] * radix;
293 b256_buf[j] = (uint8_t)(tmp & 0xFF);
294 tmp >>= 8;
295 }
296
297 }
298
299 uint8_t *buf = _buf;
300 for (unsigned j = 0; j < CEIL(buf_len, 8); j++)
301 {
302 if (j < b256_len)
303 buf[j] = b256_buf[j];
304 else
305 buf[j] = 0;
306 }
307
308 /* mask out bits that don't belong to the buffer */
309 if (buf_len % 8)
310 buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
311
312 free(b256_buf);
313 free(charbuf);
314
315 return i;
316 }

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)