improve buf_set_buf 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 void* buf_set_ones(void *_buf, unsigned size)
117 {
118 uint8_t *buf = _buf;
119 if (!buf)
120 return NULL;
121
122 memset(buf, 0xff, size / 8);
123
124 unsigned trailing_bits = size % 8;
125 if (trailing_bits)
126 buf[size / 8] = (1 << trailing_bits) - 1;
127
128 return buf;
129 }
130
131 void* buf_set_buf(const void *_src, unsigned src_start,
132 void *_dst, unsigned dst_start, unsigned len)
133 {
134 const uint8_t *src = _src;
135 uint8_t *dst = _dst;
136
137 unsigned src_idx = src_start, dst_idx = dst_start;
138 for (unsigned i = 0; i < len; i++)
139 {
140 if (((src[src_idx / 8] >> (src_idx % 8)) & 1) == 1)
141 dst[dst_idx / 8] |= 1 << (dst_idx % 8);
142 else
143 dst[dst_idx / 8] &= ~(1 << (dst_idx % 8));
144 dst_idx++;
145 src_idx++;
146 }
147
148 return dst;
149 }
150
151 uint32_t flip_u32(uint32_t value, unsigned int num)
152 {
153 uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
154 (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
155 (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
156 (bit_reverse_table256[(value >> 24) & 0xff]);
157
158 if (num < 32)
159 c = c >> (32 - num);
160
161 return c;
162 }
163
164 int ceil_f_to_u32(float x)
165 {
166 if (x < 0) /* return zero for negative numbers */
167 return 0;
168
169 uint32_t y = x; /* cut off fraction */
170
171 if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
172 y++;
173
174 return y;
175 }
176
177 char* buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
178 {
179 float factor;
180 switch (radix) {
181 case 16:
182 factor = 2.0; /* log(256) / log(16) = 2.0 */
183 break;
184 case 10:
185 factor = 2.40824; /* log(256) / log(10) = 2.40824 */
186 break;
187 case 8:
188 factor = 2.66667; /* log(256) / log(8) = 2.66667 */
189 break;
190 default:
191 return NULL;
192 }
193
194 unsigned str_len = ceil_f_to_u32(CEIL(buf_len, 8) * factor);
195 char *str = calloc(str_len + 1, 1);
196
197 const uint8_t *buf = _buf;
198 int b256_len = CEIL(buf_len, 8);
199 for (int i = b256_len - 1; i >= 0; i--)
200 {
201 uint32_t tmp = buf[i];
202 if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
203 tmp &= (0xff >> (8 - (buf_len % 8)));
204
205 /* base-256 digits */
206 for (unsigned j = str_len; j > 0; j--)
207 {
208 tmp += (uint32_t)str[j-1] * 256;
209 str[j-1] = (uint8_t)(tmp % radix);
210 tmp /= radix;
211 }
212 }
213
214 const char *DIGITS = "0123456789ABCDEF";
215 for (unsigned j = 0; j < str_len; j++)
216 str[j] = DIGITS[(int)str[j]];
217
218 return str;
219 }
220
221 /// identify radix, and skip radix-prefix (0, 0x or 0X)
222 static void str_radix_guess(const char **_str, unsigned *_str_len,
223 unsigned *_radix)
224 {
225 unsigned radix = *_radix;
226 if (0 != radix)
227 return;
228 const char *str = *_str;
229 unsigned str_len = *_str_len;
230 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
231 {
232 radix = 16;
233 str += 2;
234 str_len -= 2;
235 }
236 else if ((str[0] == '0') && (str_len != 1))
237 {
238 radix = 8;
239 str += 1;
240 str_len -= 1;
241 }
242 else
243 {
244 radix = 10;
245 }
246 *_str = str;
247 *_str_len = str_len;
248 *_radix = radix;
249 }
250
251 int str_to_buf(const char *str, unsigned str_len,
252 void *_buf, unsigned buf_len, unsigned radix)
253 {
254 str_radix_guess(&str, &str_len, &radix);
255
256 float factor;
257 if (radix == 16)
258 factor = 0.5; /* log(16) / log(256) = 0.5 */
259 else if (radix == 10)
260 factor = 0.41524; /* log(10) / log(256) = 0.41524 */
261 else if (radix == 8)
262 factor = 0.375; /* log(8) / log(256) = 0.375 */
263 else
264 return 0;
265
266 /* copy to zero-terminated buffer */
267 char *charbuf = malloc(str_len + 1);
268 memcpy(charbuf, str, str_len);
269 charbuf[str_len] = '\0';
270
271 /* number of digits in base-256 notation */
272 unsigned b256_len = ceil_f_to_u32(str_len * factor);
273 uint8_t *b256_buf = calloc(b256_len, 1);
274
275 /* go through zero terminated buffer */
276 /* input digits (ASCII) */
277 unsigned i;
278 for (i = 0; charbuf[i]; i++)
279 {
280 uint32_t tmp = charbuf[i];
281 if ((tmp >= '0') && (tmp <= '9'))
282 tmp = (tmp - '0');
283 else if ((tmp >= 'a') && (tmp <= 'f'))
284 tmp = (tmp - 'a' + 10);
285 else if ((tmp >= 'A') && (tmp <= 'F'))
286 tmp = (tmp - 'A' + 10);
287 else continue; /* skip characters other than [0-9,a-f,A-F] */
288
289 if (tmp >= radix)
290 continue; /* skip digits invalid for the current radix */
291
292 /* base-256 digits */
293 for (unsigned j = 0; j < b256_len; j++)
294 {
295 tmp += (uint32_t)b256_buf[j] * radix;
296 b256_buf[j] = (uint8_t)(tmp & 0xFF);
297 tmp >>= 8;
298 }
299
300 }
301
302 uint8_t *buf = _buf;
303 for (unsigned j = 0; j < CEIL(buf_len, 8); j++)
304 {
305 if (j < b256_len)
306 buf[j] = b256_buf[j];
307 else
308 buf[j] = 0;
309 }
310
311 /* mask out bits that don't belong to the buffer */
312 if (buf_len % 8)
313 buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
314
315 free(b256_buf);
316 free(charbuf);
317
318 return i;
319 }

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)