/*
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 .
*/
#include "Variant.hpp"
#include "Function.hpp"
#include "Object.hpp"
namespace ousia {
namespace script {
/* Class Variant */
const Variant Variant::Null;
Variant::Variant(const Variant &v) : type(v.type)
{
switch (v.type) {
case VariantType::null:
break;
case VariantType::boolean:
booleanValue = v.booleanValue;
break;
case VariantType::integer:
integerValue = v.integerValue;
break;
case VariantType::number:
numberValue = v.numberValue;
break;
case VariantType::string:
objectValue =
new std::string(*static_cast(v.objectValue));
break;
case VariantType::array:
objectValue = new std::vector(
*static_cast *>(v.objectValue));
break;
case VariantType::map:
objectValue = new std::map(
*static_cast *>(v.objectValue));
break;
case VariantType::function:
objectValue = static_cast(v.objectValue)->clone();
break;
case VariantType::object:
objectValue = new Object(*static_cast(v.objectValue));
break;
case VariantType::buffer:
// TODO
break;
}
}
Variant::Variant(Variant &&v) : type(v.type)
{
switch (type) {
case VariantType::null:
break;
case VariantType::boolean:
booleanValue = v.booleanValue;
break;
case VariantType::integer:
integerValue = v.integerValue;
break;
case VariantType::number:
numberValue = v.numberValue;
break;
case VariantType::string:
case VariantType::array:
case VariantType::map:
case VariantType::function:
case VariantType::object:
case VariantType::buffer:
objectValue = v.objectValue;
v.objectValue = nullptr;
break;
}
}
Variant::Variant() : type(VariantType::null)
{
}
Variant::Variant(bool b) : type(VariantType::boolean), booleanValue(b)
{
}
Variant::Variant(int64_t i) : type(VariantType::integer), integerValue(i)
{
}
Variant::Variant(double d) : type(VariantType::number), numberValue(d)
{
}
Variant::Variant(const char *s)
: type(VariantType::string), objectValue(new std::string(s))
{
}
Variant::Variant(const std::vector &a)
: type(VariantType::array), objectValue(new std::vector(a))
{
}
Variant::Variant(const std::map &m)
: type(VariantType::map), objectValue(new std::map(m))
{
}
Variant::Variant(const Function *f)
: type(VariantType::function), objectValue(f->clone())
{
}
Variant::Variant(const Object &o)
: type(VariantType::object), objectValue(new Object(o))
{
}
Variant::~Variant()
{
switch (type) {
case VariantType::string:
delete static_cast(objectValue);
break;
case VariantType::array:
delete static_cast *>(objectValue);
break;
case VariantType::map:
delete static_cast *>(objectValue);
break;
case VariantType::function:
delete static_cast(objectValue);
break;
case VariantType::object:
delete static_cast(objectValue);
break;
default:
break;
}
}
bool Variant::getBooleanValue() const
{
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 VariantTypeException{VariantType::boolean, type};
}
}
int64_t Variant::getIntegerValue() const
{
switch (type) {
case VariantType::boolean:
return booleanValue ? 1 : 0;
case VariantType::integer:
return integerValue;
case VariantType::number:
return static_cast(numberValue);
default:
throw VariantTypeException{VariantType::integer, type};
}
}
double Variant::getNumberValue() const
{
switch (type) {
case VariantType::boolean:
return booleanValue ? 1.0 : 0.0;
case VariantType::integer:
return static_cast(integerValue);
case VariantType::number:
return numberValue;
default:
throw VariantTypeException{VariantType::number, type};
}
}
const std::string &Variant::getStringValue() const
{
switch (type) {
case VariantType::string:
return *(static_cast(objectValue));
default:
throw VariantTypeException{VariantType::string, type};
}
}
const std::vector &Variant::getArrayValue() const
{
switch (type) {
case VariantType::array:
return *(static_cast *>(objectValue));
default:
throw VariantTypeException{VariantType::array, type};
}
}
const std::map &Variant::getMapValue() const
{
switch (type) {
case VariantType::map:
return *(static_cast *>(
objectValue));
default:
throw VariantTypeException{VariantType::map, type};
}
}
const Function *Variant::getFunctionValue() const
{
switch (type) {
case VariantType::function: return static_cast(objectValue);
default:
throw VariantTypeException{VariantType::function, type};
}
}
const Object &Variant::getObjectValue() const
{
switch (type) {
case VariantType::object: return *(static_cast(objectValue));
default:
throw VariantTypeException{VariantType::object, type};
}
}
const char *Variant::getTypeName(VariantType type)
{
switch (type) {
case VariantType::null:
return "null";
case VariantType::boolean:
return "boolean";
case VariantType::integer:
return "integer";
case VariantType::number:
return "number";
case VariantType::string:
return "string";
case VariantType::array:
return "array";
case VariantType::map:
return "map";
case VariantType::function:
return "function";
case VariantType::object:
return "object";
case VariantType::buffer:
return "buffer";
}
return "unknown";
}
/* Class VariantTypeException */
VariantTypeException::VariantTypeException(VariantType actualType,
VariantType requestedType)
: msg(std::string("Cannot get value of variant of type \"") +
Variant::getTypeName(actualType) + std::string("\" as \"") +
Variant::getTypeName(requestedType) + std::string("\"")),
actualType(actualType),
requestedType(requestedType)
{
}
const char *VariantTypeException::what() const noexcept
{
return msg.c_str();
}
/* Global scope operator */
std::ostream &operator<<(std::ostream &os, const Variant &v)
{
switch (v.type) {
case VariantType::null:
os << "null";
break;
case VariantType::boolean:
os << (v.booleanValue ? "true" : "false");
break;
case VariantType::integer:
os << v.integerValue;
break;
case VariantType::number:
os << v.numberValue;
break;
case VariantType::string:
os << "\"" << v.getStringValue() << "\"";
break;
case VariantType::array: {
bool first = true;
os << "[";
for (auto &v2 : v.getArrayValue()) {
if (!first) {
os << ", ";
}
os << v2;
first = false;
}
os << "]";
break;
}
case VariantType::map: {
bool first = true;
os << "{";
for (auto &v2 : v.getMapValue()) {
if (!first) {
os << ", ";
}
os << "\"" << v2.first << "\": " << v2.second;
first = false;
}
os << "}";
break;
}
case VariantType::function:
os << "";
break;
case VariantType::object:
os << "";
break;
case VariantType::buffer:
os << "";
break;
}
return os;
}
}
}