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
267 *
268 * @v src String
269 * @v character Character to find
270 * @ret found Found character, or NULL if not found
271 */
272char * strchr ( 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 )
277 return ( ( char * ) src_bytes );
278 if ( ! *src_bytes )
279 return NULL;
280 }
281}
282
283/**
284 * Find rightmost character within a string
285 *
286 * @v src String
287 * @v character Character to find
288 * @ret found Found character, or NULL if not found
289 */
290char * strrchr ( const char *src, int character ) {
291 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
292 const uint8_t *start = src_bytes;
293
294 while ( *src_bytes )
295 src_bytes++;
296 for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
297 if ( *src_bytes == character )
298 return ( ( char * ) src_bytes );
299 }
300 return NULL;
301}
302
303/**
304 * Find substring
305 *
306 * @v haystack String
307 * @v needle Substring
308 * @ret found Found substring, or NULL if not found
309 */
310char * strstr ( const char *haystack, const char *needle ) {
311 size_t len = strlen ( needle );
312
313 for ( ; *haystack ; haystack++ ) {
314 if ( memcmp ( haystack, needle, len ) == 0 )
315 return ( ( char * ) haystack );
316 }
317 return NULL;
318}
319
320/**
321 * Copy string
322 *
323 * @v dest Destination string
324 * @v src Source string
325 * @ret dnul Terminating NUL of destination string
326 */
327char * stpcpy ( char *dest, const char *src ) {
328 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
329 uint8_t *dest_bytes = ( ( uint8_t * ) dest );
330
331 /* We cannot use strncpy(), since that would pad the destination */
332 for ( ; ; src_bytes++, dest_bytes++ ) {
333 *dest_bytes = *src_bytes;
334 if ( ! *dest_bytes )
335 break;
336 }
337 return ( ( char * ) dest_bytes );
338}
339
340/**
341 * Copy string
342 *
343 * @v dest Destination string
344 * @v src Source string
345 * @ret dest Destination string
346 */
347char * strcpy ( char *dest, const char *src ) {
348
349 stpcpy ( dest, src );
350 return dest;
351}
352
353/**
354 * Copy string
355 *
356 * @v dest Destination string
357 * @v src Source string
358 * @v max Maximum length
359 * @ret dest Destination string
360 */
361char * strncpy ( char *dest, const char *src, size_t max ) {
362 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
363 uint8_t *dest_bytes = ( ( uint8_t * ) dest );
364
365 for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
366 *dest_bytes = *src_bytes;
367 if ( ! *dest_bytes )
368 break;
369 }
370 while ( max-- )
371 *(dest_bytes++) = '\0';
372 return dest;
373}
374
375/**
376 * Concatenate string
377 *
378 * @v dest Destination string
379 * @v src Source string
380 * @ret dest Destination string
381 */
382char * strcat ( char *dest, const char *src ) {
383
384 strcpy ( ( dest + strlen ( dest ) ), src );
385 return dest;
386}
387
388/**
389 * Duplicate string
390 *
391 * @v src Source string
392 * @ret dup Duplicated string, or NULL if allocation failed
393 */
394char * strdup ( const char *src ) {
395
396 return strndup ( src, ~( ( size_t ) 0 ) );
397}
398
399/**
400 * Duplicate string
401 *
402 * @v src Source string
403 * @v max Maximum length
404 * @ret dup Duplicated string, or NULL if allocation failed
405 */
406char * strndup ( const char *src, size_t max ) {
407 size_t len = strnlen ( src, max );
408 char *dup;
409
410 dup = malloc ( len + 1 /* NUL */ );
411 if ( dup ) {
412 memcpy ( dup, src, len );
413 dup[len] = '\0';
414 }
415 return dup;
416}
417
418/**
419 * Calculate digit value
420 *
421 * @v character Digit character
422 * @ret digit Digit value
423 *
424 * Invalid digits will be returned as a value greater than or equal to
425 * the numeric base.
426 */
427unsigned int digit_value ( unsigned int character ) {
428
429 if ( character >= 'a' )
430 return ( character - ( 'a' - 10 ) );
431 if ( character >= 'A' )
432 return ( character - ( 'A' - 10 ) );
433 if ( character <= '9' )
434 return ( character - '0' );
435 return character;
436}
437
438/**
439 * Preprocess string for strtoul() or strtoull()
440 *
441 * @v string String
442 * @v negate Final value should be negated
443 * @v base Numeric base
444 * @ret string Remaining string
445 */
446static const char * strtoul_pre ( const char *string, int *negate, int *base ) {
447
448 /* Skip any leading whitespace */
449 while ( isspace ( *string ) )
450 string++;
451
452 /* Process arithmetic sign, if present */
453 *negate = 0;
454 if ( *string == '-' ) {
455 string++;
456 *negate = 1;
457 } else if ( *string == '+' ) {
458 string++;
459 }
460
461 /* Process base, if present */
462 if ( *base == 0 ) {
463 *base = 10;
464 if ( *string == '0' ) {
465 string++;
466 *base = 8;
467 if ( ( *string & ~0x20 ) == 'X' ) {
468 string++;
469 *base = 16;
470 }
471 }
472 }
473
474 return string;
475}
476
477/**
478 * Convert string to numeric value
479 *
480 * @v string String
481 * @v endp End pointer (or NULL)
482 * @v base Numeric base (or zero to autodetect)
483 * @ret value Numeric value
484 */
485unsigned long strtoul ( const char *string, char **endp, int base ) {
486 unsigned long value = 0;
487 unsigned int digit;
488 int negate;
489
490 /* Preprocess string */
491 string = strtoul_pre ( string, &negate, &base );
492
493 /* Process digits */
494 for ( ; ; string++ ) {
495 digit = digit_value ( *string );
496 if ( digit >= ( unsigned int ) base )
497 break;
498 value = ( ( value * base ) + digit );
499 }
500
501 /* Negate value if, applicable */
502 if ( negate )
503 value = -value;
504
505 /* Fill in end pointer, if applicable */
506 if ( endp )
507 *endp = ( ( char * ) string );
508
509 return value;
510}
511
512/**
513 * Convert string to numeric value
514 *
515 * @v string String
516 * @v endp End pointer (or NULL)
517 * @v base Numeric base (or zero to autodetect)
518 * @ret value Numeric value
519 */
520unsigned long long strtoull ( const char *string, char **endp, int base ) {
521 unsigned long long value = 0;
522 unsigned int digit;
523 int negate;
524
525 /* Preprocess string */
526 string = strtoul_pre ( string, &negate, &base );
527
528 /* Process digits */
529 for ( ; ; string++ ) {
530 digit = digit_value ( *string );
531 if ( digit >= ( unsigned int ) base )
532 break;
533 value = ( ( value * base ) + digit );
534 }
535
536 /* Negate value if, applicable */
537 if ( negate )
538 value = -value;
539
540 /* Fill in end pointer, if applicable */
541 if ( endp )
542 *endp = ( ( char * ) string );
543
544 return value;
545}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
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:382
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:485
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:272
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:394
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:327
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:427
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:446
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:406
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition string.c:310
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition string.c:290
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition string.c:361
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:520
void * generic_memcpy_reverse(void *dest, const void *src, size_t len)
Copy memory region (backwards)
Definition string.c:81