/* Copyright (C) 2021,2022 fef . All rights reserved. */ #pragma once #include #include #include /** * @brief Copy up to `n` bytes from `src` to `dest`, but stop when the byte `c` is found. * The regions `src` and `dest` must not overlap. * * @param dest Destination address * @param src Source address * @param c Stop character * @param n Maximum number of bytes * @return A pointer to the next character after `c`, or `NULL` if `c` was not * encountered within the first `n` bytes */ void *memccpy(void *__restrict dest, const void *__restrict src, int c, usize n); /** * @brief Return the first occurrence of byte `c` within the first `n` bytes of `src`. * * @param src Start of buffer to search through * @param c Character to search for * @param n Maximum amount of bytes to search, starting from `src` * @return The address of the found byte, or `NULL` if it was not found * @note Because the run time of this function is not constant with respect * to `n`, it should not be used in cryptographic operations. */ __pure void *memchr(const void *src, int c, usize n); #if _GAY_SOURCE >= 202109L || __BSD_VISIBLE /** * @brief Return the last occurrence of byte `c` within the first `n` bytes of `src`. * This function does the same thing as `memchr()` but in reverse direction. * * @param src Start of buffer to search through * @param c Character to search for * @param n Maximum amount of bytes to search, starting from `src` * @return The address of the found byte, or `NULL` if it was not found * @note Because the run time of this function is not constant with respect * to `n`, it should not be used in cryptographic operations. */ __pure void *memrchr(const void *src, int c, usize n); #endif /* _GAY_SOURCE >= 202109L || __BSD_VISIBLE */ /** * @brief Copy `n` bytes from `src` to `dest`. * The regions `src` and `dest` must not overlap. * * @param dest The destination * @param src The source * @param n The amount of bytes to copy * @returns A pointer to `dest` */ void *memcpy(void *__restrict dest, const void *__restrict src, usize n); /** * @brief Compare two memory regions of size `n` for equality. * * @param s1 The first memory region * @param s2 The second memory region * @param n Amount of bytes to compare * @return 0 if the first `n` bytes in `s1` and `s2` are found to be equal, * or the difference between the first non equal bytes (interpreted as an * `unsigned char`) such that the value is positive if the byte in `s1` * is greater than the one in `s2` * @note Because the run time of this function is not constant with respect * to `n`, it should not be used in cryptographic operations. */ __pure int memcmp(const void *s1, const void *s2, usize n); #ifndef __HAVE_ARCH_MEMSET /** * @brief Starting from `ptr`, fill `n` bytes with the constant byte `c`. * * @param ptr The start of the memory region * @param c The byte to fill with * @param n The amount of bytes to write * @returns A pointer to `ptr` */ void *memset(void *ptr, int c, usize n); #endif #if _GAY_SOURCE >= 202109L #ifndef __HAVE_ARCH_MEMSET16 void *memset16(u16 *dest, u16 c, usize nbyte); #endif #ifndef __HAVE_ARCH_MEMSET32 void *memset32(u32 *dest, u32 c, usize nbyte); #endif #ifndef __HAVE_ARCH_MEMSET64 void *memset64(u64 *dest, u64 c, usize nbyte); #endif #include #if LONG_BIT == 32 #define memsetl memset32 #elif LONG_BIT == 64 #define memsetl memset64 #else #error "Unsupported sizeof(long)" #endif #endif /** * @brief Copy a memory area. * The two areas may overlap since the individual bytes are copied to a * temporary array first. * * @param dest The destination address * @param src The source address * @param n The amount of bytes to copy * @return a pointer to dest */ void *memmove(void *dest, const void *src, usize n); /** * @brief Compare the two strings `s1` and `s2`. * * @param s1 The first string * @param s2 The second string * @returns `0` if both strings are equal, a positive value f `s1` is greater * than `s2`, and a negative value if `s1` is less than `s2` */ __pure int strcmp(const char *s1, const char *s2); /** * @brief Copy a `NUL` terminated string from `src` to `dest`. * The `dest` and `src` regions must not overlap. * * @param dest The destination to copy to. The memory region must be able to * hold the entire string plus one byte for the terminator. * @param src The original string to copy from * @returns A pointer to the destination string */ char *strcpy(char *dest, const char *src); /** * @brief Copy a `NUL` terminated string from `src` to `dest`, but at most `n` characters. * Note that this may cause `dest` to miss a `NUL` terminator. * The `dest` and `src` regions must not overlap. * * @param dest The destination to copy to. The memory region must be able to * hold the entire string plus one byte for the terminator. * @param src The original string to copy from * @param n The amount of characters to copy at most * @returns A pointer to the destination string */ char *strncpy(char *dest, const char *src, usize n); #if _GAY_SOURCE >= 202109L || _POSIX_C_SOURCE >= 200809L /** @brief The same as `strcpy()`, but the returned pointer is the NUL terminator of `dest`. */ char *stpcpy(char *__restrict dest, const char *__restrict src); /** @brief The same as `strncpy()`, but the returned pointer is the NUL terminator of `dest`. */ char *stpncpy(char *__restrict dest, const char *__restrict src, usize n); #endif /* _GAY_SOURCE >= 202109L || _POSIX_C_SOURCE >= 200809L */ /** * @brief Append a NUL terminated string to another string. * `s` must be sufficiently large to hold both strings. * * @param s String to append the other string to * @param append String to append to `s` * @return A pointer to `s` */ char *strcat(char *__restrict s, const char *__restrict append); /** * @brief Append a NUL terminated string to another string, but at most `count` bytes. * * @param s String to be appended to * @param append String to append to `s` * @param count Maximum amount of bytes to append, excluding the NUL terminator * which is always appended at the end * @return A pointer to `s` */ char *strncat(char *__restrict s, const char *__restrict append, usize count); /** * @brief Compare two strings for equality. * * @param s1 First string to compare * @param s2 Second string to compare * @param n Maximum amount of bytes (characters) to check. If a NUL terminator * is encountered before this limit is reached, the comparison ends early. * @return 0 if the strings are equal up to byte `n`, or the difference between * the first non equal characters cast to an `unsigned char` (such that the * return value becomes positive if the character in `s1` has a greater * numerical value as the one in `s2`) */ int strncmp(const char *s1, const char *s2, usize n); #if _GAY_SOURCE >= 202109L || __BSD_VISIBLE /** * @brief Append a NUL terminated string to another string, such that the * resulting string is at most `dstsize` bytes long (including the NUL terminator) . * * @param s String to be appended to * @param append String to append to `s` * @param n Maximum total length of `s` in bytes * @return A pointer to `s` */ usize strlcat(char *__restrict s, const char *__restrict append, usize dstsize); /** * @brief Copy the NUL terminated string `src` into dest, but at most `dstsize` * bytes (including the NUL terminator, which is always appended). * * @param dest Destination address * @param src Source string to copy from * @param dstsize Maximum bytes (including NUL) to write to `dest` * @return The amount of characters copied, including the NUL terminator */ usize strlcpy(char *__restrict dest, const char *__restrict src, usize dstsize); #endif /* _GAY_SOURCE >= 202109L || __BSD_VISIBLE */ /** * @brief Compute the length of the `NUL` terminated string `s`. * * @param s The string * @returns The length of `s` without the `NUL` terminator */ __pure usize strlen(const char *s); #if _POSIX_C_SOURCE >= 200809L || _GAY_SOURCE >= 202109L || __BSD_VISIBLE /** * @brief Compute the length of the `NUL` terminated string `s`, but at most `maxlen` bytes. * * @param s The string * @param maxlen Maximum bytes after which to return * @returns The length of `s` without the `NUL` terminator, but at most `maxlen` */ __pure size_t strnlen(const char *s, usize maxlen); #endif /** * @brief Search a string for any in a set of characters (excluding NUL). * * @param s String to search through * @param find A set of characters to search for in `s` * @return The first occurrence of one of the characters of `find` in `s`, * or `NULL` if none were found */ __pure char *strpbrk(const char *s, const char *find); /** * @brief Span a string. * * @param s String to span * @param charset Set of characters that should appear in `s` * @return A pointer to the first character in `s` that *is not* within `charset`. * @see `strcspn()` */ __pure usize strspn(const char *s, const char *charset); /** * @brief Span a string. * * @param s String to span * @param charset Set of characters that may *not* appear in `s` * @return A pointer to the first character in `s` that *is* within `charset`. * @see `strspn()` */ __pure usize strcspn(const char *s, const char *charset); /** * @brief Find the first occurrence of `find` within `s`. * * @param s Haystack to search through * @param find Needle to find * @return A pointer to the beginning of the first occurrence of `find` in `s`, * or `NULL` if it was not found */ __pure char *strstr(const char *s, const char *find); #if _GAY_SOURCE >= 202109L || __BSD_VISIBLE /** * @brief Find the first occurrence of `find` within the first `slen` characters of `s`. * If A NUL terminator is encountered in `s`, the search is aborted early. * * @param s Haystack to search through * @param find Needle to find * @param slen Maximum characters to search in `s` * @return A pointer to the beginning of the first occurrence of `find` in `s`, * or `NULL` if it was not found */ __pure char *strnstr(const char *s, const char *find, usize slen); #endif /* _GAY_SOURCE >= 202109L || __BSD_VISIBLE */ /** * @brief Duplicate a string. * * @param s String to duplicate * @return A newly allocated copy of the string, or `NULL` if OOM */ __attribute__(( malloc )) char *strdup(const char *s); #if _POSIX_C_SOURCE >= 200809L /** * @brief Duplicate a string, but copy at most `maxlen` bytes (including NUL). * New memory will be allocated. * * @param s String to duplicate * @param maxlen Maximum length of the copied string in bytes */ __attribute__(( malloc )) char *strndup(const char *s, usize maxlen); #endif /** * @brief Locate a character in a string. * * @param s String to search through * @param c Character to search for * @return The position of the *first* occurrence of `c` within `s`, * or `NULL` if the character was not found */ __pure char *strchr(const char *s, int c); #if _GAY_SOURCE >= 202109L || __BSD_VISIBLE /** * @brief Locate a character in a string in reverse order. * * @param s String to search through * @param c Character to search for * @return The position of the *last* occurrence of `c` within `s`, * or `NULL` if the character was not found */ __pure char *strrchr(const char *s, int c); /** * @brief Locate a character in a string. * * @param s String to search through * @param c Character to search for * @return The position of the first occurrence of `c` within `s`, * or the NUL terminator of `s` if the character was not not found */ __pure char *strchrnul(const char *s, int c); /** * @brief Separate a string into individual tokens. * This is a slightly more sane replacement for `strtok()`. * * @param stringp Pointer to a `char *`, which will be advanced to one character * after the first occurrence of one of the characters in `delim` (or NUL). * The found delimiter is replaced with a NUL byte. * @param delim A set of delimiter tokens * @return The original value of `*stringp`, or `NULL` if it was `NULL`. * If this points to a NUL terminator, the end of the string was reached. */ char *strsep(char **stringp, const char *delim); #endif /* _GAY_SOURCE >= 202109L || __BSD_VISIBLE */ #ifndef _KERNEL /* we *really* don't want this anywhere in kernel code */ char *strtok(char *__restrict s, const char *__restrict tok); # if _POSIX_C_SOURCE >= 199506L char *strtok_r(char *s, const char *delim, char **last); # endif /* _POSIX_C_SOURCE >= 199506L */ #endif /* not _KERNEL */