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 FILE_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  */
48 void * 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  */
64 void * 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  */
81 void * 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  */
98 void * 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  */
115 int 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  */
136 void * 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  */
154 void * 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  */
174 int 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  */
187 int 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  */
209 int 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  */
222 int 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  */
244 size_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  */
256 size_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  */
272 char * 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  */
290 char * 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  */
310 char * 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  */
327 char * 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  */
347 char * 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  */
361 char * 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  */
382 char * 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  */
394 char * 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  */
406 char * 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  */
427 unsigned 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  */
446 static 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  */
485 unsigned 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  */
520 unsigned 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 }
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition: string.c:154
uint32_t base
Base.
Definition: librm.h:138
#define max(x, y)
Definition: ath.h:41
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:485
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:290
uint32_t first
First block in range.
Definition: pccrr.h:15
unsigned long long strtoull(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:520
uint32_t string
Definition: multiboot.h:14
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition: string.c:209
int strncasecmp(const char *first, const char *second, size_t max)
Compare case-insensitive strings.
Definition: string.c:222
Character types.
void * generic_memcpy(void *dest, const void *src, size_t len)
Copy memory region (forwards)
Definition: string.c:64
unsigned int digit_value(unsigned int character)
Calculate digit value.
Definition: string.c:427
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:187
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:136
uint32_t start
Starting offset.
Definition: netvsc.h:12
static int toupper(int character)
Convert character to upper case.
Definition: ctype.h:121
char * strncpy(char *dest, const char *src, size_t max)
Copy string.
Definition: string.c:361
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:310
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * stpcpy(char *dest, const char *src)
Copy string.
Definition: string.c:327
static const void * src
Definition: string.h:48
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
ring len
Length.
Definition: dwmac.h:231
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:347
static const char * strtoul_pre(const char *string, int *negate, int *base)
Preprocess string for strtoul() or strtoull()
Definition: string.c:446
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:272
FILE_SECBOOT(PERMITTED)
void * generic_memcpy_reverse(void *dest, const void *src, size_t len)
Copy memory region (backwards)
Definition: string.c:81
char * strdup(const char *src)
Duplicate string.
Definition: string.c:394
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:42
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
unsigned char uint8_t
Definition: stdint.h:10
size_t strnlen(const char *src, size_t max)
Get length of string.
Definition: string.c:256
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:621
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:174
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:151
void * generic_memmove(void *dest, const void *src, size_t len)
Copy (possibly overlapping) memory region.
Definition: string.c:98
char * strndup(const char *src, size_t max)
Duplicate string.
Definition: string.c:406
char * strcat(char *dest, const char *src)
Concatenate string.
Definition: string.c:382
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:115
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
String functions.
void * generic_memset(void *dest, int character, size_t len)
Fill memory region.
Definition: string.c:48