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

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)