Skip to content

Commit a1b10ad

Browse files
committed
Use C string to store strings in values
1 parent ed9e435 commit a1b10ad

File tree

3 files changed

+92
-49
lines changed

3 files changed

+92
-49
lines changed

include/scratchcpp/valuedata.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ extern "C"
3737
long intValue;
3838
double doubleValue;
3939
bool boolValue;
40-
std::string *stringValue;
40+
char *stringValue;
4141
};
4242

4343
ValueType type;
44+
size_t stringSize; // allocated size, not length
4445
};
4546
}
4647

src/scratch/value_functions.cpp

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ extern "C"
1616
{
1717
if (v->type == ValueType::String) {
1818
assert(v->stringValue);
19-
delete v->stringValue;
19+
free(v->stringValue);
2020
v->stringValue = nullptr;
21+
v->stringSize = 0;
2122
}
2223
}
2324

@@ -105,32 +106,29 @@ extern "C"
105106
/*! Assigns string to the given value. */
106107
void value_assign_string(ValueData *v, const std::string &stringValue)
107108
{
108-
if (stringValue == "Infinity") {
109+
value_assign_cstring(v, stringValue.c_str());
110+
}
111+
112+
/*! Assigns C string to the given value. */
113+
void value_assign_cstring(ValueData *v, const char *stringValue)
114+
{
115+
if (strcmp(stringValue, "Infinity") == 0) {
109116
value_free(v);
110117
v->type = ValueType::Infinity;
111-
} else if (stringValue == "-Infinity") {
118+
} else if (strcmp(stringValue, "-Infinity") == 0) {
112119
value_free(v);
113120
v->type = ValueType::NegativeInfinity;
114-
} else if (stringValue == "NaN") {
121+
} else if (strcmp(stringValue, "NaN") == 0) {
115122
value_free(v);
116123
v->type = ValueType::NaN;
124+
} else if (v->type == ValueType::String) {
125+
value_replaceStr(v, stringValue);
117126
} else {
118-
if (v->type == ValueType::String)
119-
v->stringValue->assign(stringValue);
120-
else {
121-
value_free(v);
122-
v->type = ValueType::String;
123-
v->stringValue = new std::string(stringValue);
124-
}
127+
value_free(v);
128+
value_initStr(v, stringValue);
125129
}
126130
}
127131

128-
/*! Assigns C string to the given value. */
129-
void value_assign_cstring(ValueData *v, const char *stringValue)
130-
{
131-
value_assign_string(v, std::string(stringValue));
132-
}
133-
134132
/*! Assigns special value to the given value. */
135133
void value_assign_special(ValueData *v, SpecialValue specialValue)
136134
{
@@ -162,10 +160,10 @@ extern "C"
162160
v->boolValue = another->boolValue;
163161
} else if (another->type == ValueType::String) {
164162
if (v->type == ValueType::String)
165-
v->stringValue->assign(*another->stringValue);
163+
value_replaceStr(v, another->stringValue);
166164
else {
167165
value_free(v);
168-
v->stringValue = new std::string(*another->stringValue);
166+
value_initStr(v, another->stringValue);
169167
}
170168
}
171169

@@ -185,7 +183,7 @@ extern "C"
185183
case ValueType::Double:
186184
return value_isInf(v->doubleValue);
187185
case ValueType::String:
188-
return *v->stringValue == "Infinity";
186+
return strcmp(v->stringValue, "Infinity") == 0;
189187
default:
190188
return false;
191189
}
@@ -202,7 +200,7 @@ extern "C"
202200
case ValueType::Double:
203201
return value_isNegativeInf(-v->doubleValue);
204202
case ValueType::String:
205-
return *v->stringValue == "-Infinity";
203+
return strcmp(v->stringValue, "-Infinity") == 0;
206204
default:
207205
return false;
208206
}
@@ -218,7 +216,7 @@ extern "C"
218216
assert(!std::isnan(v->doubleValue));
219217
return std::isnan(v->doubleValue);
220218
case ValueType::String:
221-
return *v->stringValue == "NaN";
219+
return strcmp(v->stringValue, "NaN") == 0;
222220
default:
223221
return false;
224222
}
@@ -247,7 +245,7 @@ extern "C"
247245
case ValueType::Bool:
248246
return true;
249247
case ValueType::String:
250-
return v->stringValue->empty() || value_checkString(*v->stringValue) > 0;
248+
return strlen(v->stringValue) == 0 || value_checkString(v->stringValue) > 0;
251249
default:
252250
return false;
253251
}
@@ -270,7 +268,7 @@ extern "C"
270268
return v->doubleValue == intpart;
271269
}
272270
case ValueType::String:
273-
return value_checkString(*v->stringValue) == 1;
271+
return value_checkString(v->stringValue) == 1;
274272
}
275273

276274
return false;
@@ -300,7 +298,7 @@ extern "C"
300298
else if (v->type == ValueType::Bool)
301299
return v->boolValue;
302300
else if (v->type == ValueType::String)
303-
return value_stringToLong(*v->stringValue);
301+
return value_stringToLong(v->stringValue);
304302
else
305303
return 0;
306304
}
@@ -315,7 +313,7 @@ extern "C"
315313
else if (v->type == ValueType::Bool)
316314
return v->boolValue;
317315
else if (v->type == ValueType::String)
318-
return value_stringToLong(*v->stringValue);
316+
return value_stringToLong(v->stringValue);
319317
else
320318
return 0;
321319
}
@@ -330,7 +328,7 @@ extern "C"
330328
else if (v->type == ValueType::Bool)
331329
return v->boolValue;
332330
else if (v->type == ValueType::String)
333-
return value_stringToDouble(*v->stringValue);
331+
return value_stringToDouble(v->stringValue);
334332
else if (v->type == ValueType::Infinity)
335333
return std::numeric_limits<double>::infinity();
336334
else if (v->type == ValueType::NegativeInfinity)
@@ -349,7 +347,7 @@ extern "C"
349347
} else if (v->type == ValueType::Double) {
350348
return v->doubleValue != 0;
351349
} else if (v->type == ValueType::String) {
352-
return !v->stringValue->empty() && !value_stringsEqual(*v->stringValue, "false") && *v->stringValue != "0";
350+
return strlen(v->stringValue) != 0 && !value_stringsEqual(v->stringValue, "false") && strcmp(v->stringValue, "0") != 0;
353351
} else if (v->type == ValueType::Infinity || v->type == ValueType::NegativeInfinity) {
354352
return true;
355353
} else if (v->type == ValueType::NaN) {
@@ -363,7 +361,7 @@ extern "C"
363361
void value_toString(const libscratchcpp::ValueData *v, std::string *dst)
364362
{
365363
if (v->type == ValueType::String)
366-
dst->assign(*v->stringValue);
364+
dst->assign(v->stringValue);
367365
else if (v->type == ValueType::Integer)
368366
dst->assign(std::to_string(v->intValue));
369367
else if (v->type == ValueType::Double)
@@ -590,12 +588,12 @@ extern "C"
590588
double n1, n2;
591589

592590
if (v1->type == ValueType::String)
593-
n1 = value_stringToDouble(*v1->stringValue);
591+
n1 = value_stringToDouble(v1->stringValue);
594592
else
595593
n1 = value_toDouble(v1);
596594

597595
if (v2->type == ValueType::String)
598-
n2 = value_stringToDouble(*v2->stringValue);
596+
n2 = value_stringToDouble(v2->stringValue);
599597
else
600598
n2 = value_toDouble(v2);
601599

@@ -628,12 +626,12 @@ extern "C"
628626
double n1, n2;
629627

630628
if (v1->type == ValueType::String)
631-
n1 = value_stringToDouble(*v1->stringValue);
629+
n1 = value_stringToDouble(v1->stringValue);
632630
else
633631
n1 = value_toDouble(v1);
634632

635633
if (v2->type == ValueType::String)
636-
n2 = value_stringToDouble(*v2->stringValue);
634+
n2 = value_stringToDouble(v2->stringValue);
637635
else
638636
n2 = value_toDouble(v2);
639637

src/scratch/value_functions_p.h

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,60 @@ inline bool value_isNegativeInf(T v)
5353
extern "C"
5454
{
5555

56+
inline size_t value_getSize(size_t x)
57+
{
58+
if (x == 0)
59+
return 0;
60+
61+
size_t ret = 1;
62+
63+
while (ret < x)
64+
ret *= 2;
65+
66+
return ret;
67+
}
68+
69+
inline void value_initStr(ValueData *v, const char *s)
70+
{
71+
const size_t len = strlen(s);
72+
v->stringSize = value_getSize(len + 1);
73+
v->type = ValueType::String;
74+
v->stringValue = (char *)malloc((v->stringSize * sizeof(char)));
75+
memcpy(v->stringValue, s, len);
76+
v->stringValue[len] = '\0';
77+
}
78+
79+
inline void value_replaceStr(ValueData *v, const char *s)
80+
{
81+
const size_t len = strlen(s);
82+
const size_t size = value_getSize(len + 1);
83+
84+
if (size == 0)
85+
return;
86+
87+
if (size > v->stringSize || v->stringSize / size > 3) {
88+
v->stringSize = size;
89+
v->stringValue = (char *)realloc(v->stringValue, v->stringSize * sizeof(char));
90+
}
91+
92+
memcpy(v->stringValue, s, len);
93+
v->stringValue[len] = '\0';
94+
}
95+
5696
inline bool value_u16StringsEqual(std::u16string s1, std::u16string s2)
5797
{
5898
std::transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
5999
std::transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
60100
return (s1.compare(s2) == 0);
61101
}
62102

63-
inline bool value_stringsEqual(std::string s1, std::string s2)
103+
inline bool value_stringsEqual(const char *s1, const char *s2)
64104
{
65-
std::transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
66-
std::transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
67-
return (s1.compare(s2) == 0);
105+
std::string str1(s1);
106+
std::string str2(s2);
107+
std::transform(str1.begin(), str1.end(), str1.begin(), ::tolower);
108+
std::transform(str2.begin(), str2.end(), str2.begin(), ::tolower);
109+
return (str1.compare(str2) == 0);
68110
}
69111

70112
inline double value_hexToDec(const char *s, int n, bool *ok)
@@ -150,20 +192,22 @@ extern "C"
150192
}
151193
}
152194

153-
inline double value_stringToDouble(const std::string &s, bool *ok = nullptr)
195+
inline double value_stringToDouble(const char *s, bool *ok = nullptr)
154196
{
155197
if (ok)
156198
*ok = false;
157199

158-
if (s.empty()) {
200+
const size_t len = strlen(s);
201+
202+
if (strlen(s) == 0) {
159203
if (ok)
160204
*ok = true;
161205

162206
return 0;
163207
}
164208

165-
const char *begin = s.data();
166-
const char *strEnd = s.data() + s.size();
209+
const char *begin = s;
210+
const char *strEnd = s + len;
167211
const char *end = strEnd;
168212

169213
// Trim leading spaces
@@ -286,15 +330,15 @@ extern "C"
286330
return 0;
287331

288332
// Special values
289-
if (s == "Infinity") {
333+
if (strcmp(s, "Infinity") == 0) {
290334
if (ok)
291335
*ok = true;
292336
return std::numeric_limits<double>::infinity();
293-
} else if (s == "-Infinity") {
337+
} else if (strcmp(s, "-Infinity") == 0) {
294338
if (ok)
295339
*ok = true;
296340
return -std::numeric_limits<double>::infinity();
297-
} else if (s == "NaN") {
341+
} else if (strcmp(s, "NaN") == 0) {
298342
if (ok)
299343
*ok = true;
300344
return std::numeric_limits<double>::quiet_NaN();
@@ -303,7 +347,7 @@ extern "C"
303347
return 0;
304348
}
305349

306-
inline long value_stringToLong(const std::string &s, bool *ok = nullptr)
350+
inline long value_stringToLong(const char *s, bool *ok = nullptr)
307351
{
308352
return value_stringToDouble(s, ok);
309353
}
@@ -364,11 +408,11 @@ extern "C"
364408
return std::round(v * f) / f;
365409
}
366410

367-
inline int value_checkString(const std::string &str)
411+
inline int value_checkString(const char *str)
368412
{
369413
bool ok;
370414

371-
if (value_stringIsInt(str.c_str(), str.size())) {
415+
if (value_stringIsInt(str, strlen(str))) {
372416
value_stringToLong(str, &ok);
373417
return ok ? 1 : 0;
374418
} else {
@@ -386,7 +430,7 @@ extern "C"
386430
// Since functions calling this already prioritize int, double and bool,
387431
// we can optimize by prioritizing the other types here.
388432
if (v->type == ValueType::String)
389-
return value_stringToDouble(*v->stringValue, ok);
433+
return value_stringToDouble(v->stringValue, ok);
390434
else if (v->type == ValueType::Infinity)
391435
return std::numeric_limits<double>::infinity();
392436
else if (v->type == ValueType::NegativeInfinity)

0 commit comments

Comments
 (0)