| /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| #pragma once |
| |
| #if SD_BOOT |
| # include <efi.h> |
| # include <efilib.h> |
| # include "efi-string.h" |
| #else |
| # include <string.h> |
| #endif |
| |
| #include "macro-fundamental.h" |
| |
| #if 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_; |
| #if !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'); |
| } |