//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: String manipulation utilities // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K 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 // // any later version. // // // // OS/K 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 OS/K. If not, see <https://www.gnu.org/licenses/>. // //----------------------------------------------------------------------------// #include <kalbase.h> // // Compare two strings // int strcmp(const char *str1, const char *str2) { while (*str1 == *str2 && *str2) str1++, str2++; return *(uchar *)str1 - *(uchar *)str2; } // // Compare at most n bytes of two strings // int strncmp(const char *str1, const char *str2, size_t n) { size_t it = 0; while (*str1 == *str2 && *str2 && it < n) str1++, str2++, it++; return *(uchar *)str1 - *(uchar *)str2; } // // Return str's length // size_t strlen(const char *str) { const char *base = str; while (*str) str++; return str - base; } // // Return a pointer to the first occurence of ch in str, // or str's null-terminator if none is found // char *strchrnul(const char *str, int ch) { while ((*str && *str != (char)ch)) str++; return (char *)str; } // // Return a pointer to the first occurence of ch in str, // NULL if none is found // char *strchr(const char *str, int ch) { while ((*str && *str != (char)ch)) str++; return *str ? (char *)str : NULL; } // // Return a point to the last occurence of ch in str, // NULL if none is found // char *strrchr(const char *str, int ch) { char *ptr = NULL; while (*str) { if (*str == ch) { ptr = (char *)str; } str++; } return ptr; } // // Return the length of the longest inital segment of str // that only contains characters in acc // size_t strspn(const char *str, const char *acc) { const char *ptr = str; while (*ptr && strchr(acc, *ptr) != NULL) ptr++; return ptr - str; } // // Return the length of the longest initial segment of str // that does not contain any character in rej // size_t strcspn(const char *str, const char *rej) { const char *ptr = str; while (*ptr && strchr(rej, *ptr) == NULL) ptr++; return ptr - str; } // // Return the first occurence in str of any byte in acc // char *strpbrk(const char *str, const char *acc) { str += strcspn(str, acc); return *str ? (char *)str : NULL; } // // Return the first occurence of the substring needle // in the string haystack, NULL if none is found // Null-terminators aren't compared // char *strstr(const char *haystack, const char *needle) { const size_t needle_size = strlen(needle); // Moves haystack to first occurence of the needle's first byte while ((haystack = strchr(haystack, *needle)) != NULL) { if (strncmp(haystack, needle, needle_size) == 0) { return (char *)haystack; } } return NULL; } // // Tokenize a string, using saveptr as a savestate // We let a segmentation fault happen if *saveptr == NULL // char *strtok_r(char *restrict str, const char *restrict delim, char **restrict saveptr) { assert(*saveptr != NULL); if (str == NULL) str = *saveptr; // Skip initial segments composed only of delimiters str += strspn(str, delim); // If str is empty, store it in saveptr so that next call // still finds an empty strings and returns NULL if (*str == 0) { *saveptr = str; return NULL; } char *ptr = str, *tok_end = strpbrk(str, delim); // // If we found the last token, set *saveptr to a str's null-terminator // Otherwise, null-terminate token and save next byte // if (tok_end == NULL) { while (*ptr) ptr++; *saveptr = ptr; } else { *tok_end = 0; *saveptr = tok_end + 1; } return str; } // // Tokenize a string in a very thread-unsafe way // char *strtok(char *restrict str, const char *restrict delim) { static char *saveptr = NULL; // Avoid this function if possible KalAssert(FALSE); if (str) saveptr = str; return strtok_r(str, delim, &saveptr); } // // Copy the string src into dest // char *strcpy(char *restrict dest, const char *restrict src) { char *base = dest; while ((*dest++ = *src++)); return base; } // // strcpy() but always writes n bytes // Will not null-terminate for strings longer than n bytes // char *strncpy(char *restrict dest, const char *restrict src, size_t n) { char *base = dest; while (n-- && (*dest++ = *src++)); while (n--) *dest++ = 0; return base; } // // Copies at most n-1 bytes from src to dest // Always null-terminates dest, but doesn't fill // dest's contents past the null-terminator // // Returns a pointer to the last character of src copied // (In particular it points to src's null-terminator if // and only if every character of src was successfuly copied) // char *strnzcpy(char *restrict dest, const char *restrict src, size_t n) { while (n-- > 1 && (*dest = *src)) dest++, src++; if (*src) *++dest = 0; return (char *)src; } // // Appends a copy of src at the end of dest // char *strcat(char *restrict dest, const char *restrict src) { char *base = dest; while (*dest) dest++; while ((*dest++ = *src++)); return base; } // // Appends a copy of at most n bytes of src at the end of dest // char *strncat(char *restrict dest, const char *restrict src, size_t n) { char *base = dest; while (*dest) dest++; while (n-- && (*dest++ = *src++)); while (n--) *dest++ = 0; return base; } // // Appends at most n-1 bytes from src to dest // Always null-terminates dest, but doesn't fill // dest's contents past the null-terminator // // Returns a pointer to the last character of src copied // (In particular it points to src's null-terminator if // and only if every character of src was successfuly copied) // char *strnzcat(char *restrict dest, const char *restrict src, size_t n) { while (*dest) dest++; while (n-- > 1 && (*dest = *src)) dest++, src++; if (*src) *++dest = 0; return (char *)src; } // // Reverses the string src, putting the result into dest // char *strrev(char *restrict dest, const char *restrict src) { char *orig = dest; size_t n = strlen(src); dest[n--] = '\0'; while ((*dest++ = src[n--])); return orig; } // // Reverses a string, modifying it // char *strrev2(char *str) { char ch, *orig = str; size_t n = strlen(str); char *temp = str + n - 1; while (temp > str) { ch = *temp; *temp-- = *str; *str++ = ch; } return orig; }