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

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)