From b87f8e3f4797203ad1541707ad6445aadae92145 Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Tue, 11 Apr 2017 14:21:25 +0200 Subject: [PATCH] C4Script: Add ParseInt function ParseInt() will take a string parameter and try to convert it into an integer. If the conversion fails, it returns nil. --- docs/sdk/script/fn/ParseInt.xml | 30 +++++++++++++++++++++++++ src/lib/Standard.cpp | 9 +++++++- src/script/C4Script.cpp | 11 +++++++++ tests/aul/AulPredefinedFunctionTest.cpp | 19 ++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/sdk/script/fn/ParseInt.xml diff --git a/docs/sdk/script/fn/ParseInt.xml b/docs/sdk/script/fn/ParseInt.xml new file mode 100644 index 000000000..094ea17f2 --- /dev/null +++ b/docs/sdk/script/fn/ParseInt.xml @@ -0,0 +1,30 @@ + + + + + + ParseInt + Arithmetics + 8.0 OC + + int + + + string + value + Absolute coordinate you want to convert to a relative coordinate. + + + + Parses a string representing a base 10 number into an integer value. If the string does not entirely consist of a base 10 number, optionally signed, nil is returned. + + + ParseInt("14") + Returns the integer 14. + ParseInt("fourteen") + Returns nil. + + + + diff --git a/src/lib/Standard.cpp b/src/lib/Standard.cpp index 0acdaebcf..ac2357616 100644 --- a/src/lib/Standard.cpp +++ b/src/lib/Standard.cpp @@ -94,8 +94,9 @@ static int ToNumber(char c) //------------------------------- Strings ------------------------------------------------ -int32_t StrToI32(const char *s, int base, const char **scan_end) +int32_t StrToI32(const char *str, int base, const char **scan_end) { + const char *s = str; int sign = 1; int32_t result = 0; if (*s == '-') @@ -107,6 +108,12 @@ int32_t StrToI32(const char *s, int base, const char **scan_end) { s++; } + if (!*s) + { + // Abort if there are no digits to parse + if (scan_end) *scan_end = str; + return 0; + } while (IsNumber(*s,base)) { int value = ToNumber(*s++); diff --git a/src/script/C4Script.cpp b/src/script/C4Script.cpp index 042a9a4d0..26d3dddcd 100644 --- a/src/script/C4Script.cpp +++ b/src/script/C4Script.cpp @@ -617,6 +617,16 @@ static C4Value FnFormat(C4PropList * _this, C4Value * Pars) return C4VString(FnStringFormat(_this, Pars[0].getStr(), &Pars[1], 9)); } +// Parse a string into an integer. Returns nil if the conversion fails. +static Nillable FnParseInt(C4PropList *_this, C4String *str) +{ + const char *cstr = str->GetCStr(); + const char *end = nullptr; + int32_t result = StrToI32(cstr, 10, &end); + if (end == cstr || *end != '\0') return C4Void(); + return result; +} + static long FnAbs(C4PropList * _this, long iVal) { return Abs(iVal); @@ -1142,6 +1152,7 @@ void InitCoreFunctionMap(C4AulScriptEngine *pEngine) for (C4ScriptFnDef *pDef = &C4ScriptFnMap[0]; pDef->Identifier; pDef++) new C4AulDefFunc(p, pDef); #define F(f) ::AddFunc(p, #f, Fn##f) + F(ParseInt); F(Abs); F(Min); F(Max); diff --git a/tests/aul/AulPredefinedFunctionTest.cpp b/tests/aul/AulPredefinedFunctionTest.cpp index e62d84497..190347cee 100644 --- a/tests/aul/AulPredefinedFunctionTest.cpp +++ b/tests/aul/AulPredefinedFunctionTest.cpp @@ -147,6 +147,25 @@ TEST_F(AulPredefFunctionTest, CreateEffect) EXPECT_EQ(C4VInt(3), RunScript("local A = { Construction=func() { this.Magicnumber = 3; } }; func Main() { return CreateEffect(A, 1).Magicnumber; }")); } +TEST_F(AulPredefFunctionTest, ParseInt) +{ + auto ParseInt = [this](const std::string &value) { return RunExpr("ParseInt(\"" + value + "\")"); }; + EXPECT_EQ(C4VInt(0), ParseInt("0")); + EXPECT_EQ(C4VInt(0), ParseInt("-0")); + EXPECT_EQ(C4VInt(0), ParseInt("+0")); + EXPECT_EQ(C4VINT_MIN, ParseInt("-2147483648")); + EXPECT_EQ(C4VINT_MAX, ParseInt("2147483647")); + + EXPECT_EQ(C4VNull, ParseInt("")); + EXPECT_EQ(C4VNull, ParseInt("-")); + EXPECT_EQ(C4VNull, ParseInt("+")); + EXPECT_EQ(C4VNull, ParseInt("--23")); + EXPECT_EQ(C4VNull, ParseInt("-+1234")); + EXPECT_EQ(C4VNull, ParseInt("a")); + EXPECT_EQ(C4VNull, ParseInt("0a")); + EXPECT_EQ(C4VNull, ParseInt("2147483647a")); +} + TEST_F(AulPredefFunctionTest, Trivial) { EXPECT_EQ(C4VInt(100), RunExpr("Sin(900,100,10)"));