diff options
Diffstat (limited to '')
46 files changed, 1497 insertions, 841 deletions
diff --git a/include/string.h b/include/string.h index fc04dcb..b3b3e10 100644 --- a/include/string.h +++ b/include/string.h @@ -148,7 +148,7 @@ size_t strlen(const char*) defined(__BSD_SOURCE) /** * Variant of `strlen` that only inspects the - * beginning of s string. + * beginning of a string. * * @param str The string. * @param maxlen The number of bytes to inspect, at most. diff --git a/src/string/memcasecmp.c b/src/string/memcasecmp.c new file mode 100644 index 0000000..d8ea014 --- /dev/null +++ b/src/string/memcasecmp.c @@ -0,0 +1,50 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <ctype.h> + + + +/** + * Compare two memory segments alphabetically in a case insensitive manner. + * + * This is a slibc extension added because it was useful + * in implementing slibc itself. + * + * @param a A negative value is returned if this is the lesser. + * @param b A positive value is returned if this is the lesser. + * @param size The size of the segments. + * @return Zero is returned if `a` and `b` are equal, otherwise, + * see the specifications for `a` and `b`. + */ +int memcasecmp(const void* a, const void* b, size_t size) +{ + const signed char* s1 = a; + const signed char* s2 = b; + int c1, c2; + for (; size--; s1++, s2++) + if (*s1 != *s2) + { + c1 = isalpha(*s1) ? tolower(*s1) : (int)*s1; + c2 = isalpha(*s2) ? tolower(*s2) : (int)*s2; + if ((c1 -= c2)) + return c1; + } + return 0; +} + diff --git a/src/string/memccpy.c b/src/string/memccpy.c index 0c73f8b..18e423d 100644 --- a/src/string/memccpy.c +++ b/src/string/memccpy.c @@ -43,30 +43,3 @@ void* (memccpy)(void* restrict whither, const void* restrict whence, int c, size return r; } - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * but stop if a specific byte is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param c The byte to stop at if encountered. - * @param size The maximum number of bytes to copy. - * @return `NULL` if `c` was not encountered, otherwise - * the possition of `c` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written character. - */ -void* (memcmove)(void* whither, const void* whence, int c, size_t size) -{ - char* stop = (memchr)(whence, c, size); - void* r = NULL; - if (stop != NULL) - size = (size_t)(stop - (const char*)whence), r = whither + size; - memmove(whither, whence, size); - return r; -} - diff --git a/src/string/memcmove.c b/src/string/memcmove.c new file mode 100644 index 0000000..50ed1f9 --- /dev/null +++ b/src/string/memcmove.c @@ -0,0 +1,47 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * but stop if a specific byte is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param c The byte to stop at if encountered. + * @param size The maximum number of bytes to copy. + * @return `NULL` if `c` was not encountered, otherwise + * the possition of `c` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written character. + */ +void* (memcmove)(void* whither, const void* whence, int c, size_t size) +{ + char* stop = (memchr)(whence, c, size); + void* r = NULL; + if (stop != NULL) + size = (size_t)(stop - (const char*)whence), r = whither + size; + memmove(whither, whence, size); + return r; +} + diff --git a/src/string/memcmp.c b/src/string/memcmp.c new file mode 100644 index 0000000..112cdd1 --- /dev/null +++ b/src/string/memcmp.c @@ -0,0 +1,42 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Compare two memory segments alphabetically in a case sensitive manner. + * + * @param a A negative value is returned if this is the lesser. + * @param b A positive value is returned if this is the lesser. + * @param size The size of the segments. + * @return Zero is returned if `a` and `b` are equal, otherwise, + * see the specifications for `a` and `b`. + */ +int memcmp(const void* a, const void* b, size_t size) +{ + const signed char* s1 = a; + const signed char* s2 = b; + while (size--) + if (*s1 == *s2) + s1++, s2++; + else + return (int)(*s1 - *s2); + return 0; +} + diff --git a/src/string/memcpy.c b/src/string/memcpy.c index 54482fb..fcda29d 100644 --- a/src/string/memcpy.c +++ b/src/string/memcpy.c @@ -18,9 +18,6 @@ #include <string.h> -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" - - /** * Copy a memory segment to another, non-overlapping, segment. @@ -33,25 +30,9 @@ void* memcpy(void* restrict whither, const void* restrict whence, size_t size) { char* d = whither; - char* s = whence; + const char* s = whence; while (size--) *d++ = *s++; return whither; } - -/** - * Copy a memory segment to another, non-overlapping, segment. - * - * This is a GNU extension. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param size The number of bytes to copy. - * @return `whither + size` is returned. - */ -void* mempcpy(void* restrict whither, const void* restrict whence, size_t size) -{ - return (char*)memcpy(whither, whence, size) + size; -} - diff --git a/src/string/memdup.c b/src/string/memdup.c new file mode 100644 index 0000000..3b301dc --- /dev/null +++ b/src/string/memdup.c @@ -0,0 +1,40 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <stdlib.h> + + + +/** + * Duplicate a memory segment. + * + * This is a slibc extension. + * + * @param segment The memory segment to duplicate. + * @param size The size of the memory segment. + * @return The new segment. `NULL` is returned on error + * and `errno` is set to indicate the error. + * + * @throws ENOMEM The process could not allocate sufficient amount of memory. + */ +void* memdup(const void* segment, size_t size) +{ + void* r = malloc(size); + return r == NULL ? NULL : memcpy(r, segment, size); +} + diff --git a/src/string/memmove.c b/src/string/memmove.c index 0acc47b..41871c6 100644 --- a/src/string/memmove.c +++ b/src/string/memmove.c @@ -40,20 +40,3 @@ void* memmove(void* whither, const void* whence, size_t size) return whither; } - -/** - * Copy a memory segment to another, possibly overlapping, segment. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param size The number of bytes to copy. - * @return `whither + size` is returned. - */ -void* mempmove(void* whither, const void* whence, size_t size) -{ - return (char*)memmove(whither, whence, size) + size; -} - diff --git a/src/string/mempcpy.c b/src/string/mempcpy.c new file mode 100644 index 0000000..2072dc3 --- /dev/null +++ b/src/string/mempcpy.c @@ -0,0 +1,36 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment. + * + * This is a GNU extension. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param size The number of bytes to copy. + * @return `whither + size` is returned. + */ +void* mempcpy(void* restrict whither, const void* restrict whence, size_t size) +{ + return (char*)memcpy(whither, whence, size) + size; +} + diff --git a/src/string/mempmove.c b/src/string/mempmove.c new file mode 100644 index 0000000..f837032 --- /dev/null +++ b/src/string/mempmove.c @@ -0,0 +1,37 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param size The number of bytes to copy. + * @return `whither + size` is returned. + */ +void* mempmove(void* whither, const void* whence, size_t size) +{ + return (char*)memmove(whither, whence, size) + size; +} + diff --git a/src/string/stpcpy.c b/src/string/stpcpy.c new file mode 100644 index 0000000..a0d5f79 --- /dev/null +++ b/src/string/stpcpy.c @@ -0,0 +1,34 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte is encountered. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @return `whither + strlen(whence)` is returned. + */ +char* stpcpy(char* restrict whither, const char* restrict whence) +{ + return mempcpy(whither, whence, strlen(whence) + 1) - 1; +} + diff --git a/src/string/stpmove.c b/src/string/stpmove.c new file mode 100644 index 0000000..8818c30 --- /dev/null +++ b/src/string/stpmove.c @@ -0,0 +1,37 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @return `whither + strlen(whence)` is returned. + */ +char* stpmove(char* whither, const char* whence) +{ + return mempmove(whither, whence, strlen(whence) + 1) - 1; +} + + diff --git a/src/string/stpncpy.c b/src/string/stpncpy.c new file mode 100644 index 0000000..876eaf0 --- /dev/null +++ b/src/string/stpncpy.c @@ -0,0 +1,46 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte is encountered. + * + * This is a GNU extension. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `whither` plus the number of written bytes, + * excluding NUL bytes, is returned. + */ +char* stpncpy(char* restrict whither, const char* restrict whence, size_t maxlen) +{ + size_t n = strnlen(whence, maxlen); + memcpy(whither, whence, n); + memset(whither, 0, maxlen - n); + return whither + n; +} + diff --git a/src/string/stpnmove.c b/src/string/stpnmove.c new file mode 100644 index 0000000..a0a0de9 --- /dev/null +++ b/src/string/stpnmove.c @@ -0,0 +1,47 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte is encountered. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `whither` plus the number of written bytes, + * excluding NUL bytes, is returned. + */ +char* stpnmove(char* whither, const char* whence, size_t maxlen) +{ + size_t n = strnlen(whence, maxlen); + memmove(whither, whence, n); + memset(whither, 0, maxlen - n); + return whither + n; +} + diff --git a/src/string/strcasecmp.c b/src/string/strcasecmp.c new file mode 100644 index 0000000..eb02084 --- /dev/null +++ b/src/string/strcasecmp.c @@ -0,0 +1,37 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <stdint.h> + + + +/** + * Compare two strings alphabetically in a case insensitive manner. + * Be aware, only ASCII characters are case insensitive, non-ASCII + * characters are case sensitive. + * + * @param a A negative value is returned if this is the lesser. + * @param b A positive value is returned if this is the lesser. + * @return Zero is returned if `a` and `b` are equal, otherwise, + * see the specifications for `a` and `b`. + */ +int strcasecmp(const char* a, const char* b) +{ + return strncasecmp(a, b, SIZE_MAX); +} + diff --git a/src/string/strcat.c b/src/string/strcat.c index 2205f39..de5c63e 100644 --- a/src/string/strcat.c +++ b/src/string/strcat.c @@ -35,26 +35,3 @@ char* strcat(char* restrict whither, const char* restrict whence) return whither; } - -/** - * Concatenate a string to the end of another string. - * The resulting strings must not overlap with the appended string. - * - * The use of this function is often a really bad idea. - * - * @param whither The string to extend. - * @param whence The string to append. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `whither` is returned. - */ -char* strncat(char* restrict whither, const char* restrict whence, size_t maxlen) -{ - strncpy(whither + strlen(whither), whence, maxlen); - return whither; -} - diff --git a/src/string/strccpy.c b/src/string/strccpy.c new file mode 100644 index 0000000..2d1bcd8 --- /dev/null +++ b/src/string/strccpy.c @@ -0,0 +1,45 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte or a specified byte is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param c The stop byte. + * @return `NULL` if `c` was not encountered, otherwise + * the position of `c` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strccpy(char* restrict whither, const char* restrict whence, int c) +{ + char* r = memccpy(whither, whence, c, strlen(whence) + 1); + if (r) + *r = 0; + return r; +} + diff --git a/src/string/strcmove.c b/src/string/strcmove.c new file mode 100644 index 0000000..8310b27 --- /dev/null +++ b/src/string/strcmove.c @@ -0,0 +1,45 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte or a specified byte is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param c The stop byte. + * @return `NULL` if `c` was not encountered, otherwise + * the position of `c` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strcmove(char* whither, const char* whence, int c) +{ + char* r = memcmove(whither, whence, c, strlen(whence) + 1); + if (r) + *r = 0; + return r; +} + diff --git a/src/string/strcmp.c b/src/string/strcmp.c index bffb2ad..3099d71 100644 --- a/src/string/strcmp.c +++ b/src/string/strcmp.c @@ -16,64 +16,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <strings.h> -#include <stdint.h> -#include <ctype.h> /** - * Compare two memory segments alphabetically in a case sensitive manner. - * - * @param a A negative value is returned if this is the lesser. - * @param b A positive value is returned if this is the lesser. - * @param size The size of the segments. - * @return Zero is returned if `a` and `b` are equal, otherwise, - * see the specifications for `a` and `b`. - */ -int memcmp(const void* a, const void* b, size_t size) -{ - const signed char* s1 = a; - const signed char* s2 = b; - while (size--) - if (*s1 == *s2) - s1++, s2++; - else - return (int)(*s1 - *s2); - return 0; -} - - -/** - * Compare two memory segments alphabetically in a case insensitive manner. - * - * This is a slibc extension added because it was useful - * in implementing slibc itself. - * - * @param a A negative value is returned if this is the lesser. - * @param b A positive value is returned if this is the lesser. - * @param size The size of the segments. - * @return Zero is returned if `a` and `b` are equal, otherwise, - * see the specifications for `a` and `b`. - */ -int memcasecmp(const void* a, const void* b, size_t size) -{ - const signed char* s1 = a; - const signed char* s2 = b; - int c1, c2; - for (; size--; s1++, s2++) - if (*s1 != *s2) - { - c1 = isalpha(*s1) ? tolower(*s1) : (int)*s1; - c2 = isalpha(*s2) ? tolower(*s2) : (int)*s2; - if ((c1 -= c2)) - return c1; - } - return 0; -} - - -/** * Compare two strings alphabetically in a case sensitive manner. * * @param a A negative value is returned if this is the lesser. @@ -88,66 +34,3 @@ int strcmp(const char* a, const char* b) return memcmp(a, b, (n < m ? n : m) + 1); } - -/** - * Compare two strings alphabetically in a case insensitive manner. - * Be aware, only ASCII characters are case insensitive, non-ASCII - * characters are case sensitive. - * - * @param a A negative value is returned if this is the lesser. - * @param b A positive value is returned if this is the lesser. - * @return Zero is returned if `a` and `b` are equal, otherwise, - * see the specifications for `a` and `b`. - */ -int strcasecmp(const char* a, const char* b) -{ - return strncasecmp(a, b, SIZE_MAX); -} - - -/** - * Compare two strings alphabetically in a case sensitive manner. - * - * @param a A negative value is returned if this is the lesser. - * @param b A positive value is returned if this is the lesser. - * @param length The maximum number of characters to compare. - * @return Zero is returned if `a` and `b` are equal, otherwise, - * see the specifications for `a` and `b`. - */ -int strncmp(const char* a, const char* b, size_t length) -{ - size_t n = strnlen(a, length); - size_t m = strnlen(b, length); - int r = memcmp(a, b, (n < m ? n : m)); - return r ? r : n == m ? 0 : n < m ? -1 : +1; -} - - -/** - * Compare two strings alphabetically in a case insensitive manner. - * Be aware, only ASCII characters are case insensitive, non-ASCII - * characters are case sensitive. - * - * @param a A negative value is returned if this is the lesser. - * @param b A positive value is returned if this is the lesser. - * @param length The maximum number of characters to compare. - * @return Zero is returned if `a` and `b` are equal, otherwise, - * see the specifications for `a` and `b`. - */ -int strncasecmp(const char* a, const char* b, size_t length) -{ - int c1, c2; - for (; length--; a++, b++) - if (*a != *b) - { - c1 = isalpha(*a) ? tolower(*a) : (int)*a; - c2 = isalpha(*b) ? tolower(*b) : (int)*b; - if ((c1 -= c2)) - return c1; - } - else if (!*a && !*b) return 0; - else if (!*a) return -1; - else if (!*b) return +1; - return 0; -} - diff --git a/src/string/strcncpy.c b/src/string/strcncpy.c new file mode 100644 index 0000000..5036c7d --- /dev/null +++ b/src/string/strcncpy.c @@ -0,0 +1,54 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte or a specified byte is encountered. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param c The stop byte. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `NULL` if `c` was not encountered, otherwise + * the position of `c` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strcncpy(char* restrict whither, const char* restrict whence, int c, size_t maxlen) +{ + const char* stop = memchr(whence, c, maxlen); + size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memcpy(whither, whence, n); + memset(whither, 0, maxlen - n); + return r; +} + diff --git a/src/string/strcnmove.c b/src/string/strcnmove.c new file mode 100644 index 0000000..f418e92 --- /dev/null +++ b/src/string/strcnmove.c @@ -0,0 +1,54 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte or a specified byte is encountered. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param c The stop byte. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `NULL` if `c` was not encountered, otherwise + * the position of `c` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strcnmove(char* whither, const char* whence, int c, size_t maxlen) +{ + const char* stop = memchr(whence, c, maxlen); + size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memmove(whither, whence, n); + memset(whither, 0, maxlen - n); + return r; +} + diff --git a/src/string/strcpy.c b/src/string/strcpy.c index 17dd339..75d88e7 100644 --- a/src/string/strcpy.c +++ b/src/string/strcpy.c @@ -32,187 +32,3 @@ char* strcpy(char* restrict whither, const char* restrict whence) return memcpy(whither, whence, strlen(whence) + 1); } - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte is encountered. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @return `whither + strlen(whence)` is returned. - */ -char* stpcpy(char* restrict whither, const char* restrict whence) -{ - return mempcpy(whither, whence, strlen(whence) + 1) - 1; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte or a specified byte is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param c The stop byte. - * @return `NULL` if `c` was not encountered, otherwise - * the position of `c` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strccpy(char* restrict whither, const char* restrict whence, int c) -{ - char* r = memccpy(whither, whence, c, strlen(whence) + 1); - if (r) - *r = 0; - return r; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte or a specified substring is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param str The substring, ignored if `NULL`. - * @return `NULL` if `str` was not encountered, otherwise - * the position of `str` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strstrcpy(char* restrict whither, const char* restrict whence, const char* restrict str) -{ - const char* stop = str == NULL ? NULL : strstr(whence, str); - size_t n = stop == NULL ? strlen(whence) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memcpy(whither, whence, n); - whither[n] = 0; - return r; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte is encountered. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `whither` is returned. - */ -char* strncpy(char* restrict whither, const char* restrict whence, size_t maxlen) -{ - size_t n = strnlen(whence, maxlen); - memcpy(whither, whence, n); - memset(whither, 0, maxlen - n); - return whither; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte is encountered. - * - * This is a GNU extension. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `whither` plus the number of written bytes, - * excluding NUL bytes, is returned. - */ -char* stpncpy(char* restrict whither, const char* restrict whence, size_t maxlen) -{ - size_t n = strnlen(whence, maxlen); - memcpy(whither, whence, n); - memset(whither, 0, maxlen - n); - return whither + n; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte or a specified byte is encountered. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param c The stop byte. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `NULL` if `c` was not encountered, otherwise - * the position of `c` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strcncpy(char* restrict whither, const char* restrict whence, int c, size_t maxlen) -{ - const char* stop = memchr(whence, c, maxlen); - size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memcpy(whither, whence, n); - memset(whither, 0, maxlen - n); - return r; -} - - -/** - * Copy a memory segment to another, non-overlapping, segment, - * stop when a NUL byte or a specified substring is encountered. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param str The substring, ignored if `NULL`. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @param maxlen The maximum number of bytes to copy. - * @return `NULL` if `str` was not encountered, otherwise - * the position of `str` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strstrncpy(char* restrict whither, const char* restrict whence, - const char* restrict str, size_t maxlen) -{ - const char* stop = strnstr(whence, str, maxlen); - size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memcpy(whither, whence, n); - memset(whither, 0, maxlen - n); - return r; -} - diff --git a/src/string/strcspn.c b/src/string/strcspn.c new file mode 100644 index 0000000..35b3404 --- /dev/null +++ b/src/string/strcspn.c @@ -0,0 +1,44 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Returns length of the initial substring + * that consists entirely of the complement + * of a set of specified bytes. + * + * @param string The string. + * @param stopset Bytes disallowed in the substring. + * @return The length of the substring. + */ +size_t strcspn(const char* string, const char* stopset) +{ + char set[256]; + char c; + const char* s = string; + memset(set, 0, 256); + while ((c = *stopset++)) + set[(size_t)c] = 1; + while ((c = *s++)) + if (!set[(size_t)c]) + break; + return (size_t)(s - 1 - string); +} + diff --git a/src/string/strdup.c b/src/string/strdup.c index 6a66c2c..b7155d7 100644 --- a/src/string/strdup.c +++ b/src/string/strdup.c @@ -36,44 +36,3 @@ char* strdup(const char* string) return r == NULL ? NULL : memcpy(r, string, n * sizeof(char)); } - -/** - * Duplicate a string. - * - * This is a GNU extension. - * - * @param string The string to duplicate. - * @param maxlen Truncate the string to this length, if it is longer. - * A NUL byte is guaranteed to always be written - * upon successful completion. - * @return The new string. `NULL` is returned on error - * and `errno` is set to indicate the error. - * - * @throws ENOMEM The process could not allocate sufficient amount of memory. - */ -char* strndup(const char* string, size_t maxlen) -{ - size_t n = strnlen(string, maxlen) + 1; - char* r = malloc(n * sizeof(char)); - return r == NULL ? NULL : memcpy(r, string, n * sizeof(char)); -} - - -/** - * Duplicate a memory segment. - * - * This is a slibc extension. - * - * @param segment The memory segment to duplicate. - * @param size The size of the memory segment. - * @return The new segment. `NULL` is returned on error - * and `errno` is set to indicate the error. - * - * @throws ENOMEM The process could not allocate sufficient amount of memory. - */ -void* memdup(const void* segment, size_t size) -{ - void* r = malloc(size); - return r == NULL ? NULL : memcpy(r, segment, size); -} - diff --git a/src/string/strerror.c b/src/string/strerror.c index ccce049..315e40d 100644 --- a/src/string/strerror.c +++ b/src/string/strerror.c @@ -16,7 +16,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> -#include <errno.h> @@ -43,86 +42,3 @@ char* strerror(int errnum) return strerror_l(errnum, 0 /* TODO CURRENT_LOCALE, not defined */); } - -/** - * Return a textual representation of an error code. - * This error code must from `errno`. - * - * POSIX specifies `errno` may only be set on failure, - * and reserves no return value to indicate such. - * You should therefore, set `errno` to zero before calling - * this function, and inspect `errno` when it returns. - * - * The returned value must not be modified or freed. - * - * @param errnum The error code. - * @param locale The locale, must be a valid locale and not - * `LC_GLOBAL_LOCALE`, lest the behaviour is undefined. - * @return A description of the error. - */ -char* strerror_l(int errnum, locale_t locale) -{ - /* TODO implement strerror_l */ - return strerror(errnum); - (void) locale; -} - - -/** - * Reenterant variant of `strerror`. - * - * This is an XSI-compliant extension. However the name - * is not part of the XSI specification, `strerror_r` - * should be used. It is defined to this function if - * `(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE`. - * However it is not defined if _SLIBC_SOURCE is defined. - * - * @param errnum The error code. - * @param buf Buffer where the description shall be stored. - * @param buflen The allocation size of `buf`. - * @return Zero on success, value for `errno` on error - * - * @throws ERANGE `buf` was too small to store the description. - */ -int __xsi_strerror_r(int errnum, char* buf, size_t buflen) -{ - char* description = strerror(errnum); - size_t length = strlen(description); - - if (buflen == 0) - return ERANGE; - - if (buflen <= length) - { - memcpy(buf, description, buflen - 1); - buf[buflen - 1] = 0; - return ERANGE; - } - - return memcpy(buf, description, length + 1), 0; -} - - -/** - * Reenterant variant of `strerror`. - * - * This is a GNU-specific extension. However the name - * is not part of the GNU specification, `strerror_r` should - * be used. It is defined to this function unless - * `(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE`. - * However it is not defined if _SLIBC_SOURCE is defined. - * - * @param errnum The error code. - * @param buf Buffer where the description shall be stored. - * @param buflen The allocation size of `buf`. - * @return `buf` on success, `NULL` on error. On error, `errno` - * is set to indicate the error. - * - * @throws ERANGE `buf` was too small to store the description. - */ -char* __gnu_strerror_r(int errnum, char* buf, size_t buflen) -{ - errno = __xsi_strerror_r(errnum, buf, buflen); - return errno ? NULL : buf; -} - diff --git a/src/string/strerror_l.c b/src/string/strerror_l.c new file mode 100644 index 0000000..838040f --- /dev/null +++ b/src/string/strerror_l.c @@ -0,0 +1,44 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Return a textual representation of an error code. + * This error code must from `errno`. + * + * POSIX specifies `errno` may only be set on failure, + * and reserves no return value to indicate such. + * You should therefore, set `errno` to zero before calling + * this function, and inspect `errno` when it returns. + * + * The returned value must not be modified or freed. + * + * @param errnum The error code. + * @param locale The locale, must be a valid locale and not + * `LC_GLOBAL_LOCALE`, lest the behaviour is undefined. + * @return A description of the error. + */ +char* strerror_l(int errnum, locale_t locale) +{ + /* TODO implement strerror_l */ + return strerror(errnum); + (void) locale; +} + diff --git a/src/string/strerror_r_gnu.c b/src/string/strerror_r_gnu.c new file mode 100644 index 0000000..3e8bfd4 --- /dev/null +++ b/src/string/strerror_r_gnu.c @@ -0,0 +1,45 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <errno.h> + + + +/** + * Reenterant variant of `strerror`. + * + * This is a GNU-specific extension. However the name + * is not part of the GNU specification, `strerror_r` should + * be used. It is defined to this function unless + * `(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE`. + * However it is not defined if _SLIBC_SOURCE is defined. + * + * @param errnum The error code. + * @param buf Buffer where the description shall be stored. + * @param buflen The allocation size of `buf`. + * @return `buf` on success, `NULL` on error. On error, `errno` + * is set to indicate the error. + * + * @throws ERANGE `buf` was too small to store the description. + */ +char* __gnu_strerror_r(int errnum, char* buf, size_t buflen) +{ + errno = __xsi_strerror_r(errnum, buf, buflen); + return errno ? NULL : buf; +} + diff --git a/src/string/strerror_r_xsi.c b/src/string/strerror_r_xsi.c new file mode 100644 index 0000000..70c3bc8 --- /dev/null +++ b/src/string/strerror_r_xsi.c @@ -0,0 +1,56 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <errno.h> + + + +/** + * Reenterant variant of `strerror`. + * + * This is an XSI-compliant extension. However the name + * is not part of the XSI specification, `strerror_r` + * should be used. It is defined to this function if + * `(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE`. + * However it is not defined if _SLIBC_SOURCE is defined. + * + * @param errnum The error code. + * @param buf Buffer where the description shall be stored. + * @param buflen The allocation size of `buf`. + * @return Zero on success, value for `errno` on error + * + * @throws ERANGE `buf` was too small to store the description. + */ +int __xsi_strerror_r(int errnum, char* buf, size_t buflen) +{ + char* description = strerror(errnum); + size_t length = strlen(description); + + if (buflen == 0) + return ERANGE; + + if (buflen <= length) + { + memcpy(buf, description, buflen - 1); + buf[buflen - 1] = 0; + return ERANGE; + } + + return memcpy(buf, description, length + 1), 0; +} + diff --git a/src/string/strlen.c b/src/string/strlen.c index 449fff0..2092ddc 100644 --- a/src/string/strlen.c +++ b/src/string/strlen.c @@ -18,9 +18,6 @@ #include <string.h> -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" - - /** * Returns the number of bytes in a NUL-terminated @@ -31,24 +28,8 @@ */ size_t strlen(const char* str) { - char* s = str; + const char* s = str; while (*str++); return (size_t)(s - 1 - str); } - -/** - * Variant of `strlen` that only inspects the - * beginning of s string. - * - * @param str The string. - * @param maxlen The number of bytes to inspect, at most. - * @return The number of bytes before, the first NUL byte. - * `maxlen` if no NUL byte was found. - */ -size_t strnlen(const char* str, size_t maxlen) -{ - const char* end = memchr(str, 0, maxlen); - return end == NULL ? maxlen : (size_t)(end - str); -} - diff --git a/src/string/strmove.c b/src/string/strmove.c index 596822a..4bd52f4 100644 --- a/src/string/strmove.c +++ b/src/string/strmove.c @@ -34,189 +34,3 @@ char* strmove(char* whither, const char* whence) return memmove(whither, whence, strlen(whence) + 1); } - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @return `whither + strlen(whence)` is returned. - */ -char* stpmove(char* whither, const char* whence) -{ - return mempmove(whither, whence, strlen(whence) + 1) - 1; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte or a specified byte is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param c The stop byte. - * @return `NULL` if `c` was not encountered, otherwise - * the position of `c` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strcmove(char* whither, const char* whence, int c) -{ - char* r = memcmove(whither, whence, c, strlen(whence) + 1); - if (r) - *r = 0; - return r; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte or a specified substring is encountered. - * - * This is a slibc extension added for completeness. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param str The substring, ignored if `NULL`. - * @return `NULL` if `str` was not encountered, otherwise - * the position of `str` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strstrmove(char* whither, const char* whence, const char* restrict str) -{ - const char* stop = str == NULL ? NULL : strstr(whence, str); - size_t n = stop == NULL ? strlen(whence) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memmove(whither, whence, n); - whither[n] = 0; - return r; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte is encountered. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `whither` is returned. - */ -char* strnmove(char* whither, const char* whence, size_t maxlen) -{ - size_t n = strnlen(whence, maxlen); - memmove(whither, whence, n); - memset(whither, 0, maxlen - n); - return whither; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte is encountered. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `whither` plus the number of written bytes, - * excluding NUL bytes, is returned. - */ -char* stpnmove(char* whither, const char* whence, size_t maxlen) -{ - size_t n = strnlen(whence, maxlen); - memmove(whither, whence, n); - memset(whither, 0, maxlen - n); - return whither + n; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte or a specified byte is encountered. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param c The stop byte. - * @param maxlen The maximum number of bytes to copy. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @return `NULL` if `c` was not encountered, otherwise - * the position of `c` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strcnmove(char* whither, const char* whence, int c, size_t maxlen) -{ - const char* stop = memchr(whence, c, maxlen); - size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memmove(whither, whence, n); - memset(whither, 0, maxlen - n); - return r; -} - - -/** - * Copy a memory segment to another, possibly overlapping, segment, - * stop when a NUL byte or a specified substring is encountered. - * - * This is a slibc extension added for completeness. - * It is only available if GNU extensions are available. - * - * @param whither The destination memory segment. - * @param whence The source memory segment. - * @param str The substring, ignored if `NULL`. - * NOTE that if the resulting string at least this - * long, no NUL byte will be written to `whither'. - * On the otherhand, if the resultnig string is - * shorter, `whither` will be filled with NUL bytes - * until this amount of bytes have been written. - * @param maxlen The maximum number of bytes to copy. - * @return `NULL` if `str` was not encountered, otherwise - * the position of `str` translated to `whither`, - * that is, the address of `whither` plus the - * number of copied characters; the address of - * one character passed the last written non-NUL - * character. - */ -char* strstrnmove(char* whither, const char* whence, const char* restrict str, size_t maxlen) -{ - const char* stop = strnstr(whence, str, maxlen); - size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); - char* r = stop == NULL ? NULL : (whither + n); - memmove(whither, whence, n); - memset(whither, 0, maxlen - n); - return r; -} - diff --git a/src/string/strncasecmp.c b/src/string/strncasecmp.c new file mode 100644 index 0000000..919ff36 --- /dev/null +++ b/src/string/strncasecmp.c @@ -0,0 +1,50 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <ctype.h> + + + +/** + * Compare two strings alphabetically in a case insensitive manner. + * Be aware, only ASCII characters are case insensitive, non-ASCII + * characters are case sensitive. + * + * @param a A negative value is returned if this is the lesser. + * @param b A positive value is returned if this is the lesser. + * @param length The maximum number of characters to compare. + * @return Zero is returned if `a` and `b` are equal, otherwise, + * see the specifications for `a` and `b`. + */ +int strncasecmp(const char* a, const char* b, size_t length) +{ + int c1, c2; + for (; length--; a++, b++) + if (*a != *b) + { + c1 = isalpha(*a) ? tolower(*a) : (int)*a; + c2 = isalpha(*b) ? tolower(*b) : (int)*b; + if ((c1 -= c2)) + return c1; + } + else if (!*a && !*b) return 0; + else if (!*a) return -1; + else if (!*b) return +1; + return 0; +} + diff --git a/src/string/strncat.c b/src/string/strncat.c new file mode 100644 index 0000000..e7db0f2 --- /dev/null +++ b/src/string/strncat.c @@ -0,0 +1,43 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Concatenate a string to the end of another string. + * The resulting strings must not overlap with the appended string. + * + * The use of this function is often a really bad idea. + * + * @param whither The string to extend. + * @param whence The string to append. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `whither` is returned. + */ +char* strncat(char* restrict whither, const char* restrict whence, size_t maxlen) +{ + strncpy(whither + strlen(whither), whence, maxlen); + return whither; +} + diff --git a/src/string/strncmp.c b/src/string/strncmp.c new file mode 100644 index 0000000..daf5be5 --- /dev/null +++ b/src/string/strncmp.c @@ -0,0 +1,39 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Compare two strings alphabetically in a case sensitive manner. + * + * @param a A negative value is returned if this is the lesser. + * @param b A positive value is returned if this is the lesser. + * @param length The maximum number of characters to compare. + * @return Zero is returned if `a` and `b` are equal, otherwise, + * see the specifications for `a` and `b`. + */ +int strncmp(const char* a, const char* b, size_t length) +{ + size_t n = strnlen(a, length); + size_t m = strnlen(b, length); + int r = memcmp(a, b, (n < m ? n : m)); + return r ? r : n == m ? 0 : n < m ? -1 : +1; +} + + diff --git a/src/string/strncpy.c b/src/string/strncpy.c new file mode 100644 index 0000000..f3eba84 --- /dev/null +++ b/src/string/strncpy.c @@ -0,0 +1,43 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte is encountered. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `whither` is returned. + */ +char* strncpy(char* restrict whither, const char* restrict whence, size_t maxlen) +{ + size_t n = strnlen(whence, maxlen); + memcpy(whither, whence, n); + memset(whither, 0, maxlen - n); + return whither; +} + diff --git a/src/string/strndup.c b/src/string/strndup.c new file mode 100644 index 0000000..ca3b3f0 --- /dev/null +++ b/src/string/strndup.c @@ -0,0 +1,43 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> +#include <stdlib.h> + + + +/** + * Duplicate a string. + * + * This is a GNU extension. + * + * @param string The string to duplicate. + * @param maxlen Truncate the string to this length, if it is longer. + * A NUL byte is guaranteed to always be written + * upon successful completion. + * @return The new string. `NULL` is returned on error + * and `errno` is set to indicate the error. + * + * @throws ENOMEM The process could not allocate sufficient amount of memory. + */ +char* strndup(const char* string, size_t maxlen) +{ + size_t n = strnlen(string, maxlen) + 1; + char* r = malloc(n * sizeof(char)); + return r == NULL ? NULL : memcpy(r, string, n * sizeof(char)); +} + diff --git a/src/string/strnlen.c b/src/string/strnlen.c new file mode 100644 index 0000000..5473682 --- /dev/null +++ b/src/string/strnlen.c @@ -0,0 +1,36 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Variant of `strlen` that only inspects the + * beginning of a string. + * + * @param str The string. + * @param maxlen The number of bytes to inspect, at most. + * @return The number of bytes before, the first NUL byte. + * `maxlen` if no NUL byte was found. + */ +size_t strnlen(const char* str, size_t maxlen) +{ + const char* end = memchr(str, 0, maxlen); + return end == NULL ? maxlen : (size_t)(end - str); +} + diff --git a/src/string/strnmove.c b/src/string/strnmove.c new file mode 100644 index 0000000..a7ec028 --- /dev/null +++ b/src/string/strnmove.c @@ -0,0 +1,43 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte is encountered. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param maxlen The maximum number of bytes to copy. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @return `whither` is returned. + */ +char* strnmove(char* whither, const char* whence, size_t maxlen) +{ + size_t n = strnlen(whence, maxlen); + memmove(whither, whence, n); + memset(whither, 0, maxlen - n); + return whither; +} + diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c new file mode 100644 index 0000000..8499d31 --- /dev/null +++ b/src/string/strpbrk.c @@ -0,0 +1,47 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * This function works like `strcspn`, + * except it returns the pointer to the + * location of the first found non-matching + * byte. + * + * @param string The string. + * @param stopset Bytes disallowed in the substring. + * @return A pointer to the first occurrence in + * `string` of a byte found in `stopset`. + * `NULL` is returned if none is found. + */ +char* (strpbrk)(const char* string, const char* stopset) +{ + char set[256]; + char c; + const char* s = string; + memset(set, 0, 256); + while ((c = *stopset++)) + set[(size_t)c] = 1; + while ((c = *s++)) + if (!set[(size_t)c]) + break; + return c ? (s - 1) : NULL; +} + diff --git a/src/string/strsep.c b/src/string/strsep.c new file mode 100644 index 0000000..9fa0cff --- /dev/null +++ b/src/string/strsep.c @@ -0,0 +1,51 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Tokenise a string. + * + * @param string Pointer to the string to tokenise on the first call, + * will be updated to keep track of the state. + * All bytes found in `delimiters` will + * be overriden with NUL bytes. + * @param delimiters Delimiting bytes (not characters). + * @return The next, possibly empty, string that does + * not contain a byte from `delimiters`. The + * returned string will be as long as possible. + * `NULL` is returned the search as reached + * the end of the string, and there therefore + * are no more tokens. + */ +char* strsep(char** restrict string, const char* restrict delimiters) +{ + char* r = *string; + char* next; + if (r == NULL) + return NULL; + + next = strpbrk(r, delimiters); + if (next != NULL) + *next++ = 0; + *string = next; + + return r; +} + diff --git a/src/string/strspn.c b/src/string/strspn.c index 511a4bc..1b2e034 100644 --- a/src/string/strspn.c +++ b/src/string/strspn.c @@ -18,9 +18,6 @@ #include <string.h> -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" - - /** * Returns length of the initial substring @@ -45,54 +42,3 @@ size_t strspn(const char* string, const char* skipset) return (size_t)(s - 1 - string); } - -/** - * Returns length of the initial substring - * that consists entirely of the complement - * of a set of specified bytes. - * - * @param string The string. - * @param stopset Bytes disallowed in the substring. - * @return The length of the substring. - */ -size_t strcspn(const char* string, const char* stopset) -{ - char set[256]; - char c; - const char* s = string; - memset(set, 0, 256); - while ((c = *stopset++)) - set[(size_t)c] = 1; - while ((c = *s++)) - if (!set[(size_t)c]) - break; - return (size_t)(s - 1 - string); -} - - -/** - * This function works like `strcspn`, - * except it returns the pointer to the - * location of the first found non-matching - * byte. - * - * @param string The string. - * @param stopset Bytes disallowed in the substring. - * @return A pointer to the first occurrence in - * `string` of a byte found in `stopset`. - * `NULL` is returned if none is found. - */ -char* (strpbrk)(const char* string, const char* stopset) -{ - char set[256]; - char c; - const char* s = string; - memset(set, 0, 256); - while ((c = *stopset++)) - set[(size_t)c] = 1; - while ((c = *s++)) - if (!set[(size_t)c]) - break; - return c ? (s - 1) : NULL; -} - diff --git a/src/string/strstrcpy.c b/src/string/strstrcpy.c new file mode 100644 index 0000000..9dc9105 --- /dev/null +++ b/src/string/strstrcpy.c @@ -0,0 +1,47 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte or a specified substring is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param str The substring, ignored if `NULL`. + * @return `NULL` if `str` was not encountered, otherwise + * the position of `str` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strstrcpy(char* restrict whither, const char* restrict whence, const char* restrict str) +{ + const char* stop = str == NULL ? NULL : strstr(whence, str); + size_t n = stop == NULL ? strlen(whence) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memcpy(whither, whence, n); + whither[n] = 0; + return r; +} + diff --git a/src/string/strstrmove.c b/src/string/strstrmove.c new file mode 100644 index 0000000..19969cd --- /dev/null +++ b/src/string/strstrmove.c @@ -0,0 +1,47 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte or a specified substring is encountered. + * + * This is a slibc extension added for completeness. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param str The substring, ignored if `NULL`. + * @return `NULL` if `str` was not encountered, otherwise + * the position of `str` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strstrmove(char* whither, const char* whence, const char* restrict str) +{ + const char* stop = str == NULL ? NULL : strstr(whence, str); + size_t n = stop == NULL ? strlen(whence) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memmove(whither, whence, n); + whither[n] = 0; + return r; +} + diff --git a/src/string/strstrncpy.c b/src/string/strstrncpy.c new file mode 100644 index 0000000..0beb8ec --- /dev/null +++ b/src/string/strstrncpy.c @@ -0,0 +1,55 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, non-overlapping, segment, + * stop when a NUL byte or a specified substring is encountered. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param str The substring, ignored if `NULL`. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @param maxlen The maximum number of bytes to copy. + * @return `NULL` if `str` was not encountered, otherwise + * the position of `str` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strstrncpy(char* restrict whither, const char* restrict whence, + const char* restrict str, size_t maxlen) +{ + const char* stop = strnstr(whence, str, maxlen); + size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memcpy(whither, whence, n); + memset(whither, 0, maxlen - n); + return r; +} + diff --git a/src/string/strstrnmove.c b/src/string/strstrnmove.c new file mode 100644 index 0000000..9bec614 --- /dev/null +++ b/src/string/strstrnmove.c @@ -0,0 +1,54 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Copy a memory segment to another, possibly overlapping, segment, + * stop when a NUL byte or a specified substring is encountered. + * + * This is a slibc extension added for completeness. + * It is only available if GNU extensions are available. + * + * @param whither The destination memory segment. + * @param whence The source memory segment. + * @param str The substring, ignored if `NULL`. + * NOTE that if the resulting string at least this + * long, no NUL byte will be written to `whither'. + * On the otherhand, if the resultnig string is + * shorter, `whither` will be filled with NUL bytes + * until this amount of bytes have been written. + * @param maxlen The maximum number of bytes to copy. + * @return `NULL` if `str` was not encountered, otherwise + * the position of `str` translated to `whither`, + * that is, the address of `whither` plus the + * number of copied characters; the address of + * one character passed the last written non-NUL + * character. + */ +char* strstrnmove(char* whither, const char* whence, const char* restrict str, size_t maxlen) +{ + const char* stop = strnstr(whence, str, maxlen); + size_t n = stop == NULL ? strnlen(whence, maxlen) : (size_t)(stop - whence); + char* r = stop == NULL ? NULL : (whither + n); + memmove(whither, whence, n); + memset(whither, 0, maxlen - n); + return r; +} + diff --git a/src/string/strtok.c b/src/string/strtok.c index 0ccd516..b1b56b9 100644 --- a/src/string/strtok.c +++ b/src/string/strtok.c @@ -42,70 +42,3 @@ char* strtok(char* restrict string, const char* restrict delimiters) return strtok_r(string, delimiters, &state); } - -/** - * Tokenise a string. - * - * @param string The string to tokenise on the first, - * `NULL` on subsequent calls. - * All bytes found in `delimiters` will - * be overriden with NUL bytes. - * @param delimiters Delimiting bytes (not characters). - * @param state Pointer to a `char*` that the function - * can use to keep track of its state. - * It is reasonable to make it point to `NULL` - * on the first call. - * @return The next non-empty string that does not - * contain a byte from `delimiters`. The - * returned string will be as long as possible. - * `NULL` is returned the search as reached - * the end of the string, and there therefore - * are no more tokens. - */ -char* strtok_r(char* restrict string, const char* restrict delimiters, - char** restrict state) -{ - char* r; - if (string == NULL) - *state = string; - for (;;) - { - r = strsep(state, delimiters); - if (r == NULL) - return NULL; - if (*r) - return r; - } -} - - -/** - * Tokenise a string. - * - * @param string Pointer to the string to tokenise on the first call, - * will be updated to keep track of the state. - * All bytes found in `delimiters` will - * be overriden with NUL bytes. - * @param delimiters Delimiting bytes (not characters). - * @return The next, possibly empty, string that does - * not contain a byte from `delimiters`. The - * returned string will be as long as possible. - * `NULL` is returned the search as reached - * the end of the string, and there therefore - * are no more tokens. - */ -char* strsep(char** restrict string, const char* restrict delimiters) -{ - char* r = *string; - char* next; - if (r == NULL) - return NULL; - - next = strpbrk(r, delimiters); - if (next != NULL) - *next++ = 0; - *string = next; - - return r; -} - diff --git a/src/string/strtok_r.c b/src/string/strtok_r.c new file mode 100644 index 0000000..3005ac7 --- /dev/null +++ b/src/string/strtok_r.c @@ -0,0 +1,56 @@ +/** + * slibc — Yet another C library + * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <string.h> + + + +/** + * Tokenise a string. + * + * @param string The string to tokenise on the first, + * `NULL` on subsequent calls. + * All bytes found in `delimiters` will + * be overriden with NUL bytes. + * @param delimiters Delimiting bytes (not characters). + * @param state Pointer to a `char*` that the function + * can use to keep track of its state. + * It is reasonable to make it point to `NULL` + * on the first call. + * @return The next non-empty string that does not + * contain a byte from `delimiters`. The + * returned string will be as long as possible. + * `NULL` is returned the search as reached + * the end of the string, and there therefore + * are no more tokens. + */ +char* strtok_r(char* restrict string, const char* restrict delimiters, + char** restrict state) +{ + char* r; + if (string == NULL) + *state = string; + for (;;) + { + r = strsep(state, delimiters); + if (r == NULL) + return NULL; + if (*r) + return r; + } +} + |