diff options
Diffstat (limited to 'src/fundamental/string-util-fundamental.h')
-rw-r--r-- | src/fundamental/string-util-fundamental.h | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/fundamental/string-util-fundamental.h b/src/fundamental/string-util-fundamental.h new file mode 100644 index 0000000..d823147 --- /dev/null +++ b/src/fundamental/string-util-fundamental.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#ifdef SD_BOOT +# include <efi.h> +# include <efilib.h> +# include "efi-string.h" +#else +# include <string.h> +#endif + +#include "macro-fundamental.h" + +#ifdef SD_BOOT +# define strlen strlen16 +# define strcmp strcmp16 +# define strncmp strncmp16 +# define strcasecmp strcasecmp16 +# define strncasecmp strncasecmp16 +# define STR_C(str) (L ## str) +typedef char16_t sd_char; +#else +# define STR_C(str) (str) +typedef char sd_char; +#endif + +#define streq(a,b) (strcmp((a),(b)) == 0) +#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0) +#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) + +static inline int strcmp_ptr(const sd_char *a, const sd_char *b) { + if (a && b) + return strcmp(a, b); + + return CMP(a, b); +} + +static inline int strcasecmp_ptr(const sd_char *a, const sd_char *b) { + if (a && b) + return strcasecmp(a, b); + + return CMP(a, b); +} + +static inline bool streq_ptr(const sd_char *a, const sd_char *b) { + return strcmp_ptr(a, b) == 0; +} + +static inline bool strcaseeq_ptr(const sd_char *a, const sd_char *b) { + return strcasecmp_ptr(a, b) == 0; +} + +static inline size_t strlen_ptr(const sd_char *s) { + if (!s) + return 0; + + return strlen(s); +} + +sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_; +#ifndef SD_BOOT +sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_; +#endif +sd_char *endswith(const sd_char *s, const sd_char *postfix) _pure_; +sd_char *endswith_no_case(const sd_char *s, const sd_char *postfix) _pure_; + +static inline bool isempty(const sd_char *a) { + return !a || a[0] == '\0'; +} + +static inline const sd_char *strempty(const sd_char *s) { + return s ?: STR_C(""); +} + +static inline const sd_char *yes_no(bool b) { + return b ? STR_C("yes") : STR_C("no"); +} + +static inline const sd_char* comparison_operator(int result) { + return result < 0 ? STR_C("<") : result > 0 ? STR_C(">") : STR_C("=="); +} + +int strverscmp_improved(const sd_char *a, const sd_char *b); + +/* Like startswith(), but operates on arbitrary memory blocks */ +static inline void *memory_startswith(const void *p, size_t sz, const sd_char *token) { + assert(token); + + size_t n = strlen(token) * sizeof(sd_char); + if (sz < n) + return NULL; + + assert(p); + + if (memcmp(p, token, n) != 0) + return NULL; + + return (uint8_t*) p + n; +} + +#define _STRV_FOREACH(s, l, i) \ + for (typeof(*(l)) *s, *i = (l); (s = i) && *i; i++) + +#define STRV_FOREACH(s, l) \ + _STRV_FOREACH(s, l, UNIQ_T(i, UNIQ)) + +static inline bool ascii_isdigit(sd_char a) { + /* A pure ASCII, locale independent version of isdigit() */ + return a >= '0' && a <= '9'; +} + +static inline bool ascii_ishex(sd_char a) { + return ascii_isdigit(a) || (a >= 'a' && a <= 'f') || (a >= 'A' && a <= 'F'); +} + +static inline bool ascii_isalpha(sd_char a) { + /* A pure ASCII, locale independent version of isalpha() */ + return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'); +} |