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 dnul Terminating NUL of destination string
325  */
326 char * stpcpy ( 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 ( ( char * ) dest_bytes );
337 }
338 
339 /**
340  * Copy string
341  *
342  * @v dest Destination string
343  * @v src Source string
344  * @ret dest Destination string
345  */
346 char * strcpy ( char *dest, const char *src ) {
347 
348  stpcpy ( dest, src );
349  return dest;
350 }
351 
352 /**
353  * Copy string
354  *
355  * @v dest Destination string
356  * @v src Source string
357  * @v max Maximum length
358  * @ret dest Destination string
359  */
360 char * strncpy ( char *dest, const char *src, size_t max ) {
361  const uint8_t *src_bytes = ( ( const uint8_t * ) src );
362  uint8_t *dest_bytes = ( ( uint8_t * ) dest );
363 
364  for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
365  *dest_bytes = *src_bytes;
366  if ( ! *dest_bytes )
367  break;
368  }
369  while ( max-- )
370  *(dest_bytes++) = '\0';
371  return dest;
372 }
373 
374 /**
375  * Concatenate string
376  *
377  * @v dest Destination string
378  * @v src Source string
379  * @ret dest Destination string
380  */
381 char * strcat ( char *dest, const char *src ) {
382 
383  strcpy ( ( dest + strlen ( dest ) ), src );
384  return dest;
385 }
386 
387 /**
388  * Duplicate string
389  *
390  * @v src Source string
391  * @ret dup Duplicated string, or NULL if allocation failed
392  */
393 char * strdup ( const char *src ) {
394 
395  return strndup ( src, ~( ( size_t ) 0 ) );
396 }
397 
398 /**
399  * Duplicate string
400  *
401  * @v src Source string
402  * @v max Maximum length
403  * @ret dup Duplicated string, or NULL if allocation failed
404  */
405 char * strndup ( const char *src, size_t max ) {
406  size_t len = strnlen ( src, max );
407  char *dup;
408 
409  dup = malloc ( len + 1 /* NUL */ );
410  if ( dup ) {
411  memcpy ( dup, src, len );
412  dup[len] = '\0';
413  }
414  return dup;
415 }
416 
417 /**
418  * Calculate digit value
419  *
420  * @v character Digit character
421  * @ret digit Digit value
422  *
423  * Invalid digits will be returned as a value greater than or equal to
424  * the numeric base.
425  */
426 unsigned int digit_value ( unsigned int character ) {
427 
428  if ( character >= 'a' )
429  return ( character - ( 'a' - 10 ) );
430  if ( character >= 'A' )
431  return ( character - ( 'A' - 10 ) );
432  if ( character <= '9' )
433  return ( character - '0' );
434  return character;
435 }
436 
437 /**
438  * Preprocess string for strtoul() or strtoull()
439  *
440  * @v string String
441  * @v negate Final value should be negated
442  * @v base Numeric base
443  * @ret string Remaining string
444  */
445 static const char * strtoul_pre ( const char *string, int *negate, int *base ) {
446 
447  /* Skip any leading whitespace */
448  while ( isspace ( *string ) )
449  string++;
450 
451  /* Process arithmetic sign, if present */
452  *negate = 0;
453  if ( *string == '-' ) {
454  string++;
455  *negate = 1;
456  } else if ( *string == '+' ) {
457  string++;
458  }
459 
460  /* Process base, if present */
461  if ( *base == 0 ) {
462  *base = 10;
463  if ( *string == '0' ) {
464  string++;
465  *base = 8;
466  if ( ( *string & ~0x20 ) == 'X' ) {
467  string++;
468  *base = 16;
469  }
470  }
471  }
472 
473  return string;
474 }
475 
476 /**
477  * Convert string to numeric value
478  *
479  * @v string String
480  * @v endp End pointer (or NULL)
481  * @v base Numeric base (or zero to autodetect)
482  * @ret value Numeric value
483  */
484 unsigned long strtoul ( const char *string, char **endp, int base ) {
485  unsigned long value = 0;
486  unsigned int digit;
487  int negate;
488 
489  /* Preprocess string */
490  string = strtoul_pre ( string, &negate, &base );
491 
492  /* Process digits */
493  for ( ; ; string++ ) {
494  digit = digit_value ( *string );
495  if ( digit >= ( unsigned int ) base )
496  break;
497  value = ( ( value * base ) + digit );
498  }
499 
500  /* Negate value if, applicable */
501  if ( negate )
502  value = -value;
503 
504  /* Fill in end pointer, if applicable */
505  if ( endp )
506  *endp = ( ( char * ) string );
507 
508  return value;
509 }
510 
511 /**
512  * Convert string to numeric value
513  *
514  * @v string String
515  * @v endp End pointer (or NULL)
516  * @v base Numeric base (or zero to autodetect)
517  * @ret value Numeric value
518  */
519 unsigned long long strtoull ( const char *string, char **endp, int base ) {
520  unsigned long long value = 0;
521  unsigned int digit;
522  int negate;
523 
524  /* Preprocess string */
525  string = strtoul_pre ( string, &negate, &base );
526 
527  /* Process digits */
528  for ( ; ; string++ ) {
529  digit = digit_value ( *string );
530  if ( digit >= ( unsigned int ) base )
531  break;
532  value = ( ( value * base ) + digit );
533  }
534 
535  /* Negate value if, applicable */
536  if ( negate )
537  value = -value;
538 
539  /* Fill in end pointer, if applicable */
540  if ( endp )
541  *endp = ( ( char * ) string );
542 
543  return value;
544 }
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition: string.c:153
uint32_t base
Base.
Definition: librm.h:252
static const void * src
Definition: string.h:47
#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:484
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:289
uint32_t first
First block in range.
Definition: pccrr.h:14
unsigned long long strtoull(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:519
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:426
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:186
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:360
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 * stpcpy(char *dest, const char *src)
Copy string.
Definition: string.c:326
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:346
static const char * strtoul_pre(const char *string, int *negate, int *base)
Preprocess string for strtoul() or strtoull()
Definition: string.c:445
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:393
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
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
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" return dest
Definition: string.h:150
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:405
char * strcat(char *dest, const char *src)
Concatenate string.
Definition: string.c:381
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
static __always_inline int off_t userptr_t second
Definition: librm.h:166
String functions.
void * generic_memset(void *dest, int character, size_t len)
Fill memory region.
Definition: string.c:47