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

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)