blob: 59396d7bed84334d644857b368b654b49440c90c [file] [log] [blame]
njn97405b22005-06-02 03:39:33 +00001
2/*--------------------------------------------------------------------*/
3/*--- Entirely standalone libc stuff. m_libcbase.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 Julian Seward
njn97405b22005-06-02 03:39:33 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njn97405b22005-06-02 03:39:33 +000032#include "pub_core_libcbase.h"
33
34/* ---------------------------------------------------------------------
florian19f91bb2012-11-10 22:29:54 +000035 HChar functions.
njn97405b22005-06-02 03:39:33 +000036 ------------------------------------------------------------------ */
37
florian19f91bb2012-11-10 22:29:54 +000038Bool VG_(isspace) ( HChar c )
njn97405b22005-06-02 03:39:33 +000039{
40 return (c == ' ' || c == '\n' || c == '\t' ||
41 c == '\f' || c == '\v' || c == '\r');
42}
43
florian19f91bb2012-11-10 22:29:54 +000044Bool VG_(isdigit) ( HChar c )
njn97405b22005-06-02 03:39:33 +000045{
46 return (c >= '0' && c <= '9');
47}
48
49/* ---------------------------------------------------------------------
50 Converting strings to numbers
51 ------------------------------------------------------------------ */
52
florian19f91bb2012-11-10 22:29:54 +000053static Bool is_dec_digit(HChar c, Long* digit)
njnea5d2352007-11-11 21:58:21 +000054{
55 if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; }
56 return False;
57}
58
florian19f91bb2012-11-10 22:29:54 +000059static Bool is_hex_digit(HChar c, Long* digit)
njnea5d2352007-11-11 21:58:21 +000060{
61 if (c >= '0' && c <= '9') { *digit = (Long)(c - '0'); return True; }
62 if (c >= 'A' && c <= 'F') { *digit = (Long)((c - 'A') + 10); return True; }
63 if (c >= 'a' && c <= 'f') { *digit = (Long)((c - 'a') + 10); return True; }
64 return False;
65}
66
florian19f91bb2012-11-10 22:29:54 +000067Long VG_(strtoll10) ( const HChar* str, HChar** endptr )
njnea5d2352007-11-11 21:58:21 +000068{
njn8a0b7042009-02-20 06:10:44 +000069 Bool neg = False, converted = False;
njn7d9b3af2007-11-20 07:04:36 +000070 Long n = 0, digit = 0;
florian19f91bb2012-11-10 22:29:54 +000071 const HChar* str0 = str;
njnea5d2352007-11-11 21:58:21 +000072
73 // Skip leading whitespace.
74 while (VG_(isspace)(*str)) str++;
75
76 // Allow a leading '-' or '+'.
77 if (*str == '-') { str++; neg = True; }
78 else if (*str == '+') { str++; }
79
80 while (is_dec_digit(*str, &digit)) {
njn8a0b7042009-02-20 06:10:44 +000081 converted = True; // Ok, we've actually converted a digit.
njnea5d2352007-11-11 21:58:21 +000082 n = 10*n + digit;
83 str++;
84 }
85
njn8a0b7042009-02-20 06:10:44 +000086 if (!converted) str = str0; // If nothing converted, endptr points to
87 if (neg) n = -n; // the start of the string.
florian19f91bb2012-11-10 22:29:54 +000088 if (endptr) *endptr = (HChar *)str; // Record first failing character.
njnea5d2352007-11-11 21:58:21 +000089 return n;
90}
91
florian19f91bb2012-11-10 22:29:54 +000092ULong VG_(strtoull10) ( const HChar* str, HChar** endptr )
sewardj3b290482011-05-06 21:02:55 +000093{
94 Bool converted = False;
95 ULong n = 0;
96 Long digit = 0;
florian19f91bb2012-11-10 22:29:54 +000097 const HChar* str0 = str;
sewardj3b290482011-05-06 21:02:55 +000098
99 // Skip leading whitespace.
100 while (VG_(isspace)(*str)) str++;
101
102 // Allow a leading '+'.
103 if (*str == '+') { str++; }
104
105 while (is_dec_digit(*str, &digit)) {
106 converted = True; // Ok, we've actually converted a digit.
107 n = 10*n + digit;
108 str++;
109 }
110
111 if (!converted) str = str0; // If nothing converted, endptr points to
112 // the start of the string.
florian19f91bb2012-11-10 22:29:54 +0000113 if (endptr) *endptr = (HChar *)str; // Record first failing character.
sewardj3b290482011-05-06 21:02:55 +0000114 return n;
115}
116
florian19f91bb2012-11-10 22:29:54 +0000117Long VG_(strtoll16) ( const HChar* str, HChar** endptr )
njnea5d2352007-11-11 21:58:21 +0000118{
njn8a0b7042009-02-20 06:10:44 +0000119 Bool neg = False, converted = False;
njn7d9b3af2007-11-20 07:04:36 +0000120 Long n = 0, digit = 0;
florian19f91bb2012-11-10 22:29:54 +0000121 const HChar* str0 = str;
njnea5d2352007-11-11 21:58:21 +0000122
123 // Skip leading whitespace.
124 while (VG_(isspace)(*str)) str++;
125
126 // Allow a leading '-' or '+'.
127 if (*str == '-') { str++; neg = True; }
128 else if (*str == '+') { str++; }
129
130 // Allow leading "0x", but only if there's a hex digit
131 // following it.
132 if (*str == '0'
133 && (*(str+1) == 'x' || *(str+1) == 'X')
134 && is_hex_digit( *(str+2), &digit )) {
135 str += 2;
136 }
137
138 while (is_hex_digit(*str, &digit)) {
njn8a0b7042009-02-20 06:10:44 +0000139 converted = True; // Ok, we've actually converted a digit.
njnea5d2352007-11-11 21:58:21 +0000140 n = 16*n + digit;
141 str++;
142 }
143
njn8a0b7042009-02-20 06:10:44 +0000144 if (!converted) str = str0; // If nothing converted, endptr points to
145 if (neg) n = -n; // the start of the string.
florian19f91bb2012-11-10 22:29:54 +0000146 if (endptr) *endptr = (HChar *)str; // Record first failing character.
njnea5d2352007-11-11 21:58:21 +0000147 return n;
148}
149
florian19f91bb2012-11-10 22:29:54 +0000150ULong VG_(strtoull16) ( const HChar* str, HChar** endptr )
sewardj3b290482011-05-06 21:02:55 +0000151{
152 Bool converted = False;
153 ULong n = 0;
154 Long digit = 0;
florian19f91bb2012-11-10 22:29:54 +0000155 const HChar* str0 = str;
sewardj3b290482011-05-06 21:02:55 +0000156
157 // Skip leading whitespace.
158 while (VG_(isspace)(*str)) str++;
159
160 // Allow a leading '+'.
161 if (*str == '+') { str++; }
162
163 // Allow leading "0x", but only if there's a hex digit
164 // following it.
165 if (*str == '0'
166 && (*(str+1) == 'x' || *(str+1) == 'X')
167 && is_hex_digit( *(str+2), &digit )) {
168 str += 2;
169 }
170
171 while (is_hex_digit(*str, &digit)) {
172 converted = True; // Ok, we've actually converted a digit.
173 n = 16*n + digit;
174 str++;
175 }
176
177 if (!converted) str = str0; // If nothing converted, endptr points to
178 // the start of the string.
florian19f91bb2012-11-10 22:29:54 +0000179 if (endptr) *endptr = (HChar *)str; // Record first failing character.
sewardj3b290482011-05-06 21:02:55 +0000180 return n;
181}
182
florian19f91bb2012-11-10 22:29:54 +0000183double VG_(strtod) ( const HChar* str, HChar** endptr )
njnea5d2352007-11-11 21:58:21 +0000184{
185 Bool neg = False;
186 Long digit;
187 double n = 0, frac = 0, x = 0.1;
188
189 // Skip leading whitespace.
190 while (VG_(isspace)(*str)) str++;
191
192 // Allow a leading '-' or '+'.
193 if (*str == '-') { str++; neg = True; }
194 else if (*str == '+') { str++; }
195
196 while (is_dec_digit(*str, &digit)) {
197 n = 10*n + digit;
198 str++;
199 }
200
201 if (*str == '.') {
202 str++;
203 while (is_dec_digit(*str, &digit)) {
204 frac += x*digit;
205 x /= 10;
206 str++;
207 }
208 }
209
210 n += frac;
211 if (neg) n = -n;
florian19f91bb2012-11-10 22:29:54 +0000212 if (endptr) *endptr = (HChar *)str; // Record first failing character.
njnea5d2352007-11-11 21:58:21 +0000213 return n;
214}
215
florian19f91bb2012-11-10 22:29:54 +0000216HChar VG_(tolower) ( HChar c )
njnf76d27a2009-05-28 01:53:07 +0000217{
218 if ( c >= 'A' && c <= 'Z' ) {
219 return c - 'A' + 'a';
220 } else {
221 return c;
222 }
223}
224
njn97405b22005-06-02 03:39:33 +0000225/* ---------------------------------------------------------------------
226 String functions
227 ------------------------------------------------------------------ */
228
florian19f91bb2012-11-10 22:29:54 +0000229SizeT VG_(strlen) ( const HChar* str )
njn97405b22005-06-02 03:39:33 +0000230{
sewardj4f2683a2008-10-26 11:53:30 +0000231 SizeT i = 0;
njn97405b22005-06-02 03:39:33 +0000232 while (str[i] != 0) i++;
233 return i;
234}
235
florian19f91bb2012-11-10 22:29:54 +0000236HChar* VG_(strcat) ( HChar* dest, const HChar* src )
njn97405b22005-06-02 03:39:33 +0000237{
florian19f91bb2012-11-10 22:29:54 +0000238 HChar* dest_orig = dest;
njn97405b22005-06-02 03:39:33 +0000239 while (*dest) dest++;
240 while (*src) *dest++ = *src++;
241 *dest = 0;
242 return dest_orig;
243}
244
florian19f91bb2012-11-10 22:29:54 +0000245HChar* VG_(strncat) ( HChar* dest, const HChar* src, SizeT n )
njn97405b22005-06-02 03:39:33 +0000246{
florian19f91bb2012-11-10 22:29:54 +0000247 HChar* dest_orig = dest;
njn97405b22005-06-02 03:39:33 +0000248 while (*dest) dest++;
249 while (*src && n > 0) { *dest++ = *src++; n--; }
250 *dest = 0;
251 return dest_orig;
252}
253
florian19f91bb2012-11-10 22:29:54 +0000254HChar* VG_(strpbrk) ( const HChar* s, const HChar* accpt )
njn97405b22005-06-02 03:39:33 +0000255{
florian19f91bb2012-11-10 22:29:54 +0000256 const HChar* a;
njn97405b22005-06-02 03:39:33 +0000257 while (*s) {
njnf9dcb3b2009-05-19 05:50:34 +0000258 a = accpt;
njn97405b22005-06-02 03:39:33 +0000259 while (*a)
260 if (*a++ == *s)
florian19f91bb2012-11-10 22:29:54 +0000261 return (HChar *)s;
njn97405b22005-06-02 03:39:33 +0000262 s++;
263 }
264 return NULL;
265}
266
florian19f91bb2012-11-10 22:29:54 +0000267HChar* VG_(strcpy) ( HChar* dest, const HChar* src )
njn97405b22005-06-02 03:39:33 +0000268{
florian19f91bb2012-11-10 22:29:54 +0000269 HChar* dest_orig = dest;
njn97405b22005-06-02 03:39:33 +0000270 while (*src) *dest++ = *src++;
271 *dest = 0;
272 return dest_orig;
273}
274
275/* Copy bytes, not overrunning the end of dest and always ensuring
276 zero termination. */
florian19f91bb2012-11-10 22:29:54 +0000277void VG_(strncpy_safely) ( HChar* dest, const HChar* src, SizeT ndest )
njn97405b22005-06-02 03:39:33 +0000278{
sewardj4f2683a2008-10-26 11:53:30 +0000279 SizeT i = 0;
njn97405b22005-06-02 03:39:33 +0000280 while (True) {
281 dest[i] = 0;
282 if (src[i] == 0) return;
283 if (i >= ndest-1) return;
284 dest[i] = src[i];
285 i++;
286 }
287}
288
florian19f91bb2012-11-10 22:29:54 +0000289HChar* VG_(strncpy) ( HChar* dest, const HChar* src, SizeT ndest )
njn97405b22005-06-02 03:39:33 +0000290{
sewardj4f2683a2008-10-26 11:53:30 +0000291 SizeT i = 0;
njn97405b22005-06-02 03:39:33 +0000292 while (True) {
293 if (i >= ndest) return dest; /* reached limit */
294 dest[i] = src[i];
295 if (src[i++] == 0) {
296 /* reached NUL; pad rest with zeroes as required */
297 while (i < ndest) dest[i++] = 0;
298 return dest;
299 }
300 }
301}
302
florian19f91bb2012-11-10 22:29:54 +0000303Int VG_(strcmp) ( const HChar* s1, const HChar* s2 )
njn97405b22005-06-02 03:39:33 +0000304{
305 while (True) {
florian3e798632012-11-24 19:41:54 +0000306 if (*(const UChar*)s1 < *(const UChar*)s2) return -1;
307 if (*(const UChar*)s1 > *(const UChar*)s2) return 1;
njn97405b22005-06-02 03:39:33 +0000308
philippe56ddd5b2012-07-26 22:44:07 +0000309 /* *s1 == *s2 */
310 if (*s1 == 0) return 0;
311
njn97405b22005-06-02 03:39:33 +0000312 s1++; s2++;
313 }
314}
315
florian19f91bb2012-11-10 22:29:54 +0000316Int VG_(strcasecmp) ( const HChar* s1, const HChar* s2 )
njnf76d27a2009-05-28 01:53:07 +0000317{
318 while (True) {
319 UChar c1 = (UChar)VG_(tolower)(*s1);
320 UChar c2 = (UChar)VG_(tolower)(*s2);
njnf76d27a2009-05-28 01:53:07 +0000321 if (c1 < c2) return -1;
322 if (c1 > c2) return 1;
philippe56ddd5b2012-07-26 22:44:07 +0000323
324 /* c1 == c2 */
325 if (c1 == 0) return 0;
njnf76d27a2009-05-28 01:53:07 +0000326
327 s1++; s2++;
328 }
329}
330
florian19f91bb2012-11-10 22:29:54 +0000331Int VG_(strncmp) ( const HChar* s1, const HChar* s2, SizeT nmax )
njn97405b22005-06-02 03:39:33 +0000332{
sewardj4f2683a2008-10-26 11:53:30 +0000333 SizeT n = 0;
njn97405b22005-06-02 03:39:33 +0000334 while (True) {
335 if (n >= nmax) return 0;
florian3e798632012-11-24 19:41:54 +0000336 if (*(const UChar*)s1 < *(const UChar*)s2) return -1;
337 if (*(const UChar*)s1 > *(const UChar*)s2) return 1;
philippe56ddd5b2012-07-26 22:44:07 +0000338
339 /* *s1 == *s2 */
340 if (*s1 == 0) return 0;
njn97405b22005-06-02 03:39:33 +0000341
342 s1++; s2++; n++;
343 }
344}
345
florian19f91bb2012-11-10 22:29:54 +0000346Int VG_(strncasecmp) ( const HChar* s1, const HChar* s2, SizeT nmax )
njnf76d27a2009-05-28 01:53:07 +0000347{
348 Int n = 0;
349 while (True) {
350 UChar c1;
351 UChar c2;
352 if (n >= nmax) return 0;
353 c1 = (UChar)VG_(tolower)(*s1);
354 c2 = (UChar)VG_(tolower)(*s2);
njnf76d27a2009-05-28 01:53:07 +0000355 if (c1 < c2) return -1;
356 if (c1 > c2) return 1;
357
philippe56ddd5b2012-07-26 22:44:07 +0000358 /* c1 == c2 */
359 if (c1 == 0) return 0;
360
njnf76d27a2009-05-28 01:53:07 +0000361 s1++; s2++; n++;
362 }
363}
364
florian19f91bb2012-11-10 22:29:54 +0000365HChar* VG_(strstr) ( const HChar* haystack, const HChar* needle )
njn97405b22005-06-02 03:39:33 +0000366{
sewardj4f2683a2008-10-26 11:53:30 +0000367 SizeT n;
njn97405b22005-06-02 03:39:33 +0000368 if (haystack == NULL)
369 return NULL;
370 n = VG_(strlen)(needle);
371 while (True) {
372 if (haystack[0] == 0)
373 return NULL;
374 if (VG_(strncmp)(haystack, needle, n) == 0)
florian19f91bb2012-11-10 22:29:54 +0000375 return (HChar*)haystack;
njn97405b22005-06-02 03:39:33 +0000376 haystack++;
377 }
378}
379
florian19f91bb2012-11-10 22:29:54 +0000380HChar* VG_(strcasestr) ( const HChar* haystack, const HChar* needle )
njnf76d27a2009-05-28 01:53:07 +0000381{
382 Int n;
383 if (haystack == NULL)
384 return NULL;
385 n = VG_(strlen)(needle);
386 while (True) {
387 if (haystack[0] == 0)
388 return NULL;
389 if (VG_(strncasecmp)(haystack, needle, n) == 0)
florian19f91bb2012-11-10 22:29:54 +0000390 return (HChar*)haystack;
njnf76d27a2009-05-28 01:53:07 +0000391 haystack++;
392 }
393}
394
florian19f91bb2012-11-10 22:29:54 +0000395HChar* VG_(strchr) ( const HChar* s, HChar c )
njn97405b22005-06-02 03:39:33 +0000396{
397 while (True) {
florian19f91bb2012-11-10 22:29:54 +0000398 if (*s == c) return (HChar *)s;
njn97405b22005-06-02 03:39:33 +0000399 if (*s == 0) return NULL;
400 s++;
401 }
402}
403
florian19f91bb2012-11-10 22:29:54 +0000404HChar* VG_(strrchr) ( const HChar* s, HChar c )
njn97405b22005-06-02 03:39:33 +0000405{
406 Int n = VG_(strlen)(s);
407 while (--n > 0) {
florian19f91bb2012-11-10 22:29:54 +0000408 if (s[n] == c) return (HChar *)s + n;
njn97405b22005-06-02 03:39:33 +0000409 }
410 return NULL;
411}
412
sewardj3b290482011-05-06 21:02:55 +0000413/* (code copied from glib then updated to valgrind types) */
florian19f91bb2012-11-10 22:29:54 +0000414static HChar *olds;
415HChar *
416VG_(strtok) (HChar *s, const HChar *delim)
sewardj3b290482011-05-06 21:02:55 +0000417{
418 return VG_(strtok_r) (s, delim, &olds);
419}
420
florian19f91bb2012-11-10 22:29:54 +0000421HChar *
422VG_(strtok_r) (HChar* s, const HChar* delim, HChar** saveptr)
sewardj3b290482011-05-06 21:02:55 +0000423{
florian19f91bb2012-11-10 22:29:54 +0000424 HChar *token;
sewardj3b290482011-05-06 21:02:55 +0000425
426 if (s == NULL)
427 s = *saveptr;
428
429 /* Scan leading delimiters. */
430 s += VG_(strspn (s, delim));
431 if (*s == '\0')
432 {
433 *saveptr = s;
434 return NULL;
435 }
436
437 /* Find the end of the token. */
438 token = s;
439 s = VG_(strpbrk (token, delim));
440 if (s == NULL)
441 /* This token finishes the string. */
442 *saveptr = token + VG_(strlen) (token);
443 else
444 {
445 /* Terminate the token and make OLDS point past it. */
446 *s = '\0';
447 *saveptr = s + 1;
448 }
449 return token;
450}
451
florian19f91bb2012-11-10 22:29:54 +0000452static Bool isHex ( HChar c )
sewardj3b290482011-05-06 21:02:55 +0000453{
454 return ((c >= '0' && c <= '9') ||
455 (c >= 'a' && c <= 'f') ||
456 (c >= 'A' && c <= 'F'));
457}
458
florian19f91bb2012-11-10 22:29:54 +0000459static UInt fromHex ( HChar c )
sewardj3b290482011-05-06 21:02:55 +0000460{
461 if (c >= '0' && c <= '9')
462 return (UInt)c - (UInt)'0';
463 if (c >= 'a' && c <= 'f')
464 return 10 + (UInt)c - (UInt)'a';
465 if (c >= 'A' && c <= 'F')
466 return 10 + (UInt)c - (UInt)'A';
467 /*NOTREACHED*/
468 // ??? need to vg_assert(0);
469 return 0;
470}
471
florian19f91bb2012-11-10 22:29:54 +0000472Bool VG_(parse_Addr) ( const HChar** ppc, Addr* result )
sewardj3b290482011-05-06 21:02:55 +0000473{
474 Int used, limit = 2 * sizeof(Addr);
475 if (**ppc != '0')
476 return False;
477 (*ppc)++;
478 if (**ppc != 'x')
479 return False;
480 (*ppc)++;
481 *result = 0;
482 used = 0;
483 while (isHex(**ppc)) {
484 // ??? need to vg_assert(d < fromHex(**ppc));
485 *result = ((*result) << 4) | fromHex(**ppc);
486 (*ppc)++;
487 used++;
488 if (used > limit) return False;
489 }
490 if (used == 0)
491 return False;
492 return True;
493}
494
florian19f91bb2012-11-10 22:29:54 +0000495SizeT VG_(strspn) ( const HChar* s, const HChar* accpt )
sewardj4f2683a2008-10-26 11:53:30 +0000496{
florian19f91bb2012-11-10 22:29:54 +0000497 const HChar *p, *a;
sewardj4f2683a2008-10-26 11:53:30 +0000498 SizeT count = 0;
499 for (p = s; *p != '\0'; ++p) {
njnf9dcb3b2009-05-19 05:50:34 +0000500 for (a = accpt; *a != '\0'; ++a)
sewardj4f2683a2008-10-26 11:53:30 +0000501 if (*p == *a)
502 break;
503 if (*a == '\0')
504 return count;
505 else
506 ++count;
507 }
508 return count;
509}
510
florian19f91bb2012-11-10 22:29:54 +0000511SizeT VG_(strcspn) ( const HChar* s, const HChar* reject )
sewardj4f2683a2008-10-26 11:53:30 +0000512{
513 SizeT count = 0;
514 while (*s != '\0') {
515 if (VG_(strchr) (reject, *s++) == NULL)
516 ++count;
517 else
518 return count;
519 }
520 return count;
521}
522
523
njn97405b22005-06-02 03:39:33 +0000524/* ---------------------------------------------------------------------
njn97405b22005-06-02 03:39:33 +0000525 mem* functions
526 ------------------------------------------------------------------ */
527
528void* VG_(memcpy) ( void *dest, const void *src, SizeT sz )
529{
sewardj45f4e7c2005-09-27 19:20:21 +0000530 const UChar* s = (const UChar*)src;
531 UChar* d = (UChar*)dest;
532 const UInt* sI = (const UInt*)src;
533 UInt* dI = (UInt*)dest;
534
535 if (VG_IS_4_ALIGNED(dI) && VG_IS_4_ALIGNED(sI)) {
536 while (sz >= 16) {
537 dI[0] = sI[0];
538 dI[1] = sI[1];
539 dI[2] = sI[2];
540 dI[3] = sI[3];
541 sz -= 16;
542 dI += 4;
543 sI += 4;
544 }
545 if (sz == 0)
546 return dest;
547 while (sz >= 4) {
548 dI[0] = sI[0];
549 sz -= 4;
550 dI += 1;
551 sI += 1;
552 }
553 if (sz == 0)
554 return dest;
555 s = (const UChar*)sI;
556 d = (UChar*)dI;
557 }
njn97405b22005-06-02 03:39:33 +0000558
559 while (sz--)
560 *d++ = *s++;
561
562 return dest;
563}
564
sewardjbbec7722007-11-25 14:08:53 +0000565void* VG_(memmove)(void *dest, const void *src, SizeT sz)
566{
567 SizeT i;
568 if (sz == 0)
569 return dest;
570 if (dest < src) {
571 for (i = 0; i < sz; i++) {
florian3e798632012-11-24 19:41:54 +0000572 ((UChar*)dest)[i] = ((const UChar*)src)[i];
sewardjbbec7722007-11-25 14:08:53 +0000573 }
574 }
575 else if (dest > src) {
tom4634b012009-11-03 21:14:31 +0000576 for (i = 0; i < sz; i++) {
florian3e798632012-11-24 19:41:54 +0000577 ((UChar*)dest)[sz-i-1] = ((const UChar*)src)[sz-i-1];
sewardjbbec7722007-11-25 14:08:53 +0000578 }
579 }
580 return dest;
581}
582
sewardjb8b79ad2008-03-03 01:35:41 +0000583void* VG_(memset) ( void *destV, Int c, SizeT sz )
njn97405b22005-06-02 03:39:33 +0000584{
sewardjb8b79ad2008-03-03 01:35:41 +0000585 Int c4;
florian19f91bb2012-11-10 22:29:54 +0000586 HChar* d = (HChar*)destV;
sewardjb8b79ad2008-03-03 01:35:41 +0000587 while ((!VG_IS_4_ALIGNED(d)) && sz >= 1) {
sewardj3187a4e2005-12-04 23:27:14 +0000588 d[0] = c;
589 d++;
590 sz--;
591 }
sewardjb8b79ad2008-03-03 01:35:41 +0000592 if (sz == 0)
593 return destV;
594 c4 = c & 0xFF;
595 c4 |= (c4 << 8);
596 c4 |= (c4 << 16);
597 while (sz >= 16) {
598 ((Int*)d)[0] = c4;
599 ((Int*)d)[1] = c4;
600 ((Int*)d)[2] = c4;
601 ((Int*)d)[3] = c4;
602 d += 16;
603 sz -= 16;
604 }
605 while (sz >= 4) {
606 ((Int*)d)[0] = c4;
607 d += 4;
608 sz -= 4;
609 }
610 while (sz >= 1) {
611 d[0] = c;
612 d++;
613 sz--;
614 }
615 return destV;
njn97405b22005-06-02 03:39:33 +0000616}
617
618Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n )
619{
620 Int res;
tom151a6392005-11-11 12:30:36 +0000621 const UChar *p1 = s1;
622 const UChar *p2 = s2;
njn97405b22005-06-02 03:39:33 +0000623 UChar a0;
624 UChar b0;
625
626 while (n != 0) {
tom151a6392005-11-11 12:30:36 +0000627 a0 = p1[0];
628 b0 = p2[0];
629 p1 += 1;
630 p2 += 1;
njn97405b22005-06-02 03:39:33 +0000631 res = a0 - b0;
632 if (res != 0)
633 return res;
634 n -= 1;
635 }
636 return 0;
637}
638
639/* ---------------------------------------------------------------------
640 Misc useful functions
641 ------------------------------------------------------------------ */
642
sewardjb8b79ad2008-03-03 01:35:41 +0000643/////////////////////////////////////////////////////////////
644/////////////////////////////////////////////////////////////
645/// begin Bentley-McIlroy style quicksort
646/// See "Engineering a Sort Function". Jon L Bentley, M. Douglas
647/// McIlroy. Software Practice and Experience Vol 23(11), Nov 1993.
648
649#define BM_MIN(a, b) \
650 (a) < (b) ? a : b
651
652#define BM_SWAPINIT(a, es) \
653 swaptype = ((a-(Char*)0) | es) % sizeof(Word) ? 2 \
654 : es > (SizeT)sizeof(Word) ? 1 \
655 : 0
656
657#define BM_EXCH(a, b, t) \
658 (t = a, a = b, b = t)
659
660#define BM_SWAP(a, b) \
661 swaptype != 0 \
662 ? bm_swapfunc(a, b, es, swaptype) \
663 : (void)BM_EXCH(*(Word*)(a), *(Word*)(b), t)
664
665#define BM_VECSWAP(a, b, n) \
666 if (n > 0) bm_swapfunc(a, b, n, swaptype)
667
668#define BM_PVINIT(pv, pm) \
669 if (swaptype != 0) \
670 pv = a, BM_SWAP(pv, pm); \
671 else \
672 pv = (Char*)&v, v = *(Word*)pm
673
674static Char* bm_med3 ( Char* a, Char* b, Char* c,
florian6bd9dc12012-11-23 16:17:43 +0000675 Int (*cmp)(const void*, const void*) ) {
sewardjb8b79ad2008-03-03 01:35:41 +0000676 return cmp(a, b) < 0
677 ? (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a)
678 : (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a);
679}
680
681static void bm_swapfunc ( Char* a, Char* b, SizeT n, Int swaptype )
682{
683 if (swaptype <= 1) {
684 Word t;
685 for ( ; n > 0; a += sizeof(Word), b += sizeof(Word),
686 n -= sizeof(Word))
687 BM_EXCH(*(Word*)a, *(Word*)b, t);
688 } else {
689 Char t;
690 for ( ; n > 0; a += 1, b += 1, n -= 1)
691 BM_EXCH(*a, *b, t);
692 }
693}
694
695static void bm_qsort ( Char* a, SizeT n, SizeT es,
florian6bd9dc12012-11-23 16:17:43 +0000696 Int (*cmp)(const void*, const void*) )
sewardjb8b79ad2008-03-03 01:35:41 +0000697{
698 Char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv;
699 Int r, swaptype;
700 Word t, v;
701 SizeT s, s1, s2;
702 tailcall:
703 BM_SWAPINIT(a, es);
704 if (n < 7) {
705 for (pm = a + es; pm < a + n*es; pm += es)
706 for (pl = pm; pl > a && cmp(pl-es, pl) > 0; pl -= es)
707 BM_SWAP(pl, pl-es);
708 return;
709 }
710 pm = a + (n/2)*es;
711 if (n > 7) {
712 pl = a;
713 pn = a + (n-1)*es;
714 if (n > 40) {
715 s = (n/8)*es;
716 pl = bm_med3(pl, pl+s, pl+2*s, cmp);
717 pm = bm_med3(pm-s, pm, pm+s, cmp);
718 pn = bm_med3(pn-2*s, pn-s, pn, cmp);
719 }
720 pm = bm_med3(pl, pm, pn, cmp);
721 }
722 BM_PVINIT(pv, pm);
723 pa = pb = a;
724 pc = pd = a + (n-1)*es;
725 for (;;) {
726 while (pb <= pc && (r = cmp(pb, pv)) <= 0) {
727 if (r == 0) { BM_SWAP(pa, pb); pa += es; }
728 pb += es;
729 }
730 while (pc >= pb && (r = cmp(pc, pv)) >= 0) {
731 if (r == 0) { BM_SWAP(pc, pd); pd -= es; }
732 pc -= es;
733 }
734 if (pb > pc) break;
735 BM_SWAP(pb, pc);
736 pb += es;
737 pc -= es;
738 }
739 pn = a + n*es;
740 s = BM_MIN(pa-a, pb-pa ); BM_VECSWAP(a, pb-s, s);
741 s = BM_MIN(pd-pc, pn-pd-es); BM_VECSWAP(pb, pn-s, s);
742 /* Now recurse. Do the smaller partition first with an explicit
743 recursion, then do the larger partition using a tail call.
744 Except we can't rely on gcc to implement a tail call in any sane
745 way, so simply jump back to the start. This guarantees stack
746 growth can never exceed O(log N) even in the worst case. */
747 s1 = pb-pa;
748 s2 = pd-pc;
749 if (s1 < s2) {
750 if (s1 > es) {
751 bm_qsort(a, s1/es, es, cmp);
752 }
753 if (s2 > es) {
754 /* bm_qsort(pn-s2, s2/es, es, cmp); */
755 a = pn-s2; n = s2/es; es = es; cmp = cmp;
756 goto tailcall;
757 }
758 } else {
759 if (s2 > es) {
760 bm_qsort(pn-s2, s2/es, es, cmp);
761 }
762 if (s1 > es) {
763 /* bm_qsort(a, s1/es, es, cmp); */
764 a = a; n = s1/es; es = es; cmp = cmp;
765 goto tailcall;
766 }
767 }
768}
769
770#undef BM_MIN
771#undef BM_SWAPINIT
772#undef BM_EXCH
773#undef BM_SWAP
774#undef BM_VECSWAP
775#undef BM_PVINIT
776
777/// end Bentley-McIlroy style quicksort
778/////////////////////////////////////////////////////////////
779/////////////////////////////////////////////////////////////
780
781/* Returns the base-2 logarithm of x. Returns -1 if x is not a power
782 of two. */
783Int VG_(log2) ( UInt x )
njn97405b22005-06-02 03:39:33 +0000784{
785 Int i;
786 /* Any more than 32 and we overflow anyway... */
787 for (i = 0; i < 32; i++) {
sewardjb8b79ad2008-03-03 01:35:41 +0000788 if ((1U << i) == x) return i;
njn97405b22005-06-02 03:39:33 +0000789 }
790 return -1;
791}
792
sewardjaebbf1c2011-06-13 13:14:00 +0000793/* Ditto for 64 bit numbers. */
794Int VG_(log2_64) ( ULong x )
795{
796 Int i;
797 for (i = 0; i < 64; i++) {
798 if ((1ULL << i) == x) return i;
799 }
800 return -1;
801}
njn97405b22005-06-02 03:39:33 +0000802
njnfab29902008-03-03 02:15:03 +0000803// Generic quick sort.
njn97405b22005-06-02 03:39:33 +0000804void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
florian6bd9dc12012-11-23 16:17:43 +0000805 Int (*compar)(const void*, const void*) )
njn97405b22005-06-02 03:39:33 +0000806{
sewardjb8b79ad2008-03-03 01:35:41 +0000807 bm_qsort(base,nmemb,size,compar);
njn97405b22005-06-02 03:39:33 +0000808}
809
sewardjb8b79ad2008-03-03 01:35:41 +0000810
njn9828b342005-07-08 04:08:59 +0000811// This random number generator is based on the one suggested in Kernighan
812// and Ritchie's "The C Programming Language".
sewardj45f4e7c2005-09-27 19:20:21 +0000813
814// A pseudo-random number generator returning a random UInt. If pSeed
815// is NULL, it uses its own seed, which starts at zero. If pSeed is
816// non-NULL, it uses and updates whatever pSeed points at.
817
818static UInt seed = 0;
819
820UInt VG_(random)( /*MOD*/UInt* pSeed )
njn9828b342005-07-08 04:08:59 +0000821{
sewardj45f4e7c2005-09-27 19:20:21 +0000822 if (pSeed == NULL)
823 pSeed = &seed;
824
825 *pSeed = (1103515245 * *pSeed + 12345);
826 return *pSeed;
njn9828b342005-07-08 04:08:59 +0000827}
828
njn97405b22005-06-02 03:39:33 +0000829/*--------------------------------------------------------------------*/
830/*--- end ---*/
831/*--------------------------------------------------------------------*/
832