diff --git a/libc/include/string.h b/libc/include/string.h index a39ab0e..727e9ea 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -1,14 +1,164 @@ -#pragma once +/* + * Copyright (c) 2011, 2012, 2013, 2014, 2017, 2024 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string.h + * String operations. + */ +#ifndef _INCLUDE_STRING_H +#define _INCLUDE_STRING_H + +#include + +#if __USE_SORTIX || __USE_POSIX +#include +#endif + +#ifndef NULL +#define __need_NULL #include +#endif -char *strchr(const char *s, int c); -int strcmp(const char *s1, const char *s2); -char *strcpy(char *restrict d, const char *restrict s); -size_t strlen(const char *s); -size_t strspn(const char *s, const char *a); -char *strpbrk(const char *s, const char *a); -int strcoll(const char *s1, const char *s2); +#ifndef __size_t_defined +#define __size_t_defined +#define __need_size_t +#include +#endif -void *memcpy(void *restrict dest, const void *restrict src, size_t n); -int memcmp(const void *s1, const void *s2, size_t n); +#if __USE_SORTIX || 2008 <= __USE_POSIX +#ifndef __locale_t_defined +#define __locale_t_defined +/* TODO: figure out what this does and typedef it properly. This is just a + temporary assignment. */ +typedef int __locale_t; +typedef __locale_t locale_t; +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void* memchr(const void*, int, size_t); +int memcmp(const void*, const void*, size_t); +void* memcpy(void* __restrict, const void* __restrict, size_t); +void* memmove(void*, const void*, size_t); +void* memset(void*, int, size_t); +char* strcat(char* __restrict, const char* __restrict); +char* strchr(const char*, int); +int strcmp(const char*, const char*); +int strcoll(const char*, const char*); +char* strcpy(char* __restrict, const char* __restrict); +size_t strcspn(const char*, const char*); +char* strerror(int errnum); +size_t strlen(const char*); +char* strncat(char* __restrict, const char* __restrict, size_t); +int strncmp(const char*, const char*, size_t); +char* strncpy(char* __restrict, const char* __restrict, size_t); +char* strpbrk(const char*, const char*); +char* strrchr(const char*, int); +size_t strspn(const char*, const char*); +char* strstr(const char*, const char*); +char* strtok(char* __restrict, const char* __restrict); +size_t strxfrm(char* __restrict, const char* __restrict, size_t); + +/* Functions from early POSIX. */ +#if __USE_SORTIX || __USE_POSIX +int strcasecmp(const char* a, const char* b); +int strncasecmp(const char* a, const char* b, size_t n); +#endif + +/* Functions from early XOPEN. */ +#if __USE_SORTIX || __USE_XOPEN +void* memccpy(void* __restrict, const void* __restrict, int, size_t); +int ffs(int); +#endif + +/* Functions from XOPEN 420 gone into POSIX 2008. */ +#if __USE_SORTIX || 420 <= __USE_XOPEN || 200809L <= __USE_POSIX +char* strdup(const char*); +#endif + +/* Functions from POSIX 2001. */ +#if __USE_SORTIX || 200112L <= __USE_POSIX +char* strerror_l(int, locale_t); +int strerror_r(int, char*, size_t); +char* strtok_r(char* __restrict, const char* __restrict, char** __restrict); +#endif + +/* Functions from POSIX 2008. */ +#if __USE_SORTIX || 200809L <= __USE_POSIX +char* stpcpy(char* __restrict, const char* __restrict); +char* stpncpy(char* __restrict, const char* __restrict, size_t); +int strcoll_l(const char*, const char*, locale_t); +char* strndup(const char*, size_t); +size_t strnlen(const char*, size_t); +char* strsignal(int signum); +size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t); +#endif + +/* Functions from POSIX 2024. */ +#if __USE_SORTIX || 202405L <= __USE_POSIX +size_t strlcat(char* __restrict, const char* __restrict, size_t); +size_t strlcpy(char* __restrict, const char* __restrict, size_t); +#endif + +#if __USE_SORTIX || 800 <= __USE_XOPEN +int ffsl(long int); +int ffsll(long long int); +#endif + +/* Functions copied from elsewhere. */ +#if __USE_SORTIX +void explicit_bzero(void*, size_t); + +void* memrchr(const void*, int, size_t); +/* TODO: strcasecmp_l */ +char* strchrnul(const char* str, int c); +char* stresep(char**, const char*, int); +/* TODO: strncasecmp_l */ +char* strsep(char**, const char*); +int strverscmp(const char*, const char*); +int timingsafe_memcmp(const void*, const void*, size_t); +#endif + +#if __USE_SORTIX +/* Duplicate S, returning an identical alloca'd string. */ +#define strdupa(s) \ + (__extension__ \ + ({ \ + const char* __old = (s); \ + size_t __len = strlen(__old) + 1; \ + char* __new = (char*) __builtin_alloca(__len); \ + (char*) memcpy(__new, __old, __len); \ + })) + +/* Return an alloca'd copy of at most N bytes of string. */ +#define strndupa(s, n) \ + (__extension__ \ + ({ \ + __const char* __old = (s); \ + size_t __len = strnlen(__old, (n)); \ + char* __new = (char*) __builtin_alloca(__len + 1); \ + __new[__len] = '\0'; \ + (char*) memcpy(__new, __old, __len); \ + })) +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/libc/string/explicit_bzero.c b/libc/string/explicit_bzero.c new file mode 100644 index 0000000..e3998a0 --- /dev/null +++ b/libc/string/explicit_bzero.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/explicit_bzero.c + * Initializes a region of memory to a byte value in a manner that is not + * optimized away by the compiler. + */ + +#include + +// TODO: Employ special compiler support to ensure this is not optimized away. +void explicit_bzero(void* dest_ptr, size_t size) +{ + volatile unsigned char* dest = (volatile unsigned char*) dest_ptr; + for ( size_t i = 0; i < size; i++ ) + dest[i] = 0; +} diff --git a/libc/string/ffs.c b/libc/string/ffs.c new file mode 100644 index 0000000..407e0f7 --- /dev/null +++ b/libc/string/ffs.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/ffs.c + * Returns the index of the first set bit. + */ + +#include + +int ffs(int val) +{ + return __builtin_ffs(val); +} diff --git a/libc/string/ffsl.c b/libc/string/ffsl.c new file mode 100644 index 0000000..a004246 --- /dev/null +++ b/libc/string/ffsl.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/ffsl.c + * Returns the index of the first set bit. + */ + +#include + +int ffsl(long int val) +{ + return __builtin_ffsl(val); +} diff --git a/libc/string/ffsll.c b/libc/string/ffsll.c new file mode 100644 index 0000000..1189914 --- /dev/null +++ b/libc/string/ffsll.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/ffsll.c + * Returns the index of the first set bit. + */ + +#include + +int ffsll(long long int val) +{ + return __builtin_ffsll(val); +} diff --git a/libc/string/memccpy.c b/libc/string/memccpy.c new file mode 100644 index 0000000..7b4a733 --- /dev/null +++ b/libc/string/memccpy.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memccpy.c + * Copy memory until length is met or character is encountered. + */ + +#include +#include + +void* memccpy(void* dest_ptr, const void* src_ptr, int c, size_t n) +{ + unsigned char* dest = (unsigned char*) dest_ptr; + const unsigned char* src = (const unsigned char*) src_ptr; + for ( size_t i = 0; i < n; i++ ) + { + if ( (dest[i] = src[i]) == (unsigned char) c ) + return dest + i + 1; + } + return NULL; +} diff --git a/libc/string/memchr.c b/libc/string/memchr.c new file mode 100644 index 0000000..d7e41dd --- /dev/null +++ b/libc/string/memchr.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memchr.c + * Scans memory for a character. + */ + +#include + +void* memchr(const void* s, int c, size_t size) +{ + const unsigned char* buf = (const unsigned char*) s; + for ( size_t i = 0; i < size; i++ ) + if ( buf[i] == (unsigned char) c ) + return (void*) (buf + i); + return NULL; +} diff --git a/libc/string/memcmp.c b/libc/string/memcmp.c new file mode 100644 index 0000000..1331452 --- /dev/null +++ b/libc/string/memcmp.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memcmp.c + * Compares two memory regions. + */ + +#include + +int memcmp(const void* a_ptr, const void* b_ptr, size_t size) +{ + const unsigned char* a = (const unsigned char*) a_ptr; + const unsigned char* b = (const unsigned char*) b_ptr; + for ( size_t i = 0; i < size; i++ ) + { + if ( a[i] < b[i] ) + return -1; + if ( a[i] > b[i] ) + return +1; + } + return 0; +} diff --git a/libc/string/memcpy.c b/libc/string/memcpy.c new file mode 100644 index 0000000..bb5e836 --- /dev/null +++ b/libc/string/memcpy.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011, 2012, 2014, 2015, 2016 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memcpy.c + * Copy memory between non-overlapping regions. + */ + +#include +#include +#include +#include + +#if defined(__is_sortix_libk) +#include +#endif + +inline static +void* memcpy_slow(void* restrict dst_ptr, + const void* restrict src_ptr, + size_t size) +{ + unsigned char* restrict dst = (unsigned char* restrict) dst_ptr; + const unsigned char* restrict src = (const unsigned char* restrict) src_ptr; + for ( size_t i = 0; i < size; i++ ) + dst[i] = src[i]; + return dst_ptr; +} + +void* memcpy(void* restrict dst_ptr, + const void* restrict src_ptr, + size_t size) +{ + if ( dst_ptr == src_ptr || !size ) + return dst_ptr; + + void* dst_end = (char*) dst_ptr + size; + const void* src_end = (const char*) src_ptr + size; + if ( (dst_ptr < src_ptr && src_ptr < dst_end) || + (src_ptr < dst_ptr && dst_ptr < src_end) ) + { +#if defined(__is_sortix_libk) + libk_overlapping_memcpy(); +#else + struct scram_undefined_behavior info; + info.filename = __FILE__; + info.line = __LINE__; + info.column = 0; + info.violation = "overlapping memcpy"; + scram(SCRAM_UNDEFINED_BEHAVIOR, &info); +#endif + } + +#if 8 < __SIZEOF_LONG__ +#warning "you should add support for your unexpectedly large unsigned long." + return memcpy_slow(dst_ptr, src_ptr, size); +#else + unsigned long unalign_mask = sizeof(unsigned long) - 1; + unsigned long src_unalign = (unsigned long) src_ptr & unalign_mask; + unsigned long dst_unalign = (unsigned long) dst_ptr & unalign_mask; + if ( src_unalign != dst_unalign ) + return memcpy_slow(dst_ptr, src_ptr, size); + + union + { + unsigned long srcval; + const unsigned char* restrict src8; + const uint16_t* restrict src16; + const uint32_t* restrict src32; + const uint64_t* restrict src64; + const unsigned long* restrict srcul; + } su; + su.srcval = (unsigned long) src_ptr; + + union + { + unsigned long dstval; + unsigned char* restrict dst8; + uint16_t* restrict dst16; + uint32_t* restrict dst32; + uint64_t* restrict dst64; + unsigned long* restrict dstul; + } du; + du.dstval = (unsigned long) dst_ptr; + + if ( dst_unalign ) + { + if ( 1 <= size && !(du.dstval & (1-1)) && (du.dstval & (2-1)) ) + *du.dst8++ = *su.src8++, + size -= 1; + + if ( 2 <= size && !(du.dstval & (2-1)) && (du.dstval & (4-1)) ) + *du.dst16++ = *su.src16++, + size -= 2; + + #if 8 <= __SIZEOF_LONG__ + if ( 4 <= size && !(du.dstval & (4-1)) && (du.dstval & (8-1)) ) + *du.dst32++ = *su.src32++, + size -= 4; + #endif + } + + size_t num_copies = size / sizeof(unsigned long); + for ( size_t i = 0; i < num_copies; i++ ) + *du.dstul++ = *su.srcul++; + + size -= num_copies * sizeof(unsigned long); + + if ( size ) + { + #if 8 <= __SIZEOF_LONG__ + if ( 4 <= size ) + *du.dst32++ = *su.src32++, + size -= 4; + #endif + + if ( 2 <= size ) + *du.dst16++ = *su.src16++, + size -= 2; + + if ( 1 <= size ) + *du.dst8++ = *su.src8++, + size -= 1; + } + + return dst_ptr; +#endif +} diff --git a/libc/string/memmove.c b/libc/string/memmove.c new file mode 100644 index 0000000..a73447f --- /dev/null +++ b/libc/string/memmove.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memmove.c + * Copy memory between potentionally overlapping regions. + */ + +#include +#include + +void* memmove(void* dest_ptr, const void* src_ptr, size_t n) +{ + unsigned char* dest = (unsigned char*) dest_ptr; + const unsigned char* src = (const unsigned char*) src_ptr; + if ( (uintptr_t) dest < (uintptr_t) src ) + { + for ( size_t i = 0; i < n; i++ ) + dest[i] = src[i]; + } + else + { + for ( size_t i = 0; i < n; i++ ) + dest[n-(i+1)] = src[n-(i+1)]; + } + return dest_ptr; +} diff --git a/libc/string/memrchr.c b/libc/string/memrchr.c new file mode 100644 index 0000000..8500ebf --- /dev/null +++ b/libc/string/memrchr.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memrchr.c + * Scans memory in reverse directory for a character. + */ + +#include +#include + +void* memrchr(const void* ptr, int c, size_t n) +{ + const unsigned char* buf = (const unsigned char*) ptr; + for ( size_t i = n; i != 0; i-- ) + if ( buf[i-1] == (unsigned char) c ) + return (void*) (buf + i-1); + return NULL; +} diff --git a/libc/string/memset.c b/libc/string/memset.c new file mode 100644 index 0000000..e247ac6 --- /dev/null +++ b/libc/string/memset.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/memset.c + * Initializes a region of memory to a byte value. + */ + +#include +#include + +#include <__/wordsize.h> + +void* memset(void* dest_ptr, int value, size_t length) +{ + unsigned char* dest = (unsigned char*) dest_ptr; +#if __WORDSIZE == 32 || __WORDSIZE == 64 + if ( ((uintptr_t) dest_ptr & (sizeof(unsigned long) - 1)) == 0 ) + { + unsigned long* ulong_dest = (unsigned long*) dest; + size_t ulong_length = length / sizeof(unsigned long); +#if __WORDSIZE == 32 + unsigned long ulong_value = + (unsigned long) ((unsigned char) value) << 0 | + (unsigned long) ((unsigned char) value) << 8 | + (unsigned long) ((unsigned char) value) << 16 | + (unsigned long) ((unsigned char) value) << 24; +#elif __WORDSIZE == 64 + unsigned long ulong_value = + (unsigned long) ((unsigned char) value) << 0 | + (unsigned long) ((unsigned char) value) << 8 | + (unsigned long) ((unsigned char) value) << 16 | + (unsigned long) ((unsigned char) value) << 24 | + (unsigned long) ((unsigned char) value) << 32 | + (unsigned long) ((unsigned char) value) << 40 | + (unsigned long) ((unsigned char) value) << 48 | + (unsigned long) ((unsigned char) value) << 56; +#endif + for ( size_t i = 0; i < ulong_length; i++ ) + ulong_dest[i] = ulong_value; + dest += ulong_length * sizeof(unsigned long); + length -= ulong_length * sizeof(unsigned long); + } +#endif + for ( size_t i = 0; i < length; i++ ) + dest[i] = (unsigned char) value; + return dest_ptr; +} diff --git a/libc/string/stpcpy.c b/libc/string/stpcpy.c new file mode 100644 index 0000000..c3876c2 --- /dev/null +++ b/libc/string/stpcpy.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/stpcpy.c + * Copy a string returning a pointer to its end. + */ + +#include + +char* stpcpy(char* dest, const char* src) +{ + size_t index; + for ( index = 0; src[index]; index++ ) + dest[index] = src[index]; + dest[index] = '\0'; + return dest + index; +} diff --git a/libc/string/stpncpy.c b/libc/string/stpncpy.c new file mode 100644 index 0000000..ad1a729 --- /dev/null +++ b/libc/string/stpncpy.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/stpncpy.c + * Copies a string into a fixed size buffer and returns last byte. + */ + +#include + +char* stpncpy(char* dest, const char* src, size_t n) +{ + size_t i; + for ( i = 0; i < n && src[i] != '\0'; i++ ) + dest[i] = src[i]; + char* ret = dest + i; + for ( ; i < n; i++ ) + dest[i] = '\0'; + return ret; +} diff --git a/libc/string/strcasecmp.c b/libc/string/strcasecmp.c new file mode 100644 index 0000000..8c0e4a5 --- /dev/null +++ b/libc/string/strcasecmp.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcasecmp.c + * Compares two strings ignoring case. + */ + +#include +#include +#include + +int strcasecmp(const char* a, const char* b) +{ + for ( size_t i = 0; true; i++ ) + { + unsigned char ac = (unsigned char) tolower((unsigned char) a[i]); + unsigned char bc = (unsigned char) tolower((unsigned char) b[i]); + if ( ac == '\0' && bc == '\0' ) + return 0; + if ( ac < bc ) + return -1; + if ( ac > bc ) + return 1; + } +} diff --git a/libc/string/strcat.c b/libc/string/strcat.c new file mode 100644 index 0000000..fb348dc --- /dev/null +++ b/libc/string/strcat.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcat.c + * Appends a string onto another string. + */ + +#include + +char* strcat(char* dest, const char* src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} diff --git a/libc/string/strchr.c b/libc/string/strchr.c new file mode 100644 index 0000000..d18cdc4 --- /dev/null +++ b/libc/string/strchr.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strchr.c + * Searches a string for a specific character. + */ + +#include + +char* strchr(const char* str, int uc) +{ + char* ret = strchrnul(str, uc); + return (unsigned char) uc == ((unsigned char*) ret)[0] ? ret : NULL; +} diff --git a/libc/string/strchrnul.c b/libc/string/strchrnul.c new file mode 100644 index 0000000..8dc4458 --- /dev/null +++ b/libc/string/strchrnul.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strchrnul.c + * Searches a string for a specific character. + */ + +#include +#include + +char* strchrnul(const char* str, int uc) +{ + const unsigned char* ustr = (const unsigned char*) str; + for ( size_t i = 0; true; i++) + if ( ustr[i] == (unsigned char) uc || !ustr[i] ) + return (char*) str + i; +} diff --git a/libc/string/strcmp.c b/libc/string/strcmp.c new file mode 100644 index 0000000..be8b97a --- /dev/null +++ b/libc/string/strcmp.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcmp.c + * Compares two strings. + */ + +#include +#include + +int strcmp(const char* a, const char* b) +{ + for ( size_t i = 0; true; i++ ) + { + unsigned char ac = (unsigned char) a[i]; + unsigned char bc = (unsigned char) b[i]; + if ( ac == '\0' && bc == '\0' ) + return 0; + if ( ac < bc ) + return -1; + if ( ac > bc ) + return 1; + } +} diff --git a/libc/string/strcoll.c b/libc/string/strcoll.c new file mode 100644 index 0000000..d275090 --- /dev/null +++ b/libc/string/strcoll.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcoll.c + * Compare two strings using the current locale. + */ + +#include + +int strcoll(const char* s1, const char* s2) +{ + // TODO: Pay attention to locales. + return strcmp(s1, s2); +} diff --git a/libc/string/strcoll_l.c b/libc/string/strcoll_l.c new file mode 100644 index 0000000..15eb017 --- /dev/null +++ b/libc/string/strcoll_l.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcoll_l.c + * Compare two strings using the given locale. + */ + +#include + +int strcoll_l(const char* s1, const char* s2, locale_t locale) +{ + (void) locale; + return strcoll(s1, s2); +} diff --git a/libc/string/strcpy.c b/libc/string/strcpy.c new file mode 100644 index 0000000..1827464 --- /dev/null +++ b/libc/string/strcpy.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcpy.c + * Copies a string and returns dest. + */ + +#include + +char* strcpy(char* dest, const char* src) +{ + size_t index; + for ( index = 0; src[index]; index++ ) + dest[index] = src[index]; + dest[index] = '\0'; + return dest; +} diff --git a/libc/string/strcspn.c b/libc/string/strcspn.c new file mode 100644 index 0000000..67a33ca --- /dev/null +++ b/libc/string/strcspn.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strcspn.c + * Search a string for a set of characters. + */ + +#include +#include + +size_t strcspn(const char* str, const char* reject) +{ + size_t reject_length = 0; + while ( reject[reject_length] ) + reject_length++; + for ( size_t result = 0; true; result++ ) + { + char c = str[result]; + if ( !c ) + return result; + bool matches = false; + for ( size_t i = 0; i < reject_length; i++ ) + { + if ( str[result] != reject[i] ) + continue; + matches = true; + break; + } + if ( matches ) + return result; + } +} diff --git a/libc/string/strdup.c b/libc/string/strdup.c new file mode 100644 index 0000000..66d073c --- /dev/null +++ b/libc/string/strdup.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strdup.c + * Creates a copy of a string. + */ + +#include +#include + +char* strdup(const char* input) +{ + size_t input_length = strlen(input); + char* result = (char*) malloc(input_length + 1); + if ( !result ) + return NULL; + memcpy(result, input, input_length + 1); + return result; +} diff --git a/libc/string/strerror.c b/libc/string/strerror.c new file mode 100644 index 0000000..1c4949e --- /dev/null +++ b/libc/string/strerror.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011-2016, 2020-2022, 2024 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strerror.c + * Convert error code to a string. + */ + +#include +#include + +char* strerror(int errnum) +{ + switch ( errnum ) + { + case ENOTBLK: return "Block device required"; + case ENODEV: return "No such device"; + case EBADF: return "Bad file descriptor"; + case EOVERFLOW: return "Value too large to be stored in data type"; + case ENOENT: return "No such file or directory"; + case ENOSPC: return "No space left on device"; + case EEXIST: return "File exists"; + case EROFS: return "Read-only file system"; + case EINVAL: return "Invalid argument"; + case ENOTDIR: return "Not a directory"; + case ENOMEM: return "Not enough memory"; + case ERANGE: return "Result too large"; + case EISDIR: return "Is a directory"; + case EPERM: return "Operation not permitted"; + case EIO: return "Input/output error"; + case ENOEXEC: return "Exec format error"; + case EACCES: return "Permission denied"; + case ESRCH: return "No such process"; + case ENOTTY: return "Not a tty"; + case ECHILD: return "No child processes"; + case ENOSYS: return "Function not implemented"; + case ENOTSUP: return "Operation not supported"; + case EBLOCKING: return "Operation is blocking"; + case EINTR: return "Interrupted function call"; + case ENOTEMPTY: return "Directory not empty"; + case EBUSY: return "Device or resource busy"; + case EPIPE: return "Broken pipe"; + case EILSEQ: return "Invalid byte sequence"; + case ELAKE: return "Sit by a lake"; + case EMFILE: return "Too many open files"; + case EAGAIN: return "Resource temporarily unavailable"; + case EEOF: return "End of file"; + case EBOUND: return "Out of bounds"; + case EINIT: return "Not initialized"; + case ENODRV: return "No such driver"; + case E2BIG: return "Argument list too long"; + case EFBIG: return "File too large"; + case EXDEV: return "Improper link"; + case ESPIPE: return "Cannot seek on stream"; + case ENAMETOOLONG: return "Filename too long"; + case ELOOP: return "Too many levels of symbolic links"; + case EMLINK: return "Too many links"; + case ENXIO: return "No such device or address"; + case EPROTONOSUPPORT: return "Protocol not supported"; + case EAFNOSUPPORT: return "Address family not supported"; + case ENOTSOCK: return "Not a socket"; + case EADDRINUSE: return "Address already in use"; + case ETIMEDOUT: return "Connection timed out"; + case ECONNREFUSED: return "Connection refused"; + case EDOM: return "Mathematics argument out of domain of function"; + case EINPROGRESS: return "Operation in progress"; + case EALREADY: return "Connection already in progress"; + case ESHUTDOWN: return "Cannot send after transport endpoint shutdown"; + case ECONNABORTED: return "Connection aborted"; + case ECONNRESET: return "Connection reset"; + case EADDRNOTAVAIL: return "Address not available"; + case EISCONN: return "Socket is connected"; + case EFAULT: return "Bad address"; + case EDESTADDRREQ: return "Destination address required"; + case EHOSTUNREACH: return "Host is unreachable"; + case EMSGSIZE: return "Message too long"; + case ENETDOWN: return "Network is down"; + case ENETRESET: return "Connection aborted by network"; + case ENETUNREACH: return "Network is unreachable"; + case ENOBUFS: return "No buffer space available"; + case ENOMSG: return "No message of the desired type"; + case ENOPROTOOPT: return "Protocol not available"; + case ENOTCONN: return "Socket is not connected"; + case EDEADLK: return "Resource deadlock avoided"; + case ENFILE: return "Too many open files in system"; + case EPROTOTYPE: return "Wrong protocol type for socket"; + case ENOLCK: return "No locks available"; + case ESIGPENDING: return "Signal is already pending"; + case ESTALE: return "Stale file handle"; + case EBADMSG: return "Bad message"; + case ECANCELED: return "Operation canceled"; + case EDQUOT: return "Disk quota exceeded"; + case EIDRM: return "Identifier removed"; + case EMULTIHOP: return "Multihop attempted"; + case ENOLINK: return "Link has been severed"; + case ENOTRECOVERABLE: return "State not recoverable"; + case EOWNERDEAD: return "Previous owner died"; + case EPROTO: return "Protocol error"; + case ETXTBSY: return "Text file busy"; + case ENOMOUNT: return "No such mountpoint"; + case ENOMEDIUM: return "No medium found"; + case EHOSTDOWN: return "Host is down"; + case ESOCKTNOSUPPORT: return "Socket type is not supported"; + default: return "Unknown error condition"; + } +} + +// TODO: After releasing Sortix 1.1, or after fixing ffmpeg, remove this symbol +// retained for compatibility. ffmpeg has a native sysroot issue where it +// accidentally taints it with the local system's headers instead of the +// sysroot headers, which accidentally pulls in an old removed symbol when +// bootstrapping on an old system. +weak_alias(strerror, sortix_strerror); diff --git a/libc/string/strerror_l.c b/libc/string/strerror_l.c new file mode 100644 index 0000000..5f238fd --- /dev/null +++ b/libc/string/strerror_l.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strerror_l.c + * Convert error code to a string. + */ + +#include + +char* strerror_l(int errnum, locale_t locale) +{ + (void) locale; + return (char*) strerror(errnum); +} diff --git a/libc/string/strerror_r.c b/libc/string/strerror_r.c new file mode 100644 index 0000000..a7cba7f --- /dev/null +++ b/libc/string/strerror_r.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2014, 2024 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strerror_r.c + * Convert error code to a string. + */ + +#include +#include + +int strerror_r(int errnum, char* dest, size_t dest_len) +{ + const char* msg = strerror(errnum); + if ( !msg ) + return -1; + if ( dest_len < strlen(msg) + 1 ) + return errno = ERANGE; + strcpy(dest, msg); + return 0; +} diff --git a/libc/string/stresep.c b/libc/string/stresep.c new file mode 100644 index 0000000..f8ecc0f --- /dev/null +++ b/libc/string/stresep.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/stresep.c + * Extract a token from a string while handling escape characters. + */ + +#include +#include + +char* stresep(char** string_ptr, const char* delim, int escape) +{ + char* token = *string_ptr; + if ( !token ) + return NULL; + size_t consumed_length = 0; + size_t token_length = 0; + bool escaped = false; + while ( true ) + { + char c = token[consumed_length++]; + bool true_nul = c == '\0'; + if ( !escaped && escape && (unsigned char) c == (unsigned char) escape ) + { + escaped = true; + continue; + } + if ( !escaped && c != '\0' ) + { + for ( size_t i = 0; delim[i]; i++ ) + { + if ( c != delim[i] ) + { + c = '\0'; + break; + } + } + } + token[token_length++] = c; + escaped = false; + if ( c == '\0' ) + { + *string_ptr = true_nul ? (char*) NULL : token + consumed_length; + return token; + } + } +} diff --git a/libc/string/strlcat.c b/libc/string/strlcat.c new file mode 100644 index 0000000..bf6a8d1 --- /dev/null +++ b/libc/string/strlcat.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strlcat.c + * Appends a string onto another string truncating if the string is too small. + */ + +#include + +size_t strlcat(char* restrict dest, const char* restrict src, size_t size) +{ + size_t dest_len = strnlen(dest, size); + if ( size <= dest_len ) + return dest_len + strlen(src); + return dest_len + strlcpy(dest + dest_len, src, size - dest_len); +} diff --git a/libc/string/strlcpy.c b/libc/string/strlcpy.c new file mode 100644 index 0000000..6cd5fad --- /dev/null +++ b/libc/string/strlcpy.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strlcpy.c + * Copies a string and truncates it if the destination is too small. + */ + +#include + +size_t strlcpy(char* restrict dest, const char* restrict src, size_t size) +{ + if ( !size ) + return strlen(src); + size_t result; + for ( result = 0; result < size-1 && src[result]; result++ ) + dest[result] = src[result]; + dest[result] = '\0'; + return result + strlen(src + result); +} diff --git a/libc/string/strlen.c b/libc/string/strlen.c new file mode 100644 index 0000000..baf405b --- /dev/null +++ b/libc/string/strlen.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strlen.c + * Returns the length of a string. + */ + +#include + +size_t strlen(const char* str) +{ + size_t ret = 0; + while ( str[ret] ) + ret++; + return ret; +} diff --git a/libc/string/strncasecmp.c b/libc/string/strncasecmp.c new file mode 100644 index 0000000..5865453 --- /dev/null +++ b/libc/string/strncasecmp.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strncasecmp.c + * Compares a prefix of two strings ignoring case. + */ + +#include +#include + +int strncasecmp(const char* a, const char* b, size_t max_count) +{ + for ( size_t i = 0; i < max_count; i++ ) + { + unsigned char ac = (unsigned char) tolower((unsigned char) a[i]); + unsigned char bc = (unsigned char) tolower((unsigned char) b[i]); + if ( ac == '\0' && bc == '\0' ) + return 0; + if ( ac < bc ) + return -1; + if ( ac > bc ) + return 1; + } + return 0; +} diff --git a/libc/string/strncat.c b/libc/string/strncat.c new file mode 100644 index 0000000..3d5a7d2 --- /dev/null +++ b/libc/string/strncat.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strncat.c + * Appends parts of a string onto another string. + */ + +#include + +char* strncat(char* dest, const char* src, size_t n) +{ + size_t dest_len = strlen(dest); + size_t i; + for ( i = 0; i < n && src[i] != '\0'; i++ ) + dest[dest_len + i] = src[i]; + dest[dest_len + i] = '\0'; + return dest; +} diff --git a/libc/string/strncmp.c b/libc/string/strncmp.c new file mode 100644 index 0000000..ea6a409 --- /dev/null +++ b/libc/string/strncmp.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strncmp.c + * Compares a prefix of two strings. + */ + +#include + +int strncmp(const char* a, const char* b, size_t max_count) +{ + for ( size_t i = 0; i < max_count; i++ ) + { + unsigned char ac = (unsigned char) a[i]; + unsigned char bc = (unsigned char) b[i]; + if ( ac == '\0' && bc == '\0' ) + return 0; + if ( ac < bc ) + return -1; + if ( ac > bc ) + return 1; + } + return 0; +} diff --git a/libc/string/strncpy.c b/libc/string/strncpy.c new file mode 100644 index 0000000..4f8ffc2 --- /dev/null +++ b/libc/string/strncpy.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strncpy.c + * Copies a string into a fixed size buffer and returns dest. + */ + +#include + +char* strncpy(char* dest, const char* src, size_t n) +{ + size_t i; + for ( i = 0; i < n && src[i] != '\0'; i++ ) + dest[i] = src[i]; + for ( ; i < n; i++ ) + dest[i] = '\0'; + return dest; +} diff --git a/libc/string/strndup.c b/libc/string/strndup.c new file mode 100644 index 0000000..c9ade08 --- /dev/null +++ b/libc/string/strndup.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strndup.c + * Creates a copy of a string. + */ + +#include +#include + +char* strndup(const char* input, size_t n) +{ + size_t input_size = strnlen(input, n); + char* result = (char*) malloc(input_size + 1); + if ( !result ) + return NULL; + memcpy(result, input, input_size); + result[input_size] = 0; + return result; +} diff --git a/libc/string/strnlen.c b/libc/string/strnlen.c new file mode 100644 index 0000000..a9c4955 --- /dev/null +++ b/libc/string/strnlen.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strnlen.c + * Returns the length of a fixed length string. + */ + +#include + +size_t strnlen(const char* str, size_t maxlen) +{ + size_t ret = 0; + while ( ret < maxlen && str[ret] ) + ret++; + return ret; +} diff --git a/libc/string/strpbrk.c b/libc/string/strpbrk.c new file mode 100644 index 0000000..e99b627 --- /dev/null +++ b/libc/string/strpbrk.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strpbrk.c + * Search a string for any of a set of characters. + */ + +#include + +char* strpbrk(const char* str, const char* accept) +{ + size_t reject_length = strcspn(str, accept); + if ( !str[reject_length] ) + return NULL; + return (char*) str + reject_length; +} diff --git a/libc/string/strrchr.c b/libc/string/strrchr.c new file mode 100644 index 0000000..4b28461 --- /dev/null +++ b/libc/string/strrchr.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strrchr.c + * Searches a string for a specific character. + */ + +#include +#include + +char* strrchr(const char* str, int uc) +{ + const unsigned char* ustr = (const unsigned char*) str; + const char* last = NULL; + for ( size_t i = 0; true; i++ ) + { + if ( ustr[i] == (unsigned char) uc ) + last = str + i; + if ( !ustr[i] ) + break; + } + return (char*) last; +} diff --git a/libc/string/strsep.c b/libc/string/strsep.c new file mode 100644 index 0000000..63eedb0 --- /dev/null +++ b/libc/string/strsep.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strsep.c + * Extract a token from a string. + */ + +#include + +char* strsep(char** string_ptr, const char* delim) +{ + char* token = *string_ptr; + if ( !token ) + return NULL; + size_t token_length = strcspn(token, delim); + if ( token[token_length] ) + { + token[token_length++] = '\0'; + *string_ptr = token + token_length; + } + else + { + *string_ptr = (char*) NULL; + } + return token; +} diff --git a/libc/string/strsignal.c b/libc/string/strsignal.c new file mode 100644 index 0000000..d5f884c --- /dev/null +++ b/libc/string/strsignal.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012, 2014, 2024 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strsignal.c + * Convert signal number to a string. + */ + +#include +#include + +char* strsignal(int signum) +{ + switch ( signum ) + { + case SIGHUP: return "Hangup"; + case SIGINT: return "Interrupt"; + case SIGQUIT: return "Quit"; + case SIGILL: return "Invalid instruction"; + case SIGTRAP: return "Trace/breakpoint trap"; + case SIGABRT: return "Aborted"; + case SIGBUS: return "Bus Error"; + case SIGFPE: return "Floating point exception"; + case SIGKILL: return "Killed"; + case SIGUSR1: return "User defined signal 1"; + case SIGSEGV: return "Segmentation fault"; + case SIGUSR2: return "User defined signal 2"; + case SIGPIPE: return "Broken pipe"; + case SIGALRM: return "Alarm clock"; + case SIGTERM: return "Terminated"; + case SIGSYS: return "Bad system call"; + case SIGCHLD: return "Child exited"; + case SIGCONT: return "Continued"; + case SIGSTOP: return "Stopped (signal)"; + case SIGTSTP: return "Stopped"; + case SIGTTIN: return "Stopped (tty input)"; + case SIGTTOU: return "Stopped (tty output)"; + case SIGURG: return "Urgent I/O condition"; + case SIGXCPU: return "CPU time limit exceeded"; + case SIGXFSZ: return "File size limit exceeded"; + case SIGVTALRM: return "Virtual timer expired"; + case SIGPWR: return "Power Fail/Restart"; + case SIGWINCH: return "Window changed"; + default: break; + } + + if ( SIGRTMIN <= signum && signum <= SIGRTMAX ) + return "Real-time signal"; + + return "Unknown signal value"; +} diff --git a/libc/string/strspn.c b/libc/string/strspn.c new file mode 100644 index 0000000..3469f55 --- /dev/null +++ b/libc/string/strspn.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strspn.c + * Search a string for a set of characters. + */ + +#include +#include + +size_t strspn(const char* str, const char* accept) +{ + size_t accept_length = 0; + while ( accept[accept_length] ) + accept_length++; + for ( size_t result = 0; true; result++ ) + { + char c = str[result]; + if ( !c ) + return result; + bool matches = false; + for ( size_t i = 0; i < accept_length; i++ ) + { + if ( str[result] != accept[i] ) + continue; + matches = true; + break; + } + if ( !matches ) + return result; + } +} diff --git a/libc/string/strstr.c b/libc/string/strstr.c new file mode 100644 index 0000000..ddfade1 --- /dev/null +++ b/libc/string/strstr.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strstr.c + * Locate a substring. + */ + +#include +#include + +// TODO: This simple and hacky implementation runs in O(N^2) even though this +// problem can be solved in O(N). +char* strstr(const char* haystack, const char* needle) +{ + if ( !needle[0] ) + return (char*) haystack; + for ( size_t i = 0; haystack[i]; i++ ) + { + bool diff = false; + for ( size_t j = 0; needle[j]; j++ ) + { + if ( haystack[i+j] != needle[j] ) { diff = true; break; } + } + if ( diff ) + continue; + return (char*) haystack + i; + } + return NULL; +} diff --git a/libc/string/strtok.c b/libc/string/strtok.c new file mode 100644 index 0000000..68b1870 --- /dev/null +++ b/libc/string/strtok.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strtok.c + * Extract tokens from strings. + */ + +#include + +char* strtok(char* str, const char* delim) +{ + static char* lasttokensaveptr = NULL; + return strtok_r(str, delim, &lasttokensaveptr); +} diff --git a/libc/string/strtok_r.c b/libc/string/strtok_r.c new file mode 100644 index 0000000..b4cdaac --- /dev/null +++ b/libc/string/strtok_r.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strtok_r.c + * Extract tokens from strings. + */ + +#include + +char* strtok_r(char* str, const char* delim, char** saveptr) +{ + if ( !str && !*saveptr ) + return NULL; + if ( !str ) + str = *saveptr; + str += strspn(str, delim); // Skip leading + if ( !*str ) + return *saveptr = NULL; + size_t amount = strcspn(str, delim); + if ( str[amount] ) + *saveptr = str + amount + 1; + else + *saveptr = NULL; + str[amount] = '\0'; + return str; +} diff --git a/libc/string/strverscmp.c b/libc/string/strverscmp.c new file mode 100644 index 0000000..ef7403f --- /dev/null +++ b/libc/string/strverscmp.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strverscmp.c + * Compares two version strings. + */ + +#include +#include + +static bool is_number(char c) +{ + return '0' <= c && c <= '9'; +} + +static int to_number(char c) +{ + return c - '0'; +} + +int strverscmp(const char* a, const char* b) +{ + for ( size_t i = 0; true; i++ ) + { + // Be a regular strcmp if the strings are equal. + if ( a[i] == '\0' && b[i] == '\0' ) + return 0; + if ( a[i] == b[i] ) + continue; + + // Be a regular strcmp if no digits are involed when they differ. + // Note: This implementation uses version number comparison if *either* + // of the first differing characters are digits, unlike glibc + // which is documented to require *both*. This behavior matches + // GNU sort -V and musl. It's also useful as "1.2.txt" compares + // before "1.2.3.txt". + bool version_string = is_number(a[i]) || is_number(b[i]); + if ( !version_string && a[i] < b[i] ) + return -1; + if ( !version_string && a[i] > b[i] ) + return 1; + + // Because the number of leading zeroes matter, we have to find the + // entire numeric block we are currently within. We know the strings are + // equal until i, so we can simply find the number of shared digits by + // looking in the first string. + size_t digits_start = i; + while ( digits_start && is_number(a[digits_start-1]) ) + digits_start--; + size_t shared_digits = i - digits_start; + + // Find the number of shared leading zeroes. + size_t shared_zeroes = 0; + while ( shared_zeroes < shared_digits && + to_number(a[digits_start + shared_zeroes]) == 0 ) + shared_zeroes++; + + // Try to expand the leading zeroes amount into a. + size_t a_zeroes = shared_zeroes; + while ( is_number(a[digits_start + a_zeroes]) == 0 ) + a_zeroes++; + + // Try to expand the leading zeroes amount into b. + size_t b_zeroes = shared_zeroes; + while ( is_number(b[digits_start + b_zeroes]) == 0 ) + b_zeroes++; + + // We treat strings with leading zeroes as if they have a decimal point + // in front of them, so strings with more zeroes sort lower. + if ( a_zeroes > b_zeroes ) + return -1; + if ( b_zeroes > a_zeroes ) + return 1; + + // Find the number of consecutive digits in a where the strings differ. + size_t a_digits = a_zeroes; + while ( is_number(a[digits_start + a_digits]) ) + a_digits++; + + // Find the number of consecutive digits in b where the strings differ. + size_t b_digits = b_zeroes; + while ( is_number(b[digits_start + b_digits]) ) + b_digits++; + + // We know the strings have the same amount of leading zeroes, so we + // so if a a block is longer than the other, then the value must be + // longer as well. + if ( a_digits < b_digits ) + return -1; + if ( b_digits < a_digits ) + return 1; + + // Finally run through the strings from where they differ and sort them + // numerically. We know this terminates because the strings differ. The + // strings have the same amount of digits, so comparing them is easy. + for ( size_t n = shared_zeroes; true; n++ ) + { + if ( a[digits_start + n] < b[digits_start + n] ) + return -1; + if ( b[digits_start + n] < a[digits_start + n] ) + return 1; + } + } +} diff --git a/libc/string/strxfrm.c b/libc/string/strxfrm.c new file mode 100644 index 0000000..68df155 --- /dev/null +++ b/libc/string/strxfrm.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011, 2012 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strxfrm.c + * Transform a string such that the result of strcmp is the same as strcoll. + */ + +#include + +size_t strxfrm(char* dest, const char* src, size_t n) +{ + size_t srclen = strlen(src); + strncpy(dest, src, n); + return srclen; +} diff --git a/libc/string/strxfrm_l.c b/libc/string/strxfrm_l.c new file mode 100644 index 0000000..67829f0 --- /dev/null +++ b/libc/string/strxfrm_l.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * string/strxfrm_l.c + * Transform a string such that the result of strcmp is the same as strcoll_l. + */ + +#include + +size_t strxfrm_l(char* dest, const char* src, size_t n, locale_t locale) +{ + (void) locale; + return strxfrm(dest, src, n); +} diff --git a/libc/string/timingsafe_memcmp.c b/libc/string/timingsafe_memcmp.c new file mode 100644 index 0000000..7f3262e --- /dev/null +++ b/libc/string/timingsafe_memcmp.c @@ -0,0 +1,53 @@ +/* $OpenBSD: timingsafe_memcmp.c,v 1.1 2014/06/13 02:12:17 matthew Exp $ */ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +// TODO: I don't fully trust that this code is _always_ timing safe in the +// presence of very smart compilers that can prove that this computes the +// same value as memcmp and could be short-circuited. We should invent and +// rely on compiler extensions that inform the compiler that sensitive +// information is involved, which forbids the compiler code generation +// from branching on the information (and such). +// TODO: We should add testcases that verify this is actually timing safe. + +int timingsafe_memcmp(const void* a_ptr, const void* b_ptr, size_t size) +{ + const unsigned char* a = (const unsigned char*) a_ptr; + const unsigned char* b = (const unsigned char*) b_ptr; + int result = 0; + int done = 0; + for ( size_t i = 0; i < size; i++ ) + { + /* lt is -1 if a[i] < b[i]; else 0. */ + int lt = (a[i] - b[i]) >> CHAR_BIT; + + /* gt is -1 if a[i] > b[i]; else 0. */ + int gt = (b[i] - a[i]) >> CHAR_BIT; + + /* cmp is 1 if a[i] > b[i]; -1 if a[i] < b[i]; else 0. */ + int cmp = lt - gt; + + /* set result = cmp if !done. */ + result |= cmp & ~done; + + /* set done if a[i] != b[i]. */ + done |= lt | gt; + } + return result; +}