You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
12 KiB
C

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#pragma once
#include <arch/string.h>
#include <gay/cdefs.h>
#include <gay/types.h>
/**
* @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 <limits.h>
#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 */