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