boot: Add strcmp8/16
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "efi-string.h"
|
||||
#include "macro-fundamental.h"
|
||||
|
||||
/* String functions for both char and char16_t that should behave the same way as their respective
|
||||
* counterpart in userspace. Where it makes sense, these accept NULL and do something sensible whereas
|
||||
@@ -35,3 +36,54 @@ size_t strlen8(const char *s) {
|
||||
size_t strlen16(const char16_t *s) {
|
||||
return strnlen16(s, SIZE_MAX);
|
||||
}
|
||||
|
||||
#define TOLOWER(c) \
|
||||
({ \
|
||||
typeof(c) _c = (c); \
|
||||
(_c >= 'A' && _c <= 'Z') ? _c + ('a' - 'A') : _c; \
|
||||
})
|
||||
|
||||
#define DEFINE_STRNCASECMP(type, name, tolower) \
|
||||
int name(const type *s1, const type *s2, size_t n) { \
|
||||
if (!s1 || !s2) \
|
||||
return CMP(s1, s2); \
|
||||
\
|
||||
while (n > 0) { \
|
||||
int c1 = *s1; \
|
||||
int c2 = *s2; \
|
||||
if (tolower) { \
|
||||
c1 = TOLOWER(c1); \
|
||||
c2 = TOLOWER(c2); \
|
||||
} \
|
||||
if (!c1 || c1 != c2) \
|
||||
return c1 - c2; \
|
||||
\
|
||||
s1++; \
|
||||
s2++; \
|
||||
n--; \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
DEFINE_STRNCASECMP(char, strncmp8, false);
|
||||
DEFINE_STRNCASECMP(char16_t, strncmp16, false);
|
||||
|
||||
int strcmp8(const char *s1, const char *s2) {
|
||||
return strncmp8(s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
int strcmp16(const char16_t *s1, const char16_t *s2) {
|
||||
return strncmp16(s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
DEFINE_STRNCASECMP(char, strncasecmp8, true);
|
||||
DEFINE_STRNCASECMP(char16_t, strncasecmp16, true);
|
||||
|
||||
int strcasecmp8(const char *s1, const char *s2) {
|
||||
return strncasecmp8(s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
int strcasecmp16(const char16_t *s1, const char16_t *s2) {
|
||||
return strncasecmp16(s1, s2, SIZE_MAX);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <uchar.h>
|
||||
|
||||
@@ -9,3 +10,47 @@ size_t strnlen16(const char16_t *s, size_t n);
|
||||
|
||||
size_t strlen8(const char *s);
|
||||
size_t strlen16(const char16_t *s);
|
||||
|
||||
int strncmp8(const char *s1, const char *s2, size_t n);
|
||||
int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
|
||||
|
||||
int strcmp8(const char *s1, const char *s2);
|
||||
int strcmp16(const char16_t *s1, const char16_t *s2);
|
||||
|
||||
int strncasecmp8(const char *s1, const char *s2, size_t n);
|
||||
int strncasecmp16(const char16_t *s1, const char16_t *s2, size_t n);
|
||||
|
||||
int strcasecmp8(const char *s1, const char *s2);
|
||||
int strcasecmp16(const char16_t *s1, const char16_t *s2);
|
||||
|
||||
static inline bool strneq8(const char *s1, const char *s2, size_t n) {
|
||||
return strncmp8(s1, s2, n) == 0;
|
||||
}
|
||||
|
||||
static inline bool strneq16(const char16_t *s1, const char16_t *s2, size_t n) {
|
||||
return strncmp16(s1, s2, n) == 0;
|
||||
}
|
||||
|
||||
static inline bool streq8(const char *s1, const char *s2) {
|
||||
return strcmp8(s1, s2) == 0;
|
||||
}
|
||||
|
||||
static inline bool streq16(const char16_t *s1, const char16_t *s2) {
|
||||
return strcmp16(s1, s2) == 0;
|
||||
}
|
||||
|
||||
static inline int strncaseeq8(const char *s1, const char *s2, size_t n) {
|
||||
return strncasecmp8(s1, s2, n) == 0;
|
||||
}
|
||||
|
||||
static inline int strncaseeq16(const char16_t *s1, const char16_t *s2, size_t n) {
|
||||
return strncasecmp16(s1, s2, n) == 0;
|
||||
}
|
||||
|
||||
static inline bool strcaseeq8(const char *s1, const char *s2) {
|
||||
return strcasecmp8(s1, s2) == 0;
|
||||
}
|
||||
|
||||
static inline bool strcaseeq16(const char16_t *s1, const char16_t *s2) {
|
||||
return strcasecmp16(s1, s2) == 0;
|
||||
}
|
||||
|
||||
@@ -41,4 +41,111 @@ TEST(strnlen16) {
|
||||
assert_se(strnlen16(u"12\0004", 5) == 2);
|
||||
}
|
||||
|
||||
TEST(strncmp8) {
|
||||
assert_se(strncmp8(NULL, "", 10) < 0);
|
||||
assert_se(strncmp8("", NULL, 10) > 0);
|
||||
assert_se(strncmp8(NULL, NULL, 0) == 0);
|
||||
assert_se(strncmp8(NULL, NULL, 10) == 0);
|
||||
assert_se(strncmp8("", "", 10) == 0);
|
||||
assert_se(strncmp8("abc", "abc", 2) == 0);
|
||||
assert_se(strncmp8("aBc", "aBc", 3) == 0);
|
||||
assert_se(strncmp8("aBC", "aBC", 4) == 0);
|
||||
assert_se(strncmp8("", "a", 0) == 0);
|
||||
assert_se(strncmp8("b", "a", 0) == 0);
|
||||
assert_se(strncmp8("", "a", 3) < 0);
|
||||
assert_se(strncmp8("=", "=", 1) == 0);
|
||||
assert_se(strncmp8("A", "a", 1) < 0);
|
||||
assert_se(strncmp8("a", "A", 2) > 0);
|
||||
assert_se(strncmp8("a", "Aa", 2) > 0);
|
||||
assert_se(strncmp8("12\00034", "12345", 4) < 0);
|
||||
assert_se(strncmp8("12\00034", "12345", SIZE_MAX) < 0);
|
||||
assert_se(strncmp8("abc\0def", "abc", SIZE_MAX) == 0);
|
||||
assert_se(strncmp8("abc\0def", "abcdef", SIZE_MAX) < 0);
|
||||
|
||||
assert_se(strncmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MIN }, 1) == 0);
|
||||
assert_se(strncmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MAX }, 1) == 0);
|
||||
assert_se(strncmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MAX }, 1) < 0);
|
||||
assert_se(strncmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MIN }, 1) > 0);
|
||||
}
|
||||
|
||||
TEST(strncmp16) {
|
||||
assert_se(strncmp16(NULL, u"", 10) < 0);
|
||||
assert_se(strncmp16(u"", NULL, 10) > 0);
|
||||
assert_se(strncmp16(NULL, NULL, 0) == 0);
|
||||
assert_se(strncmp16(NULL, NULL, 10) == 0);
|
||||
assert_se(strncmp16(u"", u"", 0) == 0);
|
||||
assert_se(strncmp16(u"", u"", 10) == 0);
|
||||
assert_se(strncmp16(u"abc", u"abc", 2) == 0);
|
||||
assert_se(strncmp16(u"aBc", u"aBc", 3) == 0);
|
||||
assert_se(strncmp16(u"aBC", u"aBC", 4) == 0);
|
||||
assert_se(strncmp16(u"", u"a", 0) == 0);
|
||||
assert_se(strncmp16(u"b", u"a", 0) == 0);
|
||||
assert_se(strncmp16(u"", u"a", 3) < 0);
|
||||
assert_se(strncmp16(u"=", u"=", 1) == 0);
|
||||
assert_se(strncmp16(u"A", u"a", 1) < 0);
|
||||
assert_se(strncmp16(u"a", u"A", 2) > 0);
|
||||
assert_se(strncmp16(u"a", u"Aa", 2) > 0);
|
||||
assert_se(strncmp16(u"12\00034", u"12345", 4) < 0);
|
||||
assert_se(strncmp16(u"12\00034", u"12345", SIZE_MAX) < 0);
|
||||
assert_se(strncmp16(u"abc\0def", u"abc", SIZE_MAX) == 0);
|
||||
assert_se(strncmp16(u"abc\0def", u"abcdef", SIZE_MAX) < 0);
|
||||
|
||||
assert_se(strncmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ UINT16_MAX }, 1) == 0);
|
||||
assert_se(strncmp16((char16_t[]){ 0 }, (char16_t[]){ UINT16_MAX }, 1) < 0);
|
||||
assert_se(strncmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ 0 }, 1) > 0);
|
||||
}
|
||||
|
||||
TEST(strncasecmp8) {
|
||||
assert_se(strncasecmp8(NULL, "", 10) < 0);
|
||||
assert_se(strncasecmp8("", NULL, 10) > 0);
|
||||
assert_se(strncasecmp8(NULL, NULL, 0) == 0);
|
||||
assert_se(strncasecmp8(NULL, NULL, 10) == 0);
|
||||
assert_se(strncasecmp8("", "", 10) == 0);
|
||||
assert_se(strncasecmp8("abc", "abc", 2) == 0);
|
||||
assert_se(strncasecmp8("aBc", "AbC", 3) == 0);
|
||||
assert_se(strncasecmp8("aBC", "Abc", 4) == 0);
|
||||
assert_se(strncasecmp8("", "a", 0) == 0);
|
||||
assert_se(strncasecmp8("b", "a", 0) == 0);
|
||||
assert_se(strncasecmp8("", "a", 3) < 0);
|
||||
assert_se(strncasecmp8("=", "=", 1) == 0);
|
||||
assert_se(strncasecmp8("A", "a", 1) == 0);
|
||||
assert_se(strncasecmp8("a", "A", 2) == 0);
|
||||
assert_se(strncasecmp8("a", "Aa", 2) < 0);
|
||||
assert_se(strncasecmp8("12\00034", "12345", 4) < 0);
|
||||
assert_se(strncasecmp8("12\00034", "12345", SIZE_MAX) < 0);
|
||||
assert_se(strncasecmp8("abc\0def", "ABC", SIZE_MAX) == 0);
|
||||
assert_se(strncasecmp8("abc\0def", "ABCDEF", SIZE_MAX) < 0);
|
||||
|
||||
assert_se(strncasecmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MIN }, 1) == 0);
|
||||
assert_se(strncasecmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MAX }, 1) == 0);
|
||||
assert_se(strncasecmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MAX }, 1) < 0);
|
||||
assert_se(strncasecmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MIN }, 1) > 0);
|
||||
}
|
||||
|
||||
TEST(strncasecmp16) {
|
||||
assert_se(strncasecmp16(NULL, u"", 10) < 0);
|
||||
assert_se(strncasecmp16(u"", NULL, 10) > 0);
|
||||
assert_se(strncasecmp16(NULL, NULL, 0) == 0);
|
||||
assert_se(strncasecmp16(NULL, NULL, 10) == 0);
|
||||
assert_se(strncasecmp16(u"", u"", 10) == 0);
|
||||
assert_se(strncasecmp16(u"abc", u"abc", 2) == 0);
|
||||
assert_se(strncasecmp16(u"aBc", u"AbC", 3) == 0);
|
||||
assert_se(strncasecmp16(u"aBC", u"Abc", 4) == 0);
|
||||
assert_se(strncasecmp16(u"", u"a", 0) == 0);
|
||||
assert_se(strncasecmp16(u"b", u"a", 0) == 0);
|
||||
assert_se(strncasecmp16(u"", u"a", 3) < 0);
|
||||
assert_se(strncasecmp16(u"=", u"=", 1) == 0);
|
||||
assert_se(strncasecmp16(u"A", u"a", 1) == 0);
|
||||
assert_se(strncasecmp16(u"a", u"A", 2) == 0);
|
||||
assert_se(strncasecmp16(u"a", u"Aa", 2) < 0);
|
||||
assert_se(strncasecmp16(u"12\00034", u"12345", 4) < 0);
|
||||
assert_se(strncasecmp16(u"12\00034", u"12345", SIZE_MAX) < 0);
|
||||
assert_se(strncasecmp16(u"abc\0def", u"ABC", SIZE_MAX) == 0);
|
||||
assert_se(strncasecmp16(u"abc\0def", u"ABCDEF", SIZE_MAX) < 0);
|
||||
|
||||
assert_se(strncasecmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ UINT16_MAX }, 1) == 0);
|
||||
assert_se(strncasecmp16((char16_t[]){ 0 }, (char16_t[]){ UINT16_MAX }, 1) < 0);
|
||||
assert_se(strncasecmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ 0 }, 1) > 0);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
Reference in New Issue
Block a user