diff options
Diffstat (limited to 'src/pdclib/functions/string')
22 files changed, 1068 insertions, 0 deletions
diff --git a/src/pdclib/functions/string/memchr.c b/src/pdclib/functions/string/memchr.c new file mode 100644 index 0000000..29598a7 --- /dev/null +++ b/src/pdclib/functions/string/memchr.c @@ -0,0 +1,41 @@ +/* memchr( const void *, int, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +void * memchr( const void * s, int c, size_t n ) +{ + const unsigned char * p = (const unsigned char *) s; + while ( n-- ) + { + if ( *p == (unsigned char) c ) + { + return (void *) p; + } + ++p; + } + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( memchr( abcde, 'c', 5 ) == &abcde[2] ); + TESTCASE( memchr( abcde, 'a', 1 ) == &abcde[0] ); + TESTCASE( memchr( abcde, 'a', 0 ) == NULL ); + TESTCASE( memchr( abcde, '\0', 5 ) == NULL ); + TESTCASE( memchr( abcde, '\0', 6 ) == &abcde[5] ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/memcmp.c b/src/pdclib/functions/string/memcmp.c new file mode 100644 index 0000000..709b941 --- /dev/null +++ b/src/pdclib/functions/string/memcmp.c @@ -0,0 +1,43 @@ +/* memcmp( const void *, const void *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +int memcmp( const void * s1, const void * s2, size_t n ) +{ + const unsigned char * p1 = (const unsigned char *) s1; + const unsigned char * p2 = (const unsigned char *) s2; + while ( n-- ) + { + if ( *p1 != *p2 ) + { + return *p1 - *p2; + } + ++p1; + ++p2; + } + return 0; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + const char xxxxx[] = "xxxxx"; + TESTCASE( memcmp( abcde, abcdx, 5 ) < 0 ); + TESTCASE( memcmp( abcde, abcdx, 4 ) == 0 ); + TESTCASE( memcmp( abcde, xxxxx, 0 ) == 0 ); + TESTCASE( memcmp( xxxxx, abcde, 1 ) > 0 ); + return 0; +} + +#endif diff --git a/src/pdclib/functions/string/memcpy.c b/src/pdclib/functions/string/memcpy.c new file mode 100644 index 0000000..21ef10e --- /dev/null +++ b/src/pdclib/functions/string/memcpy.c @@ -0,0 +1,40 @@ +/* memcpy( void *, const void *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n ) +{ + char * dest = (char *) s1; + const char * src = (const char *) s2; + while ( n-- ) + { + *dest++ = *src++; + } + return s1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxxxx"; + TESTCASE( memcpy( s, abcde, 6 ) == s ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( memcpy( s + 5, abcde, 5 ) == s + 5 ); + TESTCASE( s[9] == 'e' ); + TESTCASE( s[10] == 'x' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/memmove.c b/src/pdclib/functions/string/memmove.c new file mode 100644 index 0000000..af89813 --- /dev/null +++ b/src/pdclib/functions/string/memmove.c @@ -0,0 +1,52 @@ +/* memmove( void *, const void *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +void * memmove( void * s1, const void * s2, size_t n ) +{ + char * dest = (char *) s1; + const char * src = (const char *) s2; + if ( dest <= src ) + { + while ( n-- ) + { + *dest++ = *src++; + } + } + else + { + src += n; + dest += n; + while ( n-- ) + { + *--dest = *--src; + } + } + return s1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxabcde"; + TESTCASE( memmove( s, s + 4, 5 ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == 'b' ); + TESTCASE( memmove( s + 4, s, 5 ) == s + 4 ); + TESTCASE( s[4] == 'a' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/memset.c b/src/pdclib/functions/string/memset.c new file mode 100644 index 0000000..522ad77 --- /dev/null +++ b/src/pdclib/functions/string/memset.c @@ -0,0 +1,40 @@ +/* memset( void *, int, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +void * memset( void * s, int c, size_t n ) +{ + unsigned char * p = (unsigned char *) s; + while ( n-- ) + { + *p++ = (unsigned char) c; + } + return s; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxx"; + TESTCASE( memset( s, 'o', 10 ) == s ); + TESTCASE( s[9] == 'o' ); + TESTCASE( memset( s, '_', 0 ) == s ); + TESTCASE( s[0] == 'o' ); + TESTCASE( memset( s, '_', 1 ) == s ); + TESTCASE( s[0] == '_' ); + TESTCASE( s[1] == 'o' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strcat.c b/src/pdclib/functions/string/strcat.c new file mode 100644 index 0000000..18fd409 --- /dev/null +++ b/src/pdclib/functions/string/strcat.c @@ -0,0 +1,46 @@ +/* strcat( char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + char * rc = s1; + if ( *s1 ) + { + while ( *++s1 ); + } + while ( (*s1++ = *s2++) ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xx\0xxxxxx"; + TESTCASE( strcat( s, abcde ) == s ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strcat( s, abcdx ) == s ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strcat( s, "\0" ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strchr.c b/src/pdclib/functions/string/strchr.c new file mode 100644 index 0000000..621100e --- /dev/null +++ b/src/pdclib/functions/string/strchr.c @@ -0,0 +1,40 @@ +/* strchr( const char *, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strchr( const char * s, int c ) +{ + do + { + if ( *s == (char) c ) + { + return (char *) s; + } + } while ( *s++ ); + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char abccd[] = "abccd"; + TESTCASE( strchr( abccd, 'x' ) == NULL ); + TESTCASE( strchr( abccd, 'a' ) == &abccd[0] ); + TESTCASE( strchr( abccd, 'd' ) == &abccd[4] ); + TESTCASE( strchr( abccd, '\0' ) == &abccd[5] ); + TESTCASE( strchr( abccd, 'c' ) == &abccd[2] ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strcmp.c b/src/pdclib/functions/string/strcmp.c new file mode 100644 index 0000000..639fc10 --- /dev/null +++ b/src/pdclib/functions/string/strcmp.c @@ -0,0 +1,41 @@ +/* strcmp( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +int strcmp( const char * s1, const char * s2 ) +{ + while ( ( *s1 ) && ( *s1 == *s2 ) ) + { + ++s1; + ++s2; + } + return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde"; + char cmpabcd_[] = "abcd\xfc"; + char empty[] = ""; + TESTCASE( strcmp( abcde, cmpabcde ) == 0 ); + TESTCASE( strcmp( abcde, abcdx ) < 0 ); + TESTCASE( strcmp( abcdx, abcde ) > 0 ); + TESTCASE( strcmp( empty, abcde ) < 0 ); + TESTCASE( strcmp( abcde, empty ) > 0 ); + TESTCASE( strcmp( abcde, cmpabcd_ ) < 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strcoll.c b/src/pdclib/functions/string/strcoll.c new file mode 100644 index 0000000..41d466a --- /dev/null +++ b/src/pdclib/functions/string/strcoll.c @@ -0,0 +1,46 @@ +/* strcoll( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +#include <locale.h> + +int strcoll( const char * s1, const char * s2 ) +{ + return strcmp( s1, s2 ); + + /* FIXME: This code became invalid when we started doing *real* locales... */ + /* + while ( ( *s1 ) && ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation ) ) + { + ++s1; + ++s2; + } + return ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation ); + */ +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde"; + char empty[] = ""; + TESTCASE( strcmp( abcde, cmpabcde ) == 0 ); + TESTCASE( strcmp( abcde, abcdx ) < 0 ); + TESTCASE( strcmp( abcdx, abcde ) > 0 ); + TESTCASE( strcmp( empty, abcde ) < 0 ); + TESTCASE( strcmp( abcde, empty ) > 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strcpy.c b/src/pdclib/functions/string/strcpy.c new file mode 100644 index 0000000..e0357c8 --- /dev/null +++ b/src/pdclib/functions/string/strcpy.c @@ -0,0 +1,37 @@ +/* strcpy( char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + char * rc = s1; + while ( ( *s1++ = *s2++ ) ); + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxx"; + TESTCASE( strcpy( s, "" ) == s ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strcpy( s, abcde ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strcspn.c b/src/pdclib/functions/string/strcspn.c new file mode 100644 index 0000000..84f8af1 --- /dev/null +++ b/src/pdclib/functions/string/strcspn.c @@ -0,0 +1,50 @@ +/* strcspn( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +size_t strcspn( const char * s1, const char * s2 ) +{ + size_t len = 0; + const char * p; + while ( s1[len] ) + { + p = s2; + while ( *p ) + { + if ( s1[len] == *p++ ) + { + return len; + } + } + ++len; + } + return len; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strcspn( abcde, "x" ) == 5 ); + TESTCASE( strcspn( abcde, "xyz" ) == 5 ); + TESTCASE( strcspn( abcde, "zyx" ) == 5 ); + TESTCASE( strcspn( abcdx, "x" ) == 4 ); + TESTCASE( strcspn( abcdx, "xyz" ) == 4 ); + TESTCASE( strcspn( abcdx, "zyx" ) == 4 ); + TESTCASE( strcspn( abcde, "a" ) == 0 ); + TESTCASE( strcspn( abcde, "abc" ) == 0 ); + TESTCASE( strcspn( abcde, "cba" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strerror.c b/src/pdclib/functions/string/strerror.c new file mode 100644 index 0000000..4506376 --- /dev/null +++ b/src/pdclib/functions/string/strerror.c @@ -0,0 +1,41 @@ +/* strerror( int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +#include <locale.h> + +/* TODO: Doing this via a static array is not the way to do it. */ +char * strerror( int errnum ) +{ + if ( errnum >= _PDCLIB_ERRNO_MAX ) + { + return (char *)"Unknown error"; + } + else + { + return _PDCLIB_lc_messages.errno_texts[errnum]; + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +#include <stdio.h> +#include <errno.h> + +int main( void ) +{ + TESTCASE( strerror( ERANGE ) != strerror( EDOM ) ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strlen.c b/src/pdclib/functions/string/strlen.c new file mode 100644 index 0000000..c1a620e --- /dev/null +++ b/src/pdclib/functions/string/strlen.c @@ -0,0 +1,34 @@ +/* strlen( const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +size_t strlen( const char * s ) +{ + size_t rc = 0; + while ( s[rc] ) + { + ++rc; + } + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strlen( abcde ) == 5 ); + TESTCASE( strlen( "" ) == 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strncat.c b/src/pdclib/functions/string/strncat.c new file mode 100644 index 0000000..ba20edc --- /dev/null +++ b/src/pdclib/functions/string/strncat.c @@ -0,0 +1,60 @@ +/* strncat( char *, const char *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n ) +{ + char * rc = s1; + while ( *s1 ) + { + ++s1; + } + while ( n && ( *s1++ = *s2++ ) ) + { + --n; + } + if ( n == 0 ) + { + *s1 = '\0'; + } + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xx\0xxxxxx"; + TESTCASE( strncat( s, abcde, 10 ) == s ); + TESTCASE( s[2] == 'a' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( s[7] == '\0' ); + TESTCASE( s[8] == 'x' ); + s[0] = '\0'; + TESTCASE( strncat( s, abcdx, 10 ) == s ); + TESTCASE( s[4] == 'x' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strncat( s, "\0", 10 ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat( s, abcde, 0 ) == s ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'e' ); + TESTCASE( strncat( s, abcde, 3 ) == s ); + TESTCASE( s[5] == 'a' ); + TESTCASE( s[7] == 'c' ); + TESTCASE( s[8] == '\0' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strncmp.c b/src/pdclib/functions/string/strncmp.c new file mode 100644 index 0000000..4bb3592 --- /dev/null +++ b/src/pdclib/functions/string/strncmp.c @@ -0,0 +1,54 @@ +/* strncmp( const char *, const char *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +int strncmp( const char * s1, const char * s2, size_t n ) +{ + while ( n && *s1 && ( *s1 == *s2 ) ) + { + ++s1; + ++s2; + --n; + } + if ( n == 0 ) + { + return 0; + } + else + { + return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); + } +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char cmpabcde[] = "abcde\0f"; + char cmpabcd_[] = "abcde\xfc"; + char empty[] = ""; + char x[] = "x"; + TESTCASE( strncmp( abcde, cmpabcde, 5 ) == 0 ); + TESTCASE( strncmp( abcde, cmpabcde, 10 ) == 0 ); + TESTCASE( strncmp( abcde, abcdx, 5 ) < 0 ); + TESTCASE( strncmp( abcdx, abcde, 5 ) > 0 ); + TESTCASE( strncmp( empty, abcde, 5 ) < 0 ); + TESTCASE( strncmp( abcde, empty, 5 ) > 0 ); + TESTCASE( strncmp( abcde, abcdx, 4 ) == 0 ); + TESTCASE( strncmp( abcde, x, 0 ) == 0 ); + TESTCASE( strncmp( abcde, x, 1 ) < 0 ); + TESTCASE( strncmp( abcde, cmpabcd_, 10 ) < 0 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strncpy.c b/src/pdclib/functions/string/strncpy.c new file mode 100644 index 0000000..0627c41 --- /dev/null +++ b/src/pdclib/functions/string/strncpy.c @@ -0,0 +1,56 @@ +/* strncpy( char *, const char *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n ) +{ + char * rc = s1; + while ( n && ( *s1++ = *s2++ ) ) + { + /* Cannot do "n--" in the conditional as size_t is unsigned and we have + to check it again for >0 in the next loop below, so we must not risk + underflow. + */ + --n; + } + /* Checking against 1 as we missed the last --n in the loop above. */ + while ( n-- > 1 ) + { + *s1++ = '\0'; + } + return rc; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxx"; + TESTCASE( strncpy( s, "", 1 ) == s ); + TESTCASE( s[0] == '\0' ); + TESTCASE( s[1] == 'x' ); + TESTCASE( strncpy( s, abcde, 6 ) == s ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[4] == 'e' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( s[6] == 'x' ); + TESTCASE( strncpy( s, abcde, 7 ) == s ); + TESTCASE( s[6] == '\0' ); + TESTCASE( strncpy( s, "xxxx", 3 ) == s ); + TESTCASE( s[0] == 'x' ); + TESTCASE( s[2] == 'x' ); + TESTCASE( s[3] == 'd' ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strpbrk.c b/src/pdclib/functions/string/strpbrk.c new file mode 100644 index 0000000..e95f0c1 --- /dev/null +++ b/src/pdclib/functions/string/strpbrk.c @@ -0,0 +1,49 @@ +/* strpbrk( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strpbrk( const char * s1, const char * s2 ) +{ + const char * p1 = s1; + const char * p2; + while ( *p1 ) + { + p2 = s2; + while ( *p2 ) + { + if ( *p1 == *p2++ ) + { + return (char *) p1; + } + } + ++p1; + } + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strpbrk( abcde, "x" ) == NULL ); + TESTCASE( strpbrk( abcde, "xyz" ) == NULL ); + TESTCASE( strpbrk( abcdx, "x" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcdx, "xyz" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcdx, "zyx" ) == &abcdx[4] ); + TESTCASE( strpbrk( abcde, "a" ) == &abcde[0] ); + TESTCASE( strpbrk( abcde, "abc" ) == &abcde[0] ); + TESTCASE( strpbrk( abcde, "cba" ) == &abcde[0] ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strrchr.c b/src/pdclib/functions/string/strrchr.c new file mode 100644 index 0000000..c2369fa --- /dev/null +++ b/src/pdclib/functions/string/strrchr.c @@ -0,0 +1,41 @@ +/* strrchr( const char *, int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strrchr( const char * s, int c ) +{ + size_t i = 0; + while ( s[i++] ); + do + { + if ( s[--i] == (char) c ) + { + return (char *) s + i; + } + } while ( i ); + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char abccd[] = "abccd"; + TESTCASE( strrchr( abcde, '\0' ) == &abcde[5] ); + TESTCASE( strrchr( abcde, 'e' ) == &abcde[4] ); + TESTCASE( strrchr( abcde, 'a' ) == &abcde[0] ); + TESTCASE( strrchr( abccd, 'c' ) == &abccd[3] ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strspn.c b/src/pdclib/functions/string/strspn.c new file mode 100644 index 0000000..7b55b08 --- /dev/null +++ b/src/pdclib/functions/string/strspn.c @@ -0,0 +1,49 @@ +/* strspn( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +size_t strspn( const char * s1, const char * s2 ) +{ + size_t len = 0; + const char * p; + while ( s1[ len ] ) + { + p = s2; + while ( *p ) + { + if ( s1[len] == *p ) + { + break; + } + ++p; + } + if ( ! *p ) + { + return len; + } + ++len; + } + return len; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + TESTCASE( strspn( abcde, "abc" ) == 3 ); + TESTCASE( strspn( abcde, "b" ) == 0 ); + TESTCASE( strspn( abcde, abcde ) == 5 ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strstr.c b/src/pdclib/functions/string/strstr.c new file mode 100644 index 0000000..aee282f --- /dev/null +++ b/src/pdclib/functions/string/strstr.c @@ -0,0 +1,51 @@ +/* strstr( const char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strstr( const char * s1, const char * s2 ) +{ + const char * p1 = s1; + const char * p2; + while ( *s1 ) + { + p2 = s2; + while ( *p2 && ( *p1 == *p2 ) ) + { + ++p1; + ++p2; + } + if ( ! *p2 ) + { + return (char *) s1; + } + ++s1; + p1 = s1; + } + return NULL; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "abcabcabcdabcde"; + TESTCASE( strstr( s, "x" ) == NULL ); + TESTCASE( strstr( s, "xyz" ) == NULL ); + TESTCASE( strstr( s, "a" ) == &s[0] ); + TESTCASE( strstr( s, "abc" ) == &s[0] ); + TESTCASE( strstr( s, "abcd" ) == &s[6] ); + TESTCASE( strstr( s, "abcde" ) == &s[10] ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strtok.c b/src/pdclib/functions/string/strtok.c new file mode 100644 index 0000000..69c2d68 --- /dev/null +++ b/src/pdclib/functions/string/strtok.c @@ -0,0 +1,107 @@ +/* strtok( char *, const char * ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 ) +{ + static char * tmp = NULL; + const char * p = s2; + + if ( s1 != NULL ) + { + /* new string */ + tmp = s1; + } + else + { + /* old string continued */ + if ( tmp == NULL ) + { + /* No old string, no new string, nothing to do */ + return NULL; + } + s1 = tmp; + } + + /* skipping leading s2 characters */ + while ( *p && *s1 ) + { + if ( *s1 == *p ) + { + /* found seperator; skip and start over */ + ++s1; + p = s2; + continue; + } + ++p; + } + + if ( ! *s1 ) + { + /* no more to parse */ + return ( tmp = NULL ); + } + + /* skipping non-s2 characters */ + tmp = s1; + while ( *tmp ) + { + p = s2; + while ( *p ) + { + if ( *tmp == *p++ ) + { + /* found seperator; overwrite with '\0', position tmp, return */ + *tmp++ = '\0'; + return s1; + } + } + ++tmp; + } + + /* parsed to end of string */ + tmp = NULL; + return s1; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "_a_bc__d_"; + TESTCASE( strtok( s, "_" ) == &s[1] ); + TESTCASE( s[1] == 'a' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[3] ); + TESTCASE( s[3] == 'b' ); + TESTCASE( s[4] == 'c' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[7] ); + TESTCASE( s[6] == '_' ); + TESTCASE( s[7] == 'd' ); + TESTCASE( s[8] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == NULL ); + strcpy( s, "ab_cd" ); + TESTCASE( strtok( s, "_" ) == &s[0] ); + TESTCASE( s[0] == 'a' ); + TESTCASE( s[1] == 'b' ); + TESTCASE( s[2] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == &s[3] ); + TESTCASE( s[3] == 'c' ); + TESTCASE( s[4] == 'd' ); + TESTCASE( s[5] == '\0' ); + TESTCASE( strtok( NULL, "_" ) == NULL ); + return TEST_RESULTS; +} + +#endif diff --git a/src/pdclib/functions/string/strxfrm.c b/src/pdclib/functions/string/strxfrm.c new file mode 100644 index 0000000..e08dba2 --- /dev/null +++ b/src/pdclib/functions/string/strxfrm.c @@ -0,0 +1,50 @@ +/* strxfrm( char *, const char *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include <string.h> + +#ifndef REGTEST + +#include <locale.h> + +size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n ) +{ + size_t len = strlen( s2 ); + if ( len < n ) + { + /* Cannot use strncpy() here as the filling of s1 with '\0' is not part + of the spec. + */ + /* FIXME: The code below became invalid when we started doing *real* locales... */ + /*while ( n-- && ( *s1++ = _PDCLIB_lc_collate[(unsigned char)*s2++].collation ) );*/ + while ( n-- && ( *s1++ = (unsigned char)*s2++ ) ); + } + return len; +} + +#endif + +#ifdef TEST + +#include "_PDCLIB_test.h" + +int main( void ) +{ + char s[] = "xxxxxxxxxxx"; + TESTCASE( strxfrm( NULL, "123456789012", 0 ) == 12 ); + TESTCASE( strxfrm( s, "123456789012", 12 ) == 12 ); + /* + The following test case is true in *this* implementation, but doesn't have to. + TESTCASE( s[0] == 'x' ); + */ + TESTCASE( strxfrm( s, "1234567890", 11 ) == 10 ); + TESTCASE( s[0] == '1' ); + TESTCASE( s[9] == '0' ); + TESTCASE( s[10] == '\0' ); + return TEST_RESULTS; +} + +#endif |