Skip to content

Commit ff1bcf1

Browse files
committed
Add string comparison functions
1 parent 6a3c567 commit ff1bcf1

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed

include/scratchcpp/string_functions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ struct StringPtr;
1414
extern "C"
1515
{
1616
LIBSCRATCHCPP_EXPORT void string_alloc(StringPtr *str, size_t size);
17+
1718
LIBSCRATCHCPP_EXPORT void string_assign(StringPtr *str, const StringPtr *another);
1819
LIBSCRATCHCPP_EXPORT void string_assign_cstring(StringPtr *str, const char *another);
20+
21+
LIBSCRATCHCPP_EXPORT int string_compare_case_sensitive(StringPtr *str1, StringPtr *str2);
22+
LIBSCRATCHCPP_EXPORT int string_compare_case_insensitive(StringPtr *str1, StringPtr *str2);
1923
}
2024

2125
} // namespace libscratchcpp

src/scratch/string_functions.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <cstring>
77
#include <cassert>
88
#include <utf8.h>
9+
#include <unicodelib.h>
10+
#include <unicodelib_encodings.h>
911

1012
namespace libscratchcpp
1113
{
@@ -56,6 +58,44 @@ extern "C"
5658
str->size = converted.size();
5759
memcpy(str->data, converted.data(), (converted.size() + 1) * sizeof(typeof(*str->data)));
5860
}
61+
62+
int string_compare_case_sensitive(StringPtr *str1, StringPtr *str2)
63+
{
64+
if (str1->size != str2->size)
65+
return str1->size < str2->size ? -1 : 1;
66+
67+
const size_t min_len = std::min(str1->size, str2->size);
68+
69+
for (size_t i = 0; i < min_len; i++) {
70+
if (str1->data[i] != str2->data[i])
71+
return str1->data[i] - str2->data[i];
72+
}
73+
74+
return 0;
75+
}
76+
77+
int string_compare_case_insensitive(StringPtr *str1, StringPtr *str2)
78+
{
79+
if (str1->size != str2->size)
80+
return str1->size < str2->size ? -1 : 1;
81+
82+
const size_t min_len = std::min(str1->size, str2->size);
83+
std::u32string cp1_str, cp2_str;
84+
char32_t cp1, cp2;
85+
86+
for (size_t i = 0; i < min_len; ++i) {
87+
unicode::utf16::decode(str1->data + i, 1, cp1_str);
88+
unicode::utf16::decode(str2->data + i, 1, cp2_str);
89+
90+
cp1 = unicode::simple_lowercase_mapping(cp1_str.front());
91+
cp2 = unicode::simple_lowercase_mapping(cp2_str.front());
92+
93+
if (cp1 != cp2)
94+
return cp1 - cp2;
95+
}
96+
97+
return 0;
98+
}
5999
}
60100

61101
} // namespace libscratchcpp

test/scratch_classes/string_functions_test.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,133 @@ TEST(StringFunctionsTest, AssignAlloc)
8989
ASSERT_TRUE(str1.data);
9090
ASSERT_EQ(str1.data[0], u'\0');
9191
}
92+
93+
TEST(StringFunctionsTest, CompareCaseSensitive)
94+
{
95+
StringPtr str1, str2;
96+
97+
string_assign_cstring(&str1, "abcd");
98+
string_assign_cstring(&str2, "abcd");
99+
ASSERT_EQ(string_compare_case_sensitive(&str1, &str2), 0);
100+
101+
string_assign_cstring(&str1, "aBcd");
102+
string_assign_cstring(&str2, "abCd");
103+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
104+
105+
string_assign_cstring(&str1, "Hello");
106+
string_assign_cstring(&str2, "olleH");
107+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
108+
109+
string_assign_cstring(&str1, "olleH");
110+
string_assign_cstring(&str2, "Hello");
111+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
112+
113+
string_assign_cstring(&str1, "AbCdEfGh");
114+
string_assign_cstring(&str2, "EfGhIjKl");
115+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
116+
117+
string_assign_cstring(&str1, "EfGhIjKl");
118+
string_assign_cstring(&str2, "AbCdEfGh");
119+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
120+
121+
string_assign_cstring(&str1, "Lorem ipsum");
122+
string_assign_cstring(&str2, "dolor sit amet");
123+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
124+
125+
string_assign_cstring(&str1, "dolor sit amet");
126+
string_assign_cstring(&str2, "Lorem ipsum");
127+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
128+
129+
string_assign_cstring(&str1, "Hello");
130+
string_assign_cstring(&str2, "Hello world");
131+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
132+
133+
string_assign_cstring(&str1, "Hello world");
134+
string_assign_cstring(&str2, "Hello");
135+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
136+
137+
string_assign_cstring(&str1, "Hello");
138+
string_assign_cstring(&str2, "Hello world");
139+
ASSERT_LT(string_compare_case_sensitive(&str1, &str2), 0);
140+
141+
string_assign_cstring(&str1, "ábčď");
142+
string_assign_cstring(&str2, "ábčď");
143+
ASSERT_EQ(string_compare_case_sensitive(&str1, &str2), 0);
144+
145+
string_assign_cstring(&str1, "ábčď");
146+
string_assign_cstring(&str2, "ábČď");
147+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
148+
149+
string_assign_cstring(&str1, "test đ");
150+
string_assign_cstring(&str2, "test Đ");
151+
ASSERT_GT(string_compare_case_sensitive(&str1, &str2), 0);
152+
153+
string_assign_cstring(&str1, "💀");
154+
string_assign_cstring(&str2, "💀");
155+
ASSERT_EQ(string_compare_case_sensitive(&str1, &str2), 0);
156+
}
157+
158+
TEST(StringFunctionsTest, CompareCaseInsensitive)
159+
{
160+
StringPtr str1, str2;
161+
162+
string_assign_cstring(&str1, "abcd");
163+
string_assign_cstring(&str2, "abcd");
164+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
165+
166+
string_assign_cstring(&str1, "aBcd");
167+
string_assign_cstring(&str2, "abCd");
168+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
169+
170+
string_assign_cstring(&str1, "Hello");
171+
string_assign_cstring(&str2, "olleH");
172+
ASSERT_LT(string_compare_case_insensitive(&str1, &str2), 0);
173+
174+
string_assign_cstring(&str1, "olleH");
175+
string_assign_cstring(&str2, "Hello");
176+
ASSERT_GT(string_compare_case_insensitive(&str1, &str2), 0);
177+
178+
string_assign_cstring(&str1, "AbCdEfGh");
179+
string_assign_cstring(&str2, "EfGhIjKl");
180+
ASSERT_LT(string_compare_case_insensitive(&str1, &str2), 0);
181+
182+
string_assign_cstring(&str1, "EfGhIjKl");
183+
string_assign_cstring(&str2, "AbCdEfGh");
184+
ASSERT_GT(string_compare_case_insensitive(&str1, &str2), 0);
185+
186+
string_assign_cstring(&str1, "Lorem ipsum");
187+
string_assign_cstring(&str2, "dolor sit amet");
188+
ASSERT_LT(string_compare_case_insensitive(&str1, &str2), 0);
189+
190+
string_assign_cstring(&str1, "dolor sit amet");
191+
string_assign_cstring(&str2, "Lorem ipsum");
192+
ASSERT_GT(string_compare_case_insensitive(&str1, &str2), 0);
193+
194+
string_assign_cstring(&str1, "Hello");
195+
string_assign_cstring(&str2, "Hello world");
196+
ASSERT_LT(string_compare_case_insensitive(&str1, &str2), 0);
197+
198+
string_assign_cstring(&str1, "Hello world");
199+
string_assign_cstring(&str2, "Hello");
200+
ASSERT_GT(string_compare_case_insensitive(&str1, &str2), 0);
201+
202+
string_assign_cstring(&str1, "Hello");
203+
string_assign_cstring(&str2, "Hello world");
204+
ASSERT_LT(string_compare_case_insensitive(&str1, &str2), 0);
205+
206+
string_assign_cstring(&str1, "ábčď");
207+
string_assign_cstring(&str2, "ábčď");
208+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
209+
210+
string_assign_cstring(&str1, "ábčď");
211+
string_assign_cstring(&str2, "ábČď");
212+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
213+
214+
string_assign_cstring(&str1, "test đ");
215+
string_assign_cstring(&str2, "test Đ");
216+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
217+
218+
string_assign_cstring(&str1, "💀");
219+
string_assign_cstring(&str2, "💀");
220+
ASSERT_EQ(string_compare_case_insensitive(&str1, &str2), 0);
221+
}

0 commit comments

Comments
 (0)