2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
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.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
41 * @v dest Destination region
42 * @v character Fill character
44 * @ret dest Destination region
46 void * generic_memset ( void *dest, int character, size_t len ) {
47 uint8_t *dest_bytes = dest;
50 *(dest_bytes++) = character;
57 * @v dest Destination region
58 * @v src Source region
60 * @ret dest Destination region
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;
67 *(dest_bytes++) = *(src_bytes++);
72 * Copy (possibly overlapping) memory region
74 * @v dest Destination region
75 * @v src Source region
77 * @ret dest Destination region
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 );
84 return memcpy ( dest, src, len );
86 *(--dest_bytes) = *(--src_bytes);
91 * Compare memory regions
93 * @v first First region
94 * @v second Second region
96 * @ret diff Difference
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;
104 diff = ( *(second_bytes++) - *(first_bytes++) );
112 * Find character within a memory region
114 * @v src Source region
115 * @v character Character to find
117 * @ret found Found character, or NULL if not found
119 void * memchr ( const void *src, int character, size_t len ) {
120 const uint8_t *src_bytes = src;
122 for ( ; len-- ; src_bytes++ ) {
123 if ( *src_bytes == character )
124 return ( ( void * ) src_bytes );
130 * Swap memory regions
132 * @v first First region
133 * @v second Second region
135 * @ret first First region
137 void * memswap ( void *first, void *second, size_t len ) {
138 uint8_t *first_bytes = first;
139 uint8_t *second_bytes = second;
142 for ( ; len-- ; first_bytes++, second_bytes++ ) {
144 *first_bytes = *second_bytes;
145 *second_bytes = temp;
153 * @v first First string
154 * @v second Second string
155 * @ret diff Difference
157 int strcmp ( const char *first, const char *second ) {
159 return strncmp ( first, second, ~( ( size_t ) 0 ) );
165 * @v first First string
166 * @v second Second string
167 * @v max Maximum length to compare
168 * @ret diff Difference
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 );
175 for ( ; max-- ; first_bytes++, second_bytes++ ) {
176 diff = ( *second_bytes - *first_bytes );
179 if ( ! *first_bytes )
186 * Compare case-insensitive strings
188 * @v first First string
189 * @v second Second string
190 * @ret diff Difference
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 );
197 for ( ; ; first_bytes++, second_bytes++ ) {
198 diff = ( toupper ( *second_bytes ) -
199 toupper ( *first_bytes ) );
202 if ( ! *first_bytes )
208 * Get length of string
213 size_t strlen ( const char *src ) {
215 return strnlen ( src, ~( ( size_t ) 0 ) );
219 * Get length of string
222 * @v max Maximum length
225 size_t strnlen ( const char *src, size_t max ) {
226 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
229 while ( max-- && *(src_bytes++) )
235 * Find character within a string
238 * @v character Character to find
239 * @ret found Found character, or NULL if not found
241 char * strchr ( const char *src, int character ) {
242 const uint8_t *src_bytes = ( ( const uint8_t * ) src );
244 for ( ; ; src_bytes++ ) {
245 if ( *src_bytes == character )
246 return ( ( char * ) src_bytes );
253 * Find rightmost character within a string
256 * @v character Character to find
257 * @ret found Found character, or NULL if not found
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;
265 for ( src_bytes-- ; src_bytes >= start ; src_bytes-- ) {
266 if ( *src_bytes == character )
267 return ( ( char * ) src_bytes );
276 * @v needle Substring
277 * @ret found Found substring, or NULL if not found
279 char * strstr ( const char *haystack, const char *needle ) {
280 size_t len = strlen ( needle );
282 for ( ; *haystack ; haystack++ ) {
283 if ( memcmp ( haystack, needle, len ) == 0 )
284 return ( ( char * ) haystack );
292 * @v dest Destination string
293 * @v src Source string
294 * @ret dest Destination string
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 );
300 /* We cannot use strncpy(), since that would pad the destination */
301 for ( ; ; src_bytes++, dest_bytes++ ) {
302 *dest_bytes = *src_bytes;
312 * @v dest Destination string
313 * @v src Source string
314 * @v max Maximum length
315 * @ret dest Destination string
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 );
321 for ( ; max ; max--, src_bytes++, dest_bytes++ ) {
322 *dest_bytes = *src_bytes;
327 *(dest_bytes++) = '\0';
334 * @v dest Destination string
335 * @v src Source string
336 * @ret dest Destination string
338 char * strcat ( char *dest, const char *src ) {
340 strcpy ( ( dest + strlen ( dest ) ), src );
347 * @v src Source string
348 * @ret dup Duplicated string, or NULL if allocation failed
350 char * strdup ( const char *src ) {
352 return strndup ( src, ~( ( size_t ) 0 ) );
358 * @v src Source string
359 * @v max Maximum length
360 * @ret dup Duplicated string, or NULL if allocation failed
362 char * strndup ( const char *src, size_t max ) {
363 size_t len = strnlen ( src, max );
366 dup = malloc ( len + 1 /* NUL */ );
368 memcpy ( dup, src, len );
375 * Calculate digit value
377 * @v character Digit character
378 * @ret digit Digit value
380 * Invalid digits will be returned as a value greater than or equal to
383 unsigned int digit_value ( unsigned int character ) {
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' );
395 * Preprocess string for strtoul() or strtoull()
398 * @v negate Final value should be negated
399 * @v base Numeric base
400 * @ret string Remaining string
402 static const char * strtoul_pre ( const char *string, int *negate, int *base ) {
404 /* Skip any leading whitespace */
405 while ( isspace ( *string ) )
408 /* Process arithmetic sign, if present */
410 if ( *string == '-' ) {
413 } else if ( *string == '+' ) {
417 /* Process base, if present */
420 if ( *string == '0' ) {
423 if ( ( *string & ~0x20 ) == 'X' ) {
434 * Convert string to numeric value
437 * @v endp End pointer (or NULL)
438 * @v base Numeric base (or zero to autodetect)
439 * @ret value Numeric value
441 unsigned long strtoul ( const char *string, char **endp, int base ) {
442 unsigned long value = 0;
446 /* Preprocess string */
447 string = strtoul_pre ( string, &negate, &base );
450 for ( ; ; string++ ) {
451 digit = digit_value ( *string );
452 if ( digit >= ( unsigned int ) base )
454 value = ( ( value * base ) + digit );
457 /* Negate value if, applicable */
461 /* Fill in end pointer, if applicable */
463 *endp = ( ( char * ) string );
469 * Convert string to numeric value
472 * @v endp End pointer (or NULL)
473 * @v base Numeric base (or zero to autodetect)
474 * @ret value Numeric value
476 unsigned long long strtoull ( const char *string, char **endp, int base ) {
477 unsigned long long value = 0;
481 /* Preprocess string */
482 string = strtoul_pre ( string, &negate, &base );
485 for ( ; ; string++ ) {
486 digit = digit_value ( *string );
487 if ( digit >= ( unsigned int ) base )
489 value = ( ( value * base ) + digit );
492 /* Negate value if, applicable */
496 /* Fill in end pointer, if applicable */
498 *endp = ( ( char * ) string );