Skip to content

Commit 2d639b2

Browse files
committed
Optimize Value
* use std::variant to store the value * use long instead of uint32 * use double instead of float * add assignment operators * use fmod() for modulo to support doubles * replace toNumber() with toDouble(), toLong() and toInt() * use references
1 parent bf13e7f commit 2d639b2

File tree

6 files changed

+221
-123
lines changed

6 files changed

+221
-123
lines changed

src/blocks/controlblocks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Value ControlBlocks::repeat(const BlockArgs &args)
6464
} else
6565
return false;
6666
} else {
67-
int count = args.input(TIMES)->value().toNumber();
67+
int count = args.input(TIMES)->value().toInt();
6868
if (count > 0) {
6969
auto substack = script->getSubstack(args, SUBSTACK);
7070
if (substack) {

src/blocks/listblocks.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Value ListBlocks::deleteFromList(const BlockArgs &args)
5959
} else
6060
return Value();
6161
} else
62-
index = validateIndex(value.toNumber(), list->length());
62+
index = validateIndex(value.toInt(), list->length());
6363
if (index == 0)
6464
return Value();
6565
list->removeAt(index - 1);
@@ -88,7 +88,7 @@ Value ListBlocks::insertToList(const BlockArgs &args)
8888
} else
8989
return Value();
9090
} else {
91-
index = validateIndex(value.toNumber(), list->length());
91+
index = validateIndex(value.toInt(), list->length());
9292
if (index == 0)
9393
return Value();
9494
}
@@ -110,7 +110,7 @@ Value ListBlocks::replaceItemOfList(const BlockArgs &args)
110110
} else
111111
return Value();
112112
} else
113-
index = validateIndex(value.toNumber(), list->length());
113+
index = validateIndex(value.toInt(), list->length());
114114
if (index == 0)
115115
return Value();
116116
list->replace(index - 1, args.input(ITEM)->value());
@@ -131,7 +131,7 @@ Value ListBlocks::itemOfList(const BlockArgs &args)
131131
} else
132132
return "";
133133
} else
134-
index = validateIndex(value.toNumber(), list->length());
134+
index = validateIndex(value.toInt(), list->length());
135135
if (index == 0)
136136
return "";
137137
return list->at(index - 1);

src/blocks/operatorblocks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Value OperatorBlocks::divide(const BlockArgs &args)
5656

5757
Value OperatorBlocks::pickRandom(const BlockArgs &args)
5858
{
59-
return randint(args.input(FROM)->value().toNumber(), args.input(TO)->value().toNumber());
59+
return randint(args.input(FROM)->value().toDouble(), args.input(TO)->value().toDouble());
6060
}
6161

6262
Value OperatorBlocks::lessThan(const BlockArgs &args)

src/blocks/variableblocks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ Value VariableBlocks::setVariable(const BlockArgs &args)
3232
Value VariableBlocks::changeVariableBy(const BlockArgs &args)
3333
{
3434
auto variable = std::static_pointer_cast<Variable>(args.field(VARIABLE)->valuePtr());
35-
variable->setValue(variable->value().toNumber() + args.input(VALUE)->value().toNumber());
35+
variable->setValue(variable->value() + args.input(VALUE)->value());
3636
return Value();
3737
}

src/scratch/value.cpp

Lines changed: 117 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,64 +9,64 @@ using namespace libscratchcpp;
99

1010
/*! Constructs a number Value. */
1111
Value::Value(float numberValue) :
12-
m_numberValue(numberValue),
12+
m_value(numberValue),
1313
m_type(Type::Number)
1414
{
1515
}
1616

1717
/*! Constructs a number Value. */
1818
Value::Value(double numberValue) :
19-
m_numberValue(numberValue),
19+
m_value(numberValue),
2020
m_type(Type::Number)
2121
{
2222
}
2323

2424
/*! Constructs a number Value. */
2525
Value::Value(int numberValue) :
26-
m_numberValue(numberValue),
26+
m_value(numberValue),
2727
m_type(Type::Number)
2828
{
2929
}
3030

3131
/*! Constructs a number Value. */
32-
Value::Value(uint32_t numberValue) :
33-
m_numberValue(numberValue),
32+
Value::Value(long numberValue) :
33+
m_value(numberValue),
3434
m_type(Type::Number)
3535
{
3636
}
3737

3838
/*! Constructs a boolean Value. */
3939
Value::Value(bool boolValue) :
40-
m_boolValue(boolValue),
40+
m_value(boolValue),
4141
m_type(Type::Bool)
4242
{
4343
}
4444

4545
/*! Constructs a string Value. */
46-
Value::Value(std::string stringValue) :
47-
m_stringValue(stringValue),
46+
Value::Value(const std::string &stringValue) :
47+
m_value(stringValue),
4848
m_type(Type::String)
4949
{
50-
if (m_stringValue.empty())
50+
if (stringValue.empty())
5151
return;
52-
else if (m_stringValue == "Infinity") {
52+
else if (stringValue == "Infinity") {
5353
m_isInfinity = true;
5454
m_type = Type::Special;
5555
return;
56-
} else if (m_stringValue == "-Infinity") {
56+
} else if (stringValue == "-Infinity") {
5757
m_isNegativeInfinity = true;
5858
m_type = Type::Special;
5959
return;
60-
} else if (m_stringValue == "NaN") {
60+
} else if (stringValue == "NaN") {
6161
m_isNaN = true;
6262
m_type = Type::Special;
6363
return;
6464
}
6565

6666
bool ok;
67-
float f = stringToFloat(m_stringValue, &ok);
67+
float f = stringToDouble(stringValue, &ok);
6868
if (ok) {
69-
m_numberValue = f;
69+
m_value = f;
7070
m_type = Type::Number;
7171
}
7272
}
@@ -89,7 +89,7 @@ Value::Value(SpecialValue specialValue) :
8989
m_isNaN = true;
9090
else {
9191
m_type = Type::Number;
92-
m_numberValue = 0;
92+
m_value = 0;
9393
}
9494
}
9595

@@ -135,70 +135,88 @@ bool Value::isString() const
135135
return m_type == Type::String;
136136
}
137137

138-
/*! Returns the number representation of the value. */
139-
float Value::toNumber() const
138+
/*! Returns the int representation of the value. */
139+
int Value::toInt() const
140140
{
141-
switch (m_type) {
142-
case Type::Number:
143-
return m_numberValue;
144-
case Type::Bool:
145-
return m_boolValue;
146-
case Type::String:
147-
return stringToFloat(m_stringValue);
148-
case Type::Special:
149-
if (m_isInfinity)
150-
return std::numeric_limits<float>::infinity();
151-
else if (m_isNegativeInfinity)
152-
return -std::numeric_limits<float>::infinity();
153-
else
154-
return 0;
155-
}
156-
return 0;
141+
return toLong();
142+
}
143+
144+
/*! Returns the long representation of the value. */
145+
inline long Value::toLong() const
146+
{
147+
if (std::holds_alternative<long>(m_value))
148+
return std::get<long>(m_value);
149+
else if (std::holds_alternative<double>(m_value))
150+
return std::get<double>(m_value);
151+
else if (std::holds_alternative<bool>(m_value))
152+
return std::get<bool>(m_value);
153+
else if (std::holds_alternative<std::string>(m_value))
154+
return stringToLong(std::get<std::string>(m_value));
155+
else if (m_isInfinity)
156+
return std::numeric_limits<long>::infinity();
157+
else if (m_isNegativeInfinity)
158+
return -std::numeric_limits<long>::infinity();
159+
else
160+
return 0;
161+
}
162+
163+
/*! Returns the double representation of the value. */
164+
double Value::toDouble() const
165+
{
166+
if (std::holds_alternative<double>(m_value))
167+
return std::get<double>(m_value);
168+
else if (std::holds_alternative<long>(m_value))
169+
return std::get<long>(m_value);
170+
else if (std::holds_alternative<bool>(m_value))
171+
return std::get<bool>(m_value);
172+
else if (std::holds_alternative<std::string>(m_value))
173+
return stringToDouble(std::get<std::string>(m_value));
174+
else if (m_isInfinity)
175+
return std::numeric_limits<double>::infinity();
176+
else if (m_isNegativeInfinity)
177+
return -std::numeric_limits<double>::infinity();
178+
else
179+
return 0;
157180
}
158181

159182
/*! Returns the boolean representation of the value. */
160183
bool Value::toBool() const
161184
{
162-
switch (m_type) {
163-
case Type::Number:
164-
return m_numberValue == 1 ? true : false;
165-
case Type::Bool:
166-
return m_boolValue;
167-
case Type::String: {
168-
std::string str = m_stringValue;
169-
return (stringsEqual(str, "true") || str == "1");
170-
}
171-
case Type::Special:
172-
return false;
173-
}
174-
return false;
185+
if (std::holds_alternative<bool>(m_value))
186+
return std::get<bool>(m_value);
187+
else if (std::holds_alternative<long>(m_value))
188+
return std::get<long>(m_value) == 1 ? true : false;
189+
else if (std::holds_alternative<double>(m_value))
190+
return std::get<double>(m_value) == 1 ? true : false;
191+
else if (std::holds_alternative<std::string>(m_value)) {
192+
const std::string &str = std::get<std::string>(m_value);
193+
return (stringsEqual(str, "true") || str == "1");
194+
} else
195+
return false;
175196
}
176197

177198
/*! Returns the string representation of the value. */
178199
std::string Value::toString() const
179200
{
180-
switch (m_type) {
181-
case Type::Number: {
182-
std::string s = std::to_string(m_numberValue);
183-
s.erase(s.find_last_not_of('0') + 1, std::string::npos);
184-
if (s.back() == '.') {
185-
s.pop_back();
186-
}
187-
return s;
201+
if (std::holds_alternative<std::string>(m_value))
202+
return std::get<std::string>(m_value);
203+
else if (std::holds_alternative<long>(m_value))
204+
return std::to_string(std::get<long>(m_value));
205+
else if (std::holds_alternative<double>(m_value)) {
206+
std::string s = std::to_string(std::get<double>(m_value));
207+
s.erase(s.find_last_not_of('0') + 1, std::string::npos);
208+
if (s.back() == '.') {
209+
s.pop_back();
188210
}
189-
case Type::Bool:
190-
return m_boolValue ? "true" : "false";
191-
case Type::String:
192-
return m_stringValue;
193-
case Type::Special:
194-
if (m_isInfinity)
195-
return "Infinity";
196-
else if (m_isNegativeInfinity)
197-
return "-Infinity";
198-
else
199-
return "NaN";
200-
}
201-
return "";
211+
return s;
212+
} else if (std::holds_alternative<bool>(m_value))
213+
return std::get<bool>(m_value) ? "true" : "false";
214+
else if (m_isInfinity)
215+
return "Infinity";
216+
else if (m_isNegativeInfinity)
217+
return "-Infinity";
218+
else
219+
return "NaN";
202220
}
203221

204222
/*! Returns the UTF-16 representation of the value. */
@@ -221,26 +239,26 @@ bool Value::stringsEqual(std::string s1, std::string s2)
221239
return (s1.compare(s2) == 0);
222240
}
223241

224-
float Value::stringToFloat(std::string s, bool *ok)
242+
double Value::stringToDouble(const std::string &s, bool *ok)
225243
{
226244
if (ok)
227245
*ok = false;
228246

229247
if (s == "Infinity") {
230248
if (ok)
231249
*ok = true;
232-
return std::numeric_limits<float>::infinity();
250+
return std::numeric_limits<double>::infinity();
233251
} else if (s == "-Infinity") {
234252
if (ok)
235253
*ok = true;
236-
return -std::numeric_limits<float>::infinity();
254+
return -std::numeric_limits<double>::infinity();
237255
} else if (s == "NaN") {
238256
if (ok)
239257
*ok = true;
240258
return 0;
241259
}
242260

243-
std::string digits = "0123456789.eE+-";
261+
static const std::string digits = "0123456789.eE+-";
244262
for (char c : s) {
245263
if (digits.find(c) == std::string::npos) {
246264
return 0;
@@ -254,3 +272,31 @@ float Value::stringToFloat(std::string s, bool *ok)
254272
return 0;
255273
}
256274
}
275+
276+
long Value::stringToLong(const std::string &s, bool *ok)
277+
{
278+
if (ok)
279+
*ok = false;
280+
281+
if (s == "Infinity") {
282+
if (ok)
283+
*ok = true;
284+
return std::numeric_limits<long>::infinity();
285+
} else if (s == "-Infinity") {
286+
if (ok)
287+
*ok = true;
288+
return -std::numeric_limits<long>::infinity();
289+
} else if (s == "NaN") {
290+
if (ok)
291+
*ok = true;
292+
return 0;
293+
}
294+
295+
try {
296+
if (ok)
297+
*ok = true;
298+
return std::stol(s);
299+
} catch (...) {
300+
return 0;
301+
}
302+
}

0 commit comments

Comments
 (0)