Skip to content

Commit ca91ea8

Browse files
committed
Add string functions
1 parent 68e97cd commit ca91ea8

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ target_sources(scratchcpp
3939
include/scratchcpp/valuedata.h
4040
include/scratchcpp/value_functions.h
4141
include/scratchcpp/stringptr.h
42+
include/scratchcpp/string_functions.h
4243
include/scratchcpp/entity.h
4344
include/scratchcpp/variable.h
4445
include/scratchcpp/list.h
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#pragma once
4+
5+
#include <cstddef>
6+
7+
#include "global.h"
8+
9+
namespace libscratchcpp
10+
{
11+
12+
struct StringPtr;
13+
14+
extern "C"
15+
{
16+
LIBSCRATCHCPP_EXPORT void string_alloc(StringPtr *str, size_t size);
17+
LIBSCRATCHCPP_EXPORT void string_assign(StringPtr *str, const StringPtr *another);
18+
LIBSCRATCHCPP_EXPORT void string_assign_cstring(StringPtr *str, const char *another);
19+
}
20+
21+
} // namespace libscratchcpp

src/scratch/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ target_sources(scratchcpp
22
PRIVATE
33
value_functions.cpp
44
value_functions_p.h
5+
string_functions.cpp
56
drawable.cpp
67
drawable_p.cpp
78
drawable_p.h

src/scratch/string_functions.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#include <scratchcpp/string_functions.h>
4+
#include <scratchcpp/stringptr.h>
5+
#include <cmath>
6+
#include <cstring>
7+
#include <cassert>
8+
#include <utf8.h>
9+
10+
namespace libscratchcpp
11+
{
12+
13+
extern "C"
14+
{
15+
16+
/*! Ensures at least the given size is allocated on str. */
17+
void string_alloc(StringPtr *str, size_t size)
18+
{
19+
size++; // null terminator
20+
21+
if (str->allocatedSize < size) {
22+
// TODO: Use std::bit_ceil() in C++20
23+
const size_t newSize = std::pow(2, std::ceil(std::log2(size)));
24+
assert((str->data && str->allocatedSize > 0) || (!str->data && str->allocatedSize == 0));
25+
26+
if (str->data)
27+
str->data = (typeof(str->data))realloc(str->data, newSize * sizeof(typeof(*str->data)));
28+
else
29+
str->data = (typeof(str->data))malloc(newSize * sizeof(typeof(*str->data)));
30+
31+
str->allocatedSize = newSize;
32+
}
33+
}
34+
35+
/*! Assigns the given string to str. */
36+
void string_assign(StringPtr *str, const StringPtr *another)
37+
{
38+
if (another->size == 0) {
39+
str->size = 0;
40+
return;
41+
}
42+
43+
string_alloc(str, another->size);
44+
str->size = another->size;
45+
memcpy(str->data, another->data, (another->size + 1) * sizeof(typeof(*str->data)));
46+
}
47+
48+
/*! Assigns the given string to str. */
49+
void string_assign_cstring(StringPtr *str, const char *another)
50+
{
51+
if (!another) {
52+
str->size = 0;
53+
string_alloc(str, 0);
54+
str->data[0] = u'\0';
55+
return;
56+
}
57+
58+
// TODO: Use a library to map characters
59+
std::u16string converted = utf8::utf8to16(std::string(another));
60+
string_alloc(str, converted.size());
61+
str->size = converted.size();
62+
memcpy(str->data, converted.data(), (converted.size() + 1) * sizeof(typeof(*str->data)));
63+
}
64+
}
65+
66+
} // namespace libscratchcpp

test/scratch_classes/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ target_link_libraries(
121121

122122
gtest_discover_tests(value_test)
123123

124+
# string_functions_test
125+
add_executable(
126+
string_functions_test
127+
string_functions_test.cpp
128+
)
129+
130+
target_link_libraries(
131+
string_functions_test
132+
GTest::gtest_main
133+
scratchcpp
134+
)
135+
136+
gtest_discover_tests(string_functions_test)
137+
124138
# entity_test
125139
add_executable(
126140
entity_test
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <scratchcpp/string_functions.h>
2+
#include <scratchcpp/stringptr.h>
3+
4+
#include "../common.h"
5+
6+
using namespace libscratchcpp;
7+
8+
TEST(StringFunctionsTest, AssignAlloc)
9+
{
10+
StringPtr str1;
11+
ASSERT_FALSE(str1.data);
12+
ASSERT_EQ(str1.size, 0);
13+
ASSERT_EQ(str1.allocatedSize, 0);
14+
15+
string_assign_cstring(&str1, "test");
16+
ASSERT_EQ(str1.size, 4);
17+
ASSERT_GE(str1.allocatedSize, 5);
18+
ASSERT_TRUE(str1.data);
19+
ASSERT_EQ(str1.data[0], u't');
20+
ASSERT_EQ(str1.data[1], u'e');
21+
ASSERT_EQ(str1.data[2], u's');
22+
ASSERT_EQ(str1.data[3], u't');
23+
ASSERT_EQ(str1.data[4], u'\0');
24+
25+
string_assign_cstring(&str1, "Hello world");
26+
ASSERT_EQ(str1.size, 11);
27+
ASSERT_GE(str1.allocatedSize, 12);
28+
ASSERT_TRUE(str1.data);
29+
ASSERT_EQ(str1.data[0], u'H');
30+
ASSERT_EQ(str1.data[1], u'e');
31+
ASSERT_EQ(str1.data[2], u'l');
32+
ASSERT_EQ(str1.data[3], u'l');
33+
ASSERT_EQ(str1.data[4], u'o');
34+
ASSERT_EQ(str1.data[5], u' ');
35+
ASSERT_EQ(str1.data[6], u'w');
36+
ASSERT_EQ(str1.data[7], u'o');
37+
ASSERT_EQ(str1.data[8], u'r');
38+
ASSERT_EQ(str1.data[9], u'l');
39+
ASSERT_EQ(str1.data[10], u'd');
40+
ASSERT_EQ(str1.data[11], u'\0');
41+
42+
StringPtr str2;
43+
string_alloc(&str2, 8);
44+
ASSERT_GE(str2.allocatedSize, 9);
45+
ASSERT_TRUE(str2.data);
46+
str2.data[0] = u'a';
47+
str2.data[1] = u'b';
48+
str2.data[2] = u'c';
49+
str2.data[3] = u'd';
50+
str2.data[4] = u'e';
51+
str2.data[5] = u'f';
52+
str2.data[6] = u'g';
53+
str2.data[7] = u'h';
54+
str2.data[8] = u'\0';
55+
str2.size = 8;
56+
ASSERT_EQ(str2.data[0], u'a');
57+
ASSERT_EQ(str2.data[1], u'b');
58+
ASSERT_EQ(str2.data[2], u'c');
59+
ASSERT_EQ(str2.data[3], u'd');
60+
ASSERT_EQ(str2.data[4], u'e');
61+
ASSERT_EQ(str2.data[5], u'f');
62+
ASSERT_EQ(str2.data[6], u'g');
63+
ASSERT_EQ(str2.data[7], u'h');
64+
ASSERT_EQ(str2.data[8], u'\0');
65+
66+
string_assign(&str1, &str2);
67+
ASSERT_EQ(str2.size, str1.size);
68+
ASSERT_GE(str2.allocatedSize, str1.size + 1);
69+
ASSERT_TRUE(str2.data);
70+
ASSERT_NE(str2.data, str1.data);
71+
ASSERT_EQ(memcmp(str2.data, str1.data, (str2.size + 1) * sizeof(typeof(*str2.data))), 0);
72+
}

0 commit comments

Comments
 (0)