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

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)