summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-10-18 00:56:14 +0000
committerandreas <andreas@daaaf23c-2e50-4459-9457-1e69db5a47bf>2014-10-18 00:56:14 +0000
commit25fb41044ca080b794cbf4e85ff10e74e571ea24 (patch)
tree59c5d648d32a2655778cefc26532c72efea963ea
parent14982ab94391bf9ec0b2ddba7f4517a0c834d0b1 (diff)
improved Variant.cpp, added ScriptEngine.hpp containing the script engine abstraction layer
git-svn-id: file:///var/local/svn/basicwriter@72 daaaf23c-2e50-4459-9457-1e69db5a47bf
-rw-r--r--CMakeLists.txt19
-rw-r--r--src/core/script/ScriptEngine.cpp65
-rw-r--r--src/core/script/ScriptEngine.hpp233
-rw-r--r--src/core/script/Variant.cpp11
-rw-r--r--src/core/script/Variant.hpp199
-rw-r--r--src/core/utils/Utils.cpp39
-rw-r--r--src/core/utils/Utils.hpp65
-rw-r--r--test/core/script/Variant.cpp15
-rw-r--r--test/core/utils/Utils.cpp35
9 files changed, 565 insertions, 116 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8fb3ac9..94bbcbd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,20 +51,27 @@ INCLUDE_DIRECTORIES(
src/
)
+# ousia_utils library
+ADD_LIBRARY(ousia_utils
+ src/core/utils/Utils.cpp
+)
+
# ousia_script library (containing the code of t
ADD_LIBRARY(ousia_script
src/core/script/Variant.cpp
+ src/core/script/ScriptEngine.cpp
+ src/core/script/
+)
+
+# Link the ousia executable against ousia_core
+TARGET_LINK_LIBRARIES(ousia_script
+ ousia_utils
)
# Definition of the main program
#ADD_EXECUTABLE(ousia
#)
-# Link the ousia executable against ousia_core
-#TARGET_LINK_LIBRARIES(ousia
-# ousia_script
-#)
-
# If testing is enabled, build the unit tests
IF(test)
# Include the gtest include files and the src directory
@@ -76,11 +83,13 @@ IF(test)
# Add all unit test files
ADD_EXECUTABLE(ousia_test
test/core/model/RangeSet
+ test/core/utils/Utils
test/core/script/Variant
)
TARGET_LINK_LIBRARIES(ousia_test
${GTEST_LIBRARIES}
+ ousia_utils
ousia_script
)
diff --git a/src/core/script/ScriptEngine.cpp b/src/core/script/ScriptEngine.cpp
new file mode 100644
index 0000000..f34ccea
--- /dev/null
+++ b/src/core/script/ScriptEngine.cpp
@@ -0,0 +1,65 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sstream>
+
+#include "ScriptEngine.hpp"
+
+namespace ousia {
+namespace script {
+
+ScriptEngineException::ScriptEngineException(int line, int col,
+ const std::string &msg) :
+ line(line), col(col),
+ msg(std::to_string(line) + ":" + std::to_string(col) + " " + msg) {}
+
+ScriptEngineException::ScriptEngineException(const std::string &msg) :
+ line(-1), col(-1), msg(msg) {}
+
+const char* ScriptEngineException::what() const noexcept
+{
+ return msg.c_str();
+}
+
+void ScriptEngineFactory::registerScriptEngine(const std::string &name,
+ ScriptEngine *engine)
+{
+ registry[name] = engine;
+}
+
+bool ScriptEngineFactory::unregisterScriptEngine(const std::string &name)
+{
+ return registry.erase(name) > 0;
+}
+
+/* Class ScriptEngineFactory */
+
+ScriptEngineScope* ScriptEngineFactory::createScope(
+ const std::string &name) const
+{
+ auto it = registry.find(name);
+ if (it != registry.end()) {
+ return it->second->createScope();
+ }
+ return nullptr;
+}
+
+
+}
+}
+
diff --git a/src/core/script/ScriptEngine.hpp b/src/core/script/ScriptEngine.hpp
new file mode 100644
index 0000000..3a53791
--- /dev/null
+++ b/src/core/script/ScriptEngine.hpp
@@ -0,0 +1,233 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _OUSIA_SCRIPT_ENGINE_HPP_
+#define _OUSIA_SCRIPT_ENGINE_HPP_
+
+#include <map>
+#include <string>
+#include <exception>
+
+#include <core/utils/Utils.hpp>
+
+#include "Variant.hpp"
+
+namespace ousia {
+namespace script {
+
+/**
+ * Class used for signaling errors while executing code or registering variables
+ * in the script engine.
+ */
+class ScriptEngineException : public std::exception {
+
+public:
+ /**
+ * Line and column at which the exception occured. Set to -1 if the error
+ * does not correspond to a line or column.
+ */
+ const int line, col;
+
+ /**
+ * Error message.
+ */
+ const std::string msg;
+
+ /**
+ * ScriptEngineException constructor.
+ *
+ * @param line in the script code at which the exception occured.
+ * @param col in the script code at which the exception occured.
+ * @param msg is the message containing the reason for the exception.
+ */
+ ScriptEngineException(int line, int col, const std::string &msg);
+
+ /**
+ * ScriptEngineException constructor.
+ *
+ * @param msg is the message containing the reason for the exception.
+ */
+ ScriptEngineException(const std::string &msg);
+
+ /**
+ * Returns the error message.
+ */
+ virtual const char* what() const noexcept;
+
+};
+
+/**
+ * The ScriptEngineScope class represents an execution scope -- an execution
+ * scope is the base class
+ */
+class ScriptEngineScope {
+
+private:
+
+ /**
+ * Helper used to check the given identifiers for their validity.
+ *
+ * @param name is the name of the identifier that should be checked.
+ * @throws ScriptEngineException if the given identifier is invalid.
+ */
+ static void checkIdentifier(const std::string &name)
+ {
+ if (!Utils::isIdentifier(name)) {
+ throw ScriptEngineException{"Invalid identifier \"" + name + "\""};
+ }
+ }
+
+protected:
+
+ /**
+ * Implementation of the @see run function.
+ */
+ virtual Variant doRun(const std::string &code) = 0;
+
+ /**
+ * Implementation of the @see setVariable function.
+ */
+ virtual void doSetVariable(const std::string &name, const Variant &val,
+ bool constant) = 0;
+
+ /**
+ * Implementation of the @see getVariable function.
+ */
+ virtual Variant doGetVariable(const std::string &name) = 0;
+
+public:
+
+ /**
+ * Virtual destructor. Must be overwritten by implementing classes.
+ */
+ virtual ~ScriptEngineScope() {};
+
+ /**
+ * Runs the given code in the excution context.
+ *
+ * @param code is a string containing the code the script engine should run.
+ * @return a variant containg the result of the executed code.
+ * @throws ScriptEngineException if an error occured during code execution.
+ */
+ Variant run(const std::string &code)
+ {
+ return doRun(code);
+ }
+
+ /**
+ * Sets the value of a variable in the scope with the given name.
+ *
+ * @param name is the name of the variable in the scope. Must be a
+ * well-formed identifier.
+ * @param val is the value of the variable.
+ * @param constant if true, the value of the variable cannot be changed by
+ * the script code.
+ * @throws ScriptEngineException if name is not a well-formed identifier.
+ */
+ void setVariable(const std::string &name, const Variant &val,
+ bool constant = false)
+ {
+ checkIdentifier(name);
+ doSetVariable(name, val, constant);
+ }
+
+ /**
+ * Reads the value of the variable with the given name.
+ *
+ * @param name is the name of the variable. The name must be well-formed.
+ * @return the value of the variable, or a NULL variant if the variable does
+ * not exist.
+ * @throws ScriptEngineException if name is not a well-formed identifier.
+ */
+ Variant getVariable(const std::string &name)
+ {
+ checkIdentifier(name);
+ return doGetVariable(name);
+ }
+
+};
+
+/**
+ * The abstract ScriptEngine class is used to provide an interface for script
+ * engine implementations. A script engine implementation has to provide a
+ * function which creates an execution scope.
+ */
+class ScriptEngine {
+
+public:
+ /**
+ * Requests an execution scope from the script engine implementation. The
+ * calling code is responsible for disposing the returned pointer.
+ */
+ virtual ScriptEngineScope* createScope() const = 0;
+
+};
+
+/**
+ * The ScriptEngineFactory class is a central registry for ScriptEngine
+ * instances and factory of ScriptEngineScope instances for a certain scripting
+ * language.
+ */
+class ScriptEngineFactory {
+
+private:
+ /**
+ * Internal map between the script language name and the actual script
+ * engine instance.
+ */
+ std::map<std::string, ScriptEngine*> registry;
+
+public:
+
+ /**
+ * Registers a ScriptEngine instance for a new scripting language.
+ *
+ * @param name is the name of the scripting language as MIME, e.g.
+ * "text/javascript"
+ * @param engine is the backend that should be registered.
+ */
+ void registerScriptEngine(const std::string &name, ScriptEngine *engine);
+
+ /**
+ * Removes a script engine from the registry.
+ *
+ * @param name is the name of the script engine that
+ */
+ bool unregisterScriptEngine(const std::string &name);
+
+ /**
+ * Creates an execution scope for the scripting language with the given
+ * name.
+ *
+ * @param name is the name of the scripting language for which the scope
+ * is being created.
+ * @return a pointer to the new execution scope or null if a script engine
+ * with the given name does not exist. The caller of this function is
+ * responsible
+ */
+ ScriptEngineScope* createScope(const std::string &name) const;
+
+};
+
+}
+}
+
+
+#endif /* _OUSIA_SCRIPT_ENGINE_HPP_ */
+
+
diff --git a/src/core/script/Variant.cpp b/src/core/script/Variant.cpp
index 623b396..a379735 100644
--- a/src/core/script/Variant.cpp
+++ b/src/core/script/Variant.cpp
@@ -24,9 +24,12 @@ namespace script {
std::ostream& operator<< (std::ostream& os, const Variant &v)
{
switch (v.type) {
- case VariantType::none:
+ case VariantType::null:
os << "null";
break;
+ case VariantType::boolean:
+ os << (v.booleanValue ? "true" : "false");
+ break;
case VariantType::integer:
os << v.integerValue;
break;
@@ -34,12 +37,12 @@ std::ostream& operator<< (std::ostream& os, const Variant &v)
os << v.numberValue;
break;
case VariantType::string:
- os << "\"" << v.stringValue << "\"";
+ os << "\"" << v.getStringValue() << "\"";
break;
case VariantType::array: {
bool first = true;
os << "[";
- for (auto &v2 : v.arrayValue) {
+ for (auto &v2 : v.getArrayValue()) {
if (!first) {
os << ", ";
}
@@ -52,7 +55,7 @@ std::ostream& operator<< (std::ostream& os, const Variant &v)
case VariantType::map: {
bool first = true;
os << "{";
- for (auto &v2 : v.mapValue) {
+ for (auto &v2 : v.getMapValue()) {
if (!first) {
os << ", ";
}
diff --git a/src/core/script/Variant.hpp b/src/core/script/Variant.hpp
index e427af5..faa5bad 100644
--- a/src/core/script/Variant.hpp
+++ b/src/core/script/Variant.hpp
@@ -19,6 +19,8 @@
#ifndef _OUSIA_VARIANT_HPP_
#define _OUSIA_VARIANT_HPP_
+#include <iostream>
+
#include <cstdint>
#include <ostream>
#include <string>
@@ -28,8 +30,6 @@
namespace ousia {
namespace script {
-// TODO: Make Variant immutable (?), store large objects in heap buffer
-
/**
* Enum containing the possible types a variant may have.
*/
@@ -44,50 +44,28 @@ enum class VariantType {
class Variant {
private:
- VariantType type;
+ const VariantType type;
union {
bool booleanValue;
int64_t integerValue;
double numberValue;
- std::string stringValue;
- std::vector<Variant> arrayValue;
- std::map<std::string, Variant> mapValue;
+ void *objectValue = nullptr;
};
- /**
- * Private function calling the destructor of the currently used union
- * member.
- */
- void free() {
- // Explicitly call the destructor
- switch (type) {
- case VariantType::string:
- stringValue.std::string::~string();
- break;
- case VariantType::array:
- arrayValue.std::vector<Variant>::~vector();
- break;
- case VariantType::map:
- mapValue.std::map<std::string, Variant>::~map();
- break;
- default:
- break;
- }
+public:
- // Reset the type
- type = VariantType::none;
- }
+ class EBadEntry {};
- /**
- * Function for copying the content of the given instance v to this
- * instance. Callers must make sure the storage space has been freed
- * beforehand.
- */
- void copy(const Variant &v)
+ Variant(const Variant &v) :
+ type(v.type)
{
- type = v.type;
- switch (type) {
+ switch (v.type) {
+ case VariantType::null:
+ break;
+ case VariantType::boolean:
+ booleanValue = v.booleanValue;
+ break;
case VariantType::integer:
integerValue = v.integerValue;
break;
@@ -95,28 +73,34 @@ private:
numberValue = v.numberValue;
break;
case VariantType::string:
- new (&stringValue) std::string(v.stringValue);
+ objectValue = new std::string(
+ *static_cast<std::string*>(v.objectValue));
break;
case VariantType::array:
- new (&arrayValue) std::vector<Variant>(v.arrayValue);
+ objectValue = new std::vector<Variant>(
+ *static_cast<std::vector<Variant>*>(v.objectValue));
break;
case VariantType::map:
- new (&mapValue) std::map<std::string, Variant>(v.mapValue);
+ objectValue = new std::map<std::string, Variant>(
+ *static_cast<std::map<std::string, Variant>*>(v.objectValue));
break;
- default:
+ case VariantType::function:
+ case VariantType::object:
+ case VariantType::buffer:
+ // TODO
break;
}
}
- /**
- * Function for moving the content of the given instance v to this instance.
- * No copy operation is used. Callers must make sure the storage space has
- * been freed beforehand.
- */
- void move(Variant &v)
+ Variant(Variant &&v) :
+ type(v.type)
{
- type = v.type;
switch (type) {
+ case VariantType::null:
+ break;
+ case VariantType::boolean:
+ booleanValue = v.booleanValue;
+ break;
case VariantType::integer:
integerValue = v.integerValue;
break;
@@ -124,97 +108,96 @@ private:
numberValue = v.numberValue;
break;
case VariantType::string:
- new (&stringValue) std::string(std::move(v.stringValue));
+ case VariantType::array:
+ case VariantType::map:
+ case VariantType::function:
+ case VariantType::object:
+ case VariantType::buffer:
+ objectValue = v.objectValue;
+ v.objectValue = nullptr;
+ break;
+ }
+ }
+
+ ~Variant()
+ {
+ switch (type) {
+ case VariantType::string:
+ delete static_cast<std::string*>(objectValue);
break;
case VariantType::array:
- new (&arrayValue) std::vector<Variant>(std::move(v.arrayValue));
+ delete static_cast<std::vector<Variant>*>(objectValue);
break;
case VariantType::map:
- new (&mapValue) std::map<std::string, Variant>(std::move(v.mapValue));
+ delete static_cast<std::map<std::string, Variant>*>(objectValue);
break;
default:
break;
}
-
- // Reset the type of v to "none"
- v.type = VariantType::none;
}
-public:
+ Variant& operator=(const Variant &v) = delete;
+ Variant& operator=(Variant &&v) = delete;
- class EBadEntry {};
-
- Variant(const Variant &v)
- {
- copy(v);
- }
-
- Variant(Variant &&v)
- {
- move(v);
- }
-
- Variant& operator=(const Variant &v)
- {
- free();
- copy(v);
- return *this;
- }
-
- Variant& operator=(Variant &&v)
- {
- free();
- move(v);
- return *this;
- }
+ Variant() :
+ type(VariantType::null) {}
+ Variant(bool b) :
+ type(VariantType::boolean),
+ booleanValue(b) {}
Variant(int64_t i) :
type(VariantType::integer),
- integerValue(i)
- {
- // Do nothing here
- }
+ integerValue(i) {}
Variant(double d) :
type(VariantType::number),
- numberValue(d)
- {
- // Do nothing here
- }
+ numberValue(d) {}
Variant(const char *s) :
- type(VariantType::string)
- {
- new (&stringValue) std::string(s);
- }
+ type(VariantType::string),
+ objectValue(new std::string(s)) {}
Variant(const std::vector<Variant> &a) :
- type(VariantType::array)
- {
- new (&arrayValue) std::vector<Variant>(a);
- }
-
+ type(VariantType::array),
+ objectValue(new std::vector<Variant>(a)) {}
Variant(const std::map<std::string, Variant> &m) :
- type(VariantType::map)
- {
- new (&mapValue) std::map<std::string, Variant>(m);
- }
+ type(VariantType::map),
+ objectValue(new std::map<std::string, Variant>(m)) {}
- ~Variant()
+ VariantType getType() const
{
- free();
+ return type;
}
- VariantType getType() const
+ bool getBooleanValue() const
{
- return type;
+ switch (type) {
+ case VariantType::null:
+ return false;
+ case VariantType::boolean:
+ return booleanValue;
+ case VariantType::integer:
+ return integerValue != 0;
+ case VariantType::number:
+ return numberValue != 0.0;
+ case VariantType::string:
+ return !getStringValue().empty();
+ case VariantType::array:
+ return !getArrayValue().empty();
+ case VariantType::map:
+ return !getMapValue().empty();
+ default:
+ throw EBadEntry{};
+ }
}
int64_t getIntegerValue() const
{
switch (type) {
+ case VariantType::boolean:
+ return booleanValue ? 1 : 0;
case VariantType::integer:
return integerValue;
case VariantType::number:
@@ -227,6 +210,8 @@ public:
double getNumberValue() const
{
switch (type) {
+ case VariantType::boolean:
+ return booleanValue ? 1.0 : 0.0;
case VariantType::integer:
return static_cast<double>(integerValue);
case VariantType::number:
@@ -240,7 +225,7 @@ public:
{
switch (type) {
case VariantType::string:
- return stringValue;
+ return *(static_cast<std::string*>(objectValue));
default:
throw EBadEntry {};
}
@@ -250,7 +235,7 @@ public:
{
switch (type) {
case VariantType::array:
- return arrayValue;
+ return *(static_cast<std::vector<Variant>*>(objectValue));
default:
throw EBadEntry {};
}
@@ -260,7 +245,7 @@ public:
{
switch (type) {
case VariantType::map:
- return mapValue;
+ return *(static_cast<std::map<std::string, Variant>*>(objectValue));
default:
throw EBadEntry {};
}
diff --git a/src/core/utils/Utils.cpp b/src/core/utils/Utils.cpp
new file mode 100644
index 0000000..184fdd0
--- /dev/null
+++ b/src/core/utils/Utils.cpp
@@ -0,0 +1,39 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "Utils.hpp"
+
+namespace ousia {
+
+bool Utils::isIdentifier(const std::string &name)
+{
+ bool first = true;
+ for (char c : name) {
+ if (first && !(isAlphabetic(c) || c == '_')) {
+ return false;
+ }
+ if (first && !(isAlphanumeric(c) || c == '_' || c == '-')) {
+ return false;
+ }
+ first = false;
+ }
+ return true;
+}
+
+}
+
diff --git a/src/core/utils/Utils.hpp b/src/core/utils/Utils.hpp
new file mode 100644
index 0000000..2fcd794
--- /dev/null
+++ b/src/core/utils/Utils.hpp
@@ -0,0 +1,65 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef _OUSIA_UTILS_H_
+#define _OUSIA_UTILS_H_
+
+#include <string>
+
+namespace ousia {
+
+class Utils {
+
+public:
+
+ /**
+ * Returns true if the given character is in [A-Za-z]
+ */
+ static bool isAlphabetic(const char c)
+ {
+ return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
+ }
+
+ /**
+ * Returns true if the given character is in [0-9]
+ */
+ static bool isNumeric(const char c)
+ {
+ return (c >= '0') && (c <= '9');
+ }
+
+ /**
+ * Returns true if the given character is in [A-Za-z0-9]
+ */
+ static bool isAlphanumeric(const char c)
+ {
+ return isAlphabetic(c) || isNumeric(c);
+ }
+
+ /**
+ * Returns true if the given character is in [A-Za-z_][A-Za-z0-9_-]*
+ */
+ static bool isIdentifier(const std::string &name);
+
+};
+
+}
+
+#endif /* _OUSIA_UTILS_H_ */
+
diff --git a/test/core/script/Variant.cpp b/test/core/script/Variant.cpp
index 164bcab..cf8f3c7 100644
--- a/test/core/script/Variant.cpp
+++ b/test/core/script/Variant.cpp
@@ -23,6 +23,17 @@
namespace ousia {
namespace script {
+TEST(Variant, getBooleanValue)
+{
+ ASSERT_TRUE((Variant{true}).getBooleanValue());
+ ASSERT_FALSE((Variant{false}).getBooleanValue());
+ ASSERT_FALSE((Variant{(int64_t)0}).getBooleanValue());
+ ASSERT_TRUE((Variant{(int64_t)1}).getBooleanValue());
+ ASSERT_FALSE((Variant{0.0}).getBooleanValue());
+ ASSERT_TRUE((Variant{1.2}).getBooleanValue());
+ ASSERT_FALSE((Variant{""}).getBooleanValue());
+}
+
TEST(Variant, getIntegerValue)
{
Variant vi{(int64_t)42};
@@ -30,6 +41,8 @@ TEST(Variant, getIntegerValue)
ASSERT_EQ(42, vi.getIntegerValue());
ASSERT_EQ(42, vf.getIntegerValue());
+ ASSERT_EQ(1, (Variant{true}).getIntegerValue());
+ ASSERT_EQ(0, (Variant{false}).getIntegerValue());
}
TEST(Variant, getNumberValue)
@@ -39,6 +52,8 @@ TEST(Variant, getNumberValue)
ASSERT_EQ(42, vi.getNumberValue());
ASSERT_EQ(42.5, vf.getNumberValue());
+ ASSERT_EQ(1.0, (Variant{true}).getIntegerValue());
+ ASSERT_EQ(0.0, (Variant{false}).getIntegerValue());
}
TEST(Variant, getStringValue)
diff --git a/test/core/utils/Utils.cpp b/test/core/utils/Utils.cpp
new file mode 100644
index 0000000..d349c6f
--- /dev/null
+++ b/test/core/utils/Utils.cpp
@@ -0,0 +1,35 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+
+#include <core/utils/Utils.hpp>
+
+namespace ousia {
+
+TEST(Utils, isIdentifier)
+{
+ ASSERT_TRUE(Utils::isIdentifier("test"));
+ ASSERT_TRUE(Utils::isIdentifier("t0-_est"));
+ ASSERT_TRUE(Utils::isIdentifier("_t0-_EST"));
+ ASSERT_FALSE(Utils::isIdentifier("-t0-_EST"));
+ ASSERT_FALSE(Utils::isIdentifier("0t-_EST"));
+}
+
+}
+