iPXE
string.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stddef.h>
28#include <stdint.h>
29#include <stdlib.h>
30#include <string.h>
31#include <strings.h>
32#include <ctype.h>
33
34/** @file
35 *
36 * String functions
37 *
38 */
39
40/**
41 * Fill memory region
42 *
43 * @v dest Destination region
44 * @v character Fill character
45 * @v len Length
46 * @ret dest Destination region
47 */
48void * generic_memset ( void *dest, int character, size_t len ) {
49 uint8_t *dest_bytes = dest;
50
51 while ( len-- )
52 *(dest_bytes++) = character;
53 return dest;
54}
55
56/**
57 * Copy memory region (forwards)
58 *
59 * @v dest Destination region
60 * @v src Source region
61 * @v len Length
62 * @ret dest Destination region
63 */
64void * generic_memcpy ( void *dest, const void *src, size_t len ) {
65 const uint8_t *src_bytes = src;
66 uint8_t *dest_bytes = dest;
67
68 while ( len-- )
69 *(dest_bytes++) = *(src_bytes++);
70 return dest;
71}
72
73/**
74 * Copy memory region (backwards)
75 *
76 * @v dest Destination region
77 * @v src Source region
78 * @v len Length
79 * @ret dest Destination region
80 */
81void * generic_memcpy_reverse ( void *dest, const void *src, size_t len ) {
82 const uint8_t *src_bytes = ( src + len );
83 uint8_t *dest_bytes = ( dest + len );
84
85 while ( len-- )
86 *(--dest_bytes) = *(--src_bytes);
87 return dest;
88}
89
90/**
91 * Copy (possibly overlapping) memory region
92 *
93 * @v dest Destination region
94 * @v src Source region
95 * @v len Length
96 * @ret dest Destination region
97 */
98void * generic_memmove ( void *dest, const void *src, size_t len ) {
99
100 if ( dest < src ) {
101 return generic_memcpy ( dest, src, len );
102 } else {
103 return generic_memcpy_reverse ( dest, src, len );
104 }
105}
106
107/**
108 * Compare memory regions
109 *
110 * @v first First region
111 * @v second Second region
112 * @v len Length
113 * @ret diff Difference
114 */
115int memcmp ( const void *first, const void *second, size_t len ) {
116 const uint8_t *first_bytes = first;
117 const uint8_t *second_bytes = second;
118 int diff;
119
120 while ( len-- ) {
121 diff = ( *(first_bytes++) - *(second_bytes++) );
122 if ( diff )
123 return diff;
124 }
125 return 0;
126}
127
128/**
129 * Find character within a memory region
130 *
131 * @v src Source region
132 * @v character Character to find
133 * @v len Length
134 * @ret found Found character, or NULL if not found
135 */
136void * memchr ( const void *src, int character, size_t len ) {
137 const uint8_t *src_bytes = src;
138
139 for ( ; len-- ; src_bytes++ ) {
140 if ( *src_bytes == character )
141 return ( ( void * ) src_bytes );
142 }
143 return NULL;
144}
145
146/**
147 * Swap memory regions
148 *
149 * @v first First region
150 * @v second Second region
151 * @v len Length
152 * @ret first First region
153 */
154void * memswap ( void *first, void *second, size_t len ) {
155 uint8_t *first_bytes = first;
156 uint8_t *second_bytes = second;
157 uint8_t temp;
158
159 for ( ; len-- ; first_bytes++, second_bytes++ ) {
160 temp = *first_bytes;
161 *first_bytes = *second_bytes;
162 *second_bytes = temp;
163 }
164 return first;
165}
166
167/**
168 * Compare strings
169 *
170 * @v first First string
171 * @v second Second string
172 * @ret diff Difference
173 */
174int strcmp ( const char *first, const char *second ) {
175
176 return strncmp ( first, second, ~( ( size_t ) 0 ) );
177}
178
179/**
180 * Compare strings
181 *
182 * @v first First string
183 * @v second Second string
184 * @v max Maximum length to compare
185 * @ret diff Difference
186 */
187int strncmp ( const char *first, const char *second, size_t max ) {
188 const uint8_t *first_bytes = ( ( const uint8_t * ) first );
189 const uint8_t *second_bytes = ( ( const uint8_t * ) second );
190 int diff;
191
192 for ( ; max-- ; first_bytes++, second_bytes++ ) {
193 diff = ( *first_bytes - *second_bytes );
194 if ( diff )
195 return diff;
196 if ( ! *first_bytes )
197 return 0;
198 }
199 return 0;
200}
201
202/**
203 * Compare case-insensitive strings
204 *
205 * @v first First string
206 * @v second Second string
207 * @ret diff Difference
208 */
209int strcasecmp ( const char *first, const char *second ) {
210
211 return strncasecmp ( first, second, ~( ( size_t ) 0 ) );
212}
213
214/**
215 * Compare case-insensitive strings
216 *
217 * @v first First string
218 * @v second Second string
219 * @v max Maximum length to compare
220 * @ret diff Difference
221 */
222int strncasecmp ( const char *first, const char *second, size_t max ) {
223 const uint8_t *first_bytes = ( ( const uint8_t * ) first );
224 const uint8_t *second_bytes = ( ( const uint8_t * ) second );
225 int diff;
226
227 for ( ; max-- ; first_bytes++, second_bytes++ ) {
228 diff = ( toupper ( *first_bytes ) -
229 toupper ( *second_bytes ) );
230 if ( diff )
231 return diff;
232 if ( ! *first_bytes )
233 return 0;
234 }
235 return 0;
236}
237
238/**
239 * Get length of string
240 *
241 * @v src String
242 * @ret len Length
243 */
244size_t strlen ( const char *src ) {
245
246 return strnlen ( src, ~( ( size_t ) 0 ) );
247}
248
249/**
250 * Get length of string
251 *
252 * @v src String
253 * @v max Maximum length
254 * @ret len Length
255 */
256size_t strnlen ( const char *src, size_t max ) {
257 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
258 size_t len = 0;
259
260 while ( max-- && *(src_bytes++) )
261 len++;
262 return len;
263}
264
265/**
266 * Find character within a string, or NUL terminator
267 *
268 * @v src String
269 * @v character Character to find
270 * @ret found Found character, or terminating NUL if not found
271 */
272char * strchrnul ( const char *src, int character ) {
273 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
274
275 for ( ; ; src_bytes++ ) {
276 if ( ( *src_bytes == character ) || ( ! *src_bytes ) )
277 return ( ( char * ) src_bytes );
278 }
279}
280
281/**
282 * Find character within a string
283 *
284 * @v src String
285 * @v character Character to find
286 * @ret found Found character, or NULL if not found
287 */
288char * strchr ( const char *src, int character ) {
289 char *found;
290
291 found = strchrnul ( src, character );
292 if ( character != *( ( uint8_t * ) found ) )
293 return NULL;
294 return found;
295}
296
297/**
298 * Find rightmost character within a string
299 *
300 * @v src String
301 * @v character Character to find
302 * @ret found Found character, or NULL if not found
303 */
304char * strrchr ( const char *src, int character ) {
305 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
306 const uint8_t *start = src_bytes;
307
308 while ( *src_bytes )
309 src_bytes++;
310 for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
311 if ( *src_bytes == character )
312 return ( ( char * ) src_bytes );
313 }
314 return NULL;
315}
316
317/**
318 * Find substring
319 *
320 * @v haystack String
321 * @v needle Substring
322 * @ret found Found substring, or NULL if not found
323 */
324char * strstr ( const char *haystack, const char *needle ) {
325 size_t len = strlen ( needle );
326
327 for ( ; *haystack ; haystack++ ) {
328 if ( memcmp ( haystack, needle, len ) == 0 )
329 return ( ( char * ) haystack );
330 }
331 return NULL;
332}
333
334/**
335 * Find case-insensitive substring
336 *
337 * @v haystack String
338 * @v needle Substring
339 * @ret found Found substring, or NULL if not found
340 */
341char * strcasestr ( const char *haystack, const char *needle ) {
342 size_t len = strlen ( needle );
343
344 for ( ; *haystack ; haystack++ ) {
345 if ( strncasecmp ( haystack, needle, len ) == 0 )
346 return ( ( char * ) haystack );
347 }
348 return NULL;
349}
350
351/**
352 * Copy string
353 *
354 * @v dest Destination string
355 * @v src Source string
356 * @ret dnul Terminating NUL of destination string
357 */
358char * stpcpy ( char *dest, const char *src ) {
359 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
360 uint8_t *dest_bytes = ( ( uint8_t * ) dest );
361
362 /* We cannot use strncpy(), since that would pad the destination */
363 for ( ; ; src_bytes++, dest_bytes++ ) {
364 *dest_bytes = *src_bytes;
365 if ( ! *dest_bytes )
366 break;
367 }
368 return ( ( char * ) dest_bytes );
369}
370
371/**
372 * Copy string
373 *
374 * @v dest Destination string
375 * @v src Source string
376 * @ret dest Destination string
377 */
378char * strcpy ( char *dest, const char *src ) {
379
380 stpcpy ( dest, src );
381 return dest;
382}
383
384/**
385 * Copy string
386 *
387 * @v dest Destination string
388 * @v src Source string
389 * @v max Maximum length
390 * @ret dest Destination string
391 */
392char * strncpy ( char *dest, const char *src, size_t max ) {
393 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
394 uint8_t *dest_bytes = ( ( uint8_t * ) dest );
395
396 for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
397 *dest_bytes = *src_bytes;
398 if ( ! *dest_bytes )
399 break;
400 }
401 while ( max-- )
402 *(dest_bytes++) = '\0';
403 return dest;
404}
405
406/**
407 * Concatenate string
408 *
409 * @v dest Destination string
410 * @v src Source string
411 * @ret dest Destination string
412 */
413char * strcat ( char *dest, const char *src ) {
414
415 strcpy ( ( dest + strlen ( dest ) ), src );
416 return dest;
417}
418
419/**
420 * Duplicate string
421 *
422 * @v src Source string
423 * @ret dup Duplicated string, or NULL if allocation failed
424 */
425char * strdup ( const char *src ) {
426
427 return strndup ( src, ~( ( size_t ) 0 ) );
428}
429
430/**
431 * Duplicate string
432 *
433 * @v src Source string
434 * @v max Maximum length
435 * @ret dup Duplicated string, or NULL if allocation failed
436 */
437char * strndup ( const char *src, size_t max ) {
438 size_t len = strnlen ( src, max );
439 char *dup;
440
441 dup = malloc ( len + 1 /* NUL */ );
442 if ( dup ) {
443 memcpy ( dup, src, len );
444 dup[len] = '\0';
445 }
446 return dup;
447}
448
449/**
450 * Calculate digit value
451 *
452 * @v character Digit character
453 * @ret digit Digit value
454 *
455 * Invalid digits will be returned as a value greater than or equal to
456 * the numeric base.
457 */
458unsigned int digit_value ( unsigned int character ) {
459
460 if ( character >= 'a' )
461 return ( character - ( 'a' - 10 ) );
462 if ( character >= 'A' )
463 return ( character - ( 'A' - 10 ) );
464 if ( character <= '9' )
465 return ( character - '0' );
466 return character;
467}
468
469/**
470 * Preprocess string for strtoul() or strtoull()
471 *
472 * @v string String
473 * @v negate Final value should be negated
474 * @v base Numeric base
475 * @ret string Remaining string
476 */
477static const char * strtoul_pre ( const char *string, int *negate, int *base ) {
478
479 /* Skip any leading whitespace */
480 while ( isspace ( *string ) )
481 string++;
482
483 /* Process arithmetic sign, if present */
484 *negate = 0;
485 if ( *string == '-' ) {
486 string++;
487 *negate = 1;
488 } else if ( *string == '+' ) {
489 string++;
490 }
491
492 /* Process base, if present */
493 if ( *base == 0 ) {
494 *base = 10;
495 if ( *string == '0' ) {
496 string++;
497 *base = 8;
498 if ( ( *string & ~0x20 ) == 'X' ) {
499 string++;
500 *base = 16;
501 }
502 }
503 }
504
505 return string;
506}
507
508/**
509 * Convert string to numeric value
510 *
511 * @v string String
512 * @v endp End pointer (or NULL)
513 * @v base Numeric base (or zero to autodetect)
514 * @ret value Numeric value
515 */
516unsigned long strtoul ( const char *string, char **endp, int base ) {
517 unsigned long value = 0;
518 unsigned int digit;
519 int negate;
520
521 /* Preprocess string */
522 string = strtoul_pre ( string, &negate, &base );
523
524 /* Process digits */
525 for ( ; ; string++ ) {
526 digit = digit_value ( *string );
527 if ( digit >= ( unsigned int ) base )
528 break;
529 value = ( ( value * base ) + digit );
530 }
531
532 /* Negate value if, applicable */
533 if ( negate )
534 value = -value;
535
536 /* Fill in end pointer, if applicable */
537 if ( endp )
538 *endp = ( ( char * ) string );
539
540 return value;
541}
542
543/**
544 * Convert string to numeric value
545 *
546 * @v string String
547 * @v endp End pointer (or NULL)
548 * @v base Numeric base (or zero to autodetect)
549 * @ret value Numeric value
550 */
551unsigned long long strtoull ( const char *string, char **endp, int base ) {
552 unsigned long long value = 0;
553 unsigned int digit;
554 int negate;
555
556 /* Preprocess string */
557 string = strtoul_pre ( string, &negate, &base );
558
559 /* Process digits */
560 for ( ; ; string++ ) {
561 digit = digit_value ( *string );
562 if ( digit >= ( unsigned int ) base )
563 break;
564 value = ( ( value * base ) + digit );
565 }
566
567 /* Negate value if, applicable */
568 if ( negate )
569 value = -value;
570
571 /* Fill in end pointer, if applicable */
572 if ( endp )
573 *endp = ( ( char * ) string );
574
575 return value;
576}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
static const void * src
Definition string.h:48
#define max(x, y)
Definition ath.h:41
int isspace(int character)
Check to see if character is a space.
Definition ctype.c:42
Character types.
static int toupper(int character)
Convert character to upper case.
Definition ctype.h:121
ring len
Length.
Definition dwmac.h:226
uint32_t start
Starting offset.
Definition netvsc.h:1
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
String functions.
uint32_t base
Base.
Definition librm.h:3
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
uint32_t string
Definition multiboot.h:2
uint32_t first
First block in range.
Definition pccrr.h:1
void * generic_memcpy(void *dest, const void *src, size_t len)
Copy memory region (forwards).
Definition string.c:64
char * strcat(char *dest, const char *src)
Concatenate string.
Definition string.c:413
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition string.c:154
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:516
void * generic_memmove(void *dest, const void *src, size_t len)
Copy (possibly overlapping) memory region.
Definition string.c:98
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:288
int strncasecmp(const char *first, const char *second, size_t max)
Compare case-insensitive strings.
Definition string.c:222
char * strdup(const char *src)
Duplicate string.
Definition string.c:425
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition string.c:136
char * stpcpy(char *dest, const char *src)
Copy string.
Definition string.c:358
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition string.c:187
size_t strnlen(const char *src, size_t max)
Get length of string.
Definition string.c:256
unsigned int digit_value(unsigned int character)
Calculate digit value.
Definition string.c:458
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
static const char * strtoul_pre(const char *string, int *negate, int *base)
Preprocess string for strtoul() or strtoull().
Definition string.c:477
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition string.c:209
char * strndup(const char *src, size_t max)
Duplicate string.
Definition string.c:437
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition string.c:324
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition string.c:304
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:378
char * strcasestr(const char *haystack, const char *needle)
Find case-insensitive substring.
Definition string.c:341
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
char * strchrnul(const char *src, int character)
Find character within a string, or NUL terminator.
Definition string.c:272
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:392
void * generic_memset(void *dest, int character, size_t len)
Fill memory region.
Definition string.c:48
unsigned long long strtoull(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:551
void * generic_memcpy_reverse(void *dest, const void *src, size_t len)
Copy memory region (backwards).
Definition string.c:81