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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <ctype.h>
32 
33 /** @file
34  *
35  * String functions
36  *
37  */
38 
39 /**
40  * Fill memory region
41  *
42  * @v dest Destination region
43  * @v character Fill character
44  * @v len Length
45  * @ret dest Destination region
46  */
47 void * generic_memset ( void *dest, int character, size_t len ) {
48  uint8_t *dest_bytes = dest;
49 
50  while ( len-- )
51  *(dest_bytes++) = character;
52  return dest;
53 }
54 
55 /**
56  * Copy memory region (forwards)
57  *
58  * @v dest Destination region
59  * @v src Source region
60  * @v len Length
61  * @ret dest Destination region
62  */
63 void * generic_memcpy ( void *dest, const void *src, size_t len ) {
64  const uint8_t *src_bytes = src;
65  uint8_t *dest_bytes = dest;
66 
67  while ( len-- )
68  *(dest_bytes++) = *(src_bytes++);
69  return dest;
70 }
71 
72 /**
73  * Copy memory region (backwards)
74  *
75  * @v dest Destination region
76  * @v src Source region
77  * @v len Length
78  * @ret dest Destination region
79  */
80 void * generic_memcpy_reverse ( void *dest, const void *src, size_t len ) {
81  const uint8_t *src_bytes = ( src + len );
82  uint8_t *dest_bytes = ( dest + len );
83 
84  while ( len-- )
85  *(--dest_bytes) = *(--src_bytes);
86  return dest;
87 }
88 
89 /**
90  * Copy (possibly overlapping) memory region
91  *
92  * @v dest Destination region
93  * @v src Source region
94  * @v len Length
95  * @ret dest Destination region
96  */
97 void * generic_memmove ( void *dest, const void *src, size_t len ) {
98 
99  if ( dest < src ) {
100  return generic_memcpy ( dest, src, len );
101  } else {
102  return generic_memcpy_reverse ( dest, src, len );
103  }
104 }
105 
106 /**
107  * Compare memory regions
108  *
109  * @v first First region
110  * @v second Second region
111  * @v len Length
112  * @ret diff Difference
113  */
114 int memcmp ( const void *first, const void *second, size_t len ) {
115  const uint8_t *first_bytes = first;
116  const uint8_t *second_bytes = second;
117  int diff;
118 
119  while ( len-- ) {
120  diff = ( *(first_bytes++) - *(second_bytes++) );
121  if ( diff )
122  return diff;
123  }
124  return 0;
125 }
126 
127 /**
128  * Find character within a memory region
129  *
130  * @v src Source region
131  * @v character Character to find
132  * @v len Length
133  * @ret found Found character, or NULL if not found
134  */
135 void * memchr ( const void *src, int character, size_t len ) {
136  const uint8_t *src_bytes = src;
137 
138  for ( ; len-- ; src_bytes++ ) {
139  if ( *src_bytes == character )
140  return ( ( void * ) src_bytes );
141  }
142  return NULL;
143 }
144 
145 /**
146  * Swap memory regions
147  *
148  * @v first First region
149  * @v second Second region
150  * @v len Length
151  * @ret first First region
152  */
153 void * memswap ( void *first, void *second, size_t len ) {
154  uint8_t *first_bytes = first;
155  uint8_t *second_bytes = second;
156  uint8_t temp;
157 
158  for ( ; len-- ; first_bytes++, second_bytes++ ) {
159  temp = *first_bytes;
160  *first_bytes = *second_bytes;
161  *second_bytes = temp;
162  }
163  return first;
164 }
165 
166 /**
167  * Compare strings
168  *
169  * @v first First string
170  * @v second Second string
171  * @ret diff Difference
172  */
173 int strcmp ( const char *first, const char *second ) {
174 
175  return strncmp ( first, second, ~( ( size_t ) 0 ) );
176 }
177 
178 /**
179  * Compare strings
180  *
181  * @v first First string
182  * @v second Second string
183  * @v max Maximum length to compare
184  * @ret diff Difference
185  */
186 int strncmp ( const char *first, const char *second, size_t max ) {
187  const uint8_t *first_bytes = ( ( const uint8_t * ) first );
188  const uint8_t *second_bytes = ( ( const uint8_t * ) second );
189  int diff;
190 
191  for ( ; max-- ; first_bytes++, second_bytes++ ) {
192  diff = ( *first_bytes - *second_bytes );
193  if ( diff )
194  return diff;
195  if ( ! *first_bytes )
196  return 0;
197  }
198  return 0;
199 }
200 
201 /**
202  * Compare case-insensitive strings
203  *
204  * @v first First string
205  * @v second Second string
206  * @ret diff Difference
207  */
208 int strcasecmp ( const char *first, const char *second ) {
209 
210  return strncasecmp ( first, second, ~( ( size_t ) 0 ) );
211 }
212 
213 /**
214  * Compare case-insensitive strings
215  *
216  * @v first First string
217  * @v second Second string
218  * @v max Maximum length to compare
219  * @ret diff Difference
220  */
221 int strncasecmp ( const char *first, const char *second, size_t max ) {
222  const uint8_t *first_bytes = ( ( const uint8_t * ) first );
223  const uint8_t *second_bytes = ( ( const uint8_t * ) second );
224  int diff;
225 
226  for ( ; max-- ; first_bytes++, second_bytes++ ) {
227  diff = ( toupper ( *first_bytes ) -
228  toupper ( *second_bytes ) );
229  if ( diff )
230  return diff;
231  if ( ! *first_bytes )
232  return 0;
233  }
234  return 0;
235 }
236 
237 /**
238  * Get length of string
239  *
240  * @v src String
241  * @ret len Length
242  */
243 size_t strlen ( const char *src ) {
244 
245  return strnlen ( src, ~( ( size_t ) 0 ) );
246 }
247 
248 /**
249  * Get length of string
250  *
251  * @v src String
252  * @v max Maximum length
253  * @ret len Length
254  */
255 size_t strnlen ( const char *src, size_t max ) {
256  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
257  size_t len = 0;
258 
259  while ( max-- && *(src_bytes++) )
260  len++;
261  return len;
262 }
263 
264 /**
265  * Find character within a string
266  *
267  * @v src String
268  * @v character Character to find
269  * @ret found Found character, or NULL if not found
270  */
271 char * strchr ( const char *src, int character ) {
272  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
273 
274  for ( ; ; src_bytes++ ) {
275  if ( *src_bytes == character )
276  return ( ( char * ) src_bytes );
277  if ( ! *src_bytes )
278  return NULL;
279  }
280 }
281 
282 /**
283  * Find rightmost character within a string
284  *
285  * @v src String
286  * @v character Character to find
287  * @ret found Found character, or NULL if not found
288  */
289 char * strrchr ( const char *src, int character ) {
290  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
291  const uint8_t *start = src_bytes;
292 
293  while ( *src_bytes )
294  src_bytes++;
295  for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
296  if ( *src_bytes == character )
297  return ( ( char * ) src_bytes );
298  }
299  return NULL;
300 }
301 
302 /**
303  * Find substring
304  *
305  * @v haystack String
306  * @v needle Substring
307  * @ret found Found substring, or NULL if not found
308  */
309 char * strstr ( const char *haystack, const char *needle ) {
310  size_t len = strlen ( needle );
311 
312  for ( ; *haystack ; haystack++ ) {
313  if ( memcmp ( haystack, needle, len ) == 0 )
314  return ( ( char * ) haystack );
315  }
316  return NULL;
317 }
318 
319 /**
320  * Copy string
321  *
322  * @v dest Destination string
323  * @v src Source string
324  * @ret dest Destination string
325  */
326 char * strcpy ( char *dest, const char *src ) {
327  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
328  uint8_t *dest_bytes = ( ( uint8_t * ) dest );
329 
330  /* We cannot use strncpy(), since that would pad the destination */
331  for ( ; ; src_bytes++, dest_bytes++ ) {
332  *dest_bytes = *src_bytes;
333  if ( ! *dest_bytes )
334  break;
335  }
336  return dest;
337 }
338 
339 /**
340  * Copy string
341  *
342  * @v dest Destination string
343  * @v src Source string
344  * @v max Maximum length
345  * @ret dest Destination string
346  */
347 char * strncpy ( char *dest, const char *src, size_t max ) {
348  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
349  uint8_t *dest_bytes = ( ( uint8_t * ) dest );
350 
351  for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
352  *dest_bytes = *src_bytes;
353  if ( ! *dest_bytes )
354  break;
355  }
356  while ( max-- )
357  *(dest_bytes++) = '\0';
358  return dest;
359 }
360 
361 /**
362  * Concatenate string
363  *
364  * @v dest Destination string
365  * @v src Source string
366  * @ret dest Destination string
367  */
368 char * strcat ( char *dest, const char *src ) {
369 
370  strcpy ( ( dest + strlen ( dest ) ), src );
371  return dest;
372 }
373 
374 /**
375  * Duplicate string
376  *
377  * @v src Source string
378  * @ret dup Duplicated string, or NULL if allocation failed
379  */
380 char * strdup ( const char *src ) {
381 
382  return strndup ( src, ~( ( size_t ) 0 ) );
383 }
384 
385 /**
386  * Duplicate string
387  *
388  * @v src Source string
389  * @v max Maximum length
390  * @ret dup Duplicated string, or NULL if allocation failed
391  */
392 char * strndup ( const char *src, size_t max ) {
393  size_t len = strnlen ( src, max );
394  char *dup;
395 
396  dup = malloc ( len + 1 /* NUL */ );
397  if ( dup ) {
398  memcpy ( dup, src, len );
399  dup[len] = '\0';
400  }
401  return dup;
402 }
403 
404 /**
405  * Calculate digit value
406  *
407  * @v character Digit character
408  * @ret digit Digit value
409  *
410  * Invalid digits will be returned as a value greater than or equal to
411  * the numeric base.
412  */
413 unsigned int digit_value ( unsigned int character ) {
414 
415  if ( character >= 'a' )
416  return ( character - ( 'a' - 10 ) );
417  if ( character >= 'A' )
418  return ( character - ( 'A' - 10 ) );
419  if ( character <= '9' )
420  return ( character - '0' );
421  return character;
422 }
423 
424 /**
425  * Preprocess string for strtoul() or strtoull()
426  *
427  * @v string String
428  * @v negate Final value should be negated
429  * @v base Numeric base
430  * @ret string Remaining string
431  */
432 static const char * strtoul_pre ( const char *string, int *negate, int *base ) {
433 
434  /* Skip any leading whitespace */
435  while ( isspace ( *string ) )
436  string++;
437 
438  /* Process arithmetic sign, if present */
439  *negate = 0;
440  if ( *string == '-' ) {
441  string++;
442  *negate = 1;
443  } else if ( *string == '+' ) {
444  string++;
445  }
446 
447  /* Process base, if present */
448  if ( *base == 0 ) {
449  *base = 10;
450  if ( *string == '0' ) {
451  string++;
452  *base = 8;
453  if ( ( *string & ~0x20 ) == 'X' ) {
454  string++;
455  *base = 16;
456  }
457  }
458  }
459 
460  return string;
461 }
462 
463 /**
464  * Convert string to numeric value
465  *
466  * @v string String
467  * @v endp End pointer (or NULL)
468  * @v base Numeric base (or zero to autodetect)
469  * @ret value Numeric value
470  */
471 unsigned long strtoul ( const char *string, char **endp, int base ) {
472  unsigned long value = 0;
473  unsigned int digit;
474  int negate;
475 
476  /* Preprocess string */
477  string = strtoul_pre ( string, &negate, &base );
478 
479  /* Process digits */
480  for ( ; ; string++ ) {
481  digit = digit_value ( *string );
482  if ( digit >= ( unsigned int ) base )
483  break;
484  value = ( ( value * base ) + digit );
485  }
486 
487  /* Negate value if, applicable */
488  if ( negate )
489  value = -value;
490 
491  /* Fill in end pointer, if applicable */
492  if ( endp )
493  *endp = ( ( char * ) string );
494 
495  return value;
496 }
497 
498 /**
499  * Convert string to numeric value
500  *
501  * @v string String
502  * @v endp End pointer (or NULL)
503  * @v base Numeric base (or zero to autodetect)
504  * @ret value Numeric value
505  */
506 unsigned long long strtoull ( const char *string, char **endp, int base ) {
507  unsigned long long value = 0;
508  unsigned int digit;
509  int negate;
510 
511  /* Preprocess string */
512  string = strtoul_pre ( string, &negate, &base );
513 
514  /* Process digits */
515  for ( ; ; string++ ) {
516  digit = digit_value ( *string );
517  if ( digit >= ( unsigned int ) base )
518  break;
519  value = ( ( value * base ) + digit );
520  }
521 
522  /* Negate value if, applicable */
523  if ( negate )
524  value = -value;
525 
526  /* Fill in end pointer, if applicable */
527  if ( endp )
528  *endp = ( ( char * ) string );
529 
530  return value;
531 }
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition: string.c:153
#define max(x, y)
Definition: ath.h:39
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:471
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:289
static __always_inline int off_t userptr_t second
Definition: efi_uaccess.h:80
static void const void * src
Definition: crypto.h:244
unsigned long long strtoull(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:506
uint32_t string
Definition: multiboot.h:14
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition: string.c:208
int strncasecmp(const char *first, const char *second, size_t max)
Compare case-insensitive strings.
Definition: string.c:221
Character types.
void * generic_memcpy(void *dest, const void *src, size_t len)
Copy memory region (forwards)
Definition: string.c:63
unsigned int digit_value(unsigned int character)
Calculate digit value.
Definition: string.c:413
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:186
static const void * base
Base address.
Definition: crypto.h:335
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition: string.c:135
uint32_t start
Starting offset.
Definition: netvsc.h:12
static int toupper(int character)
Convert character to upper case.
Definition: ctype.h:120
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition: string.c:347
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:309
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:326
static void * dest
Definition: strings.h:176
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
static const char * strtoul_pre(const char *string, int *negate, int *base)
Preprocess string for strtoul() or strtoull()
Definition: string.c:432
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:271
void * generic_memcpy_reverse(void *dest, const void *src, size_t len)
Copy memory region (backwards)
Definition: string.c:80
char * strdup(const char *src)
Duplicate string.
Definition: string.c:380
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:41
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
unsigned char uint8_t
Definition: stdint.h:10
size_t strnlen(const char *src, size_t max)
Get length of string.
Definition: string.c:255
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
uint32_t len
Length.
Definition: ena.h:14
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
void * generic_memmove(void *dest, const void *src, size_t len)
Copy (possibly overlapping) memory region.
Definition: string.c:97
char * strndup(const char *src, size_t max)
Duplicate string.
Definition: string.c:392
char * strcat(char *dest, const char *src)
Concatenate string.
Definition: string.c:368
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
uint32_t first
Length to skip in first segment.
Definition: pccrc.h:23
String functions.
void * generic_memset(void *dest, int character, size_t len)
Fill memory region.
Definition: string.c:47