summaryrefslogtreecommitdiffstats
path: root/src/fundamental/string-util-fundamental.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/fundamental/string-util-fundamental.h120
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');
+}