// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
//-----------------------------------------------------------------------------
// V8Value
//-----------------------------------------------------------------------------
class V8Value
{
public:
enum NonexistentInitializer
{
Nonexistent
};
enum UndefinedInitializer
{
Undefined
};
enum NullInitializer
{
Null
};
enum class Subtype: std::uint16_t
{
None,
ArrayBuffer,
DataView,
Uint8Array,
Uint8ClampedArray,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Float32Array,
Float64Array
};
explicit V8Value(NonexistentInitializer):
m_Type(Type::Nonexistent),
m_Subtype(Subtype::None)
{
}
explicit V8Value(UndefinedInitializer):
m_Type(Type::Undefined),
m_Subtype(Subtype::None)
{
}
explicit V8Value(NullInitializer):
m_Type(Type::Null),
m_Subtype(Subtype::None)
{
}
explicit V8Value(bool value):
m_Type(Type::Boolean),
m_Subtype(Subtype::None)
{
m_Data.BooleanValue = value;
}
explicit V8Value(double value):
m_Type(Type::Number),
m_Subtype(Subtype::None)
{
m_Data.DoubleValue = value;
}
explicit V8Value(std::int32_t value):
m_Type(Type::Int32),
m_Subtype(Subtype::None)
{
m_Data.Int32Value = value;
}
explicit V8Value(std::uint32_t value):
m_Type(Type::UInt32),
m_Subtype(Subtype::None)
{
m_Data.UInt32Value = value;
}
explicit V8Value(const StdString* pString):
m_Type(Type::String),
m_Subtype(Subtype::None)
{
m_Data.pString = pString;
}
V8Value(V8ObjectHolder* pV8ObjectHolder, Subtype subtype):
m_Type(Type::V8Object),
m_Subtype(subtype)
{
m_Data.pV8ObjectHolder = pV8ObjectHolder;
}
explicit V8Value(HostObjectHolder* pHostObjectHolder):
m_Type(Type::HostObject),
m_Subtype(Subtype::None)
{
m_Data.pHostObjectHolder = pHostObjectHolder;
}
V8Value(const V8Value& that)
{
Copy(that);
}
V8Value(V8Value&& that)
{
Move(that);
}
const V8Value& operator=(const V8Value& that)
{
Dispose();
Copy(that);
return *this;
}
const V8Value& operator=(V8Value&& that)
{
Dispose();
Move(that);
return *this;
}
bool IsNonexistent() const
{
return m_Type == Type::Nonexistent;
}
bool IsUndefined() const
{
return m_Type == Type::Undefined;
}
bool IsNull() const
{
return m_Type == Type::Null;
}
bool AsBoolean(bool& result) const
{
if (m_Type == Type::Boolean)
{
result = m_Data.BooleanValue;
return true;
}
return false;
}
bool AsNumber(double& result) const
{
if (m_Type == Type::Number)
{
result = m_Data.DoubleValue;
return true;
}
return false;
}
bool AsInt32(std::int32_t& result) const
{
if (m_Type == Type::Int32)
{
result = m_Data.Int32Value;
return true;
}
return false;
}
bool AsUInt32(std::uint32_t& result) const
{
if (m_Type == Type::UInt32)
{
result = m_Data.UInt32Value;
return true;
}
return false;
}
bool AsString(const StdString*& pString) const
{
if (m_Type == Type::String)
{
pString = m_Data.pString;
return true;
}
return false;
}
bool AsV8Object(V8ObjectHolder*& pV8ObjectHolder, Subtype& subtype) const
{
if (m_Type == Type::V8Object)
{
pV8ObjectHolder = m_Data.pV8ObjectHolder;
subtype = m_Subtype;
return true;
}
return false;
}
bool AsHostObject(HostObjectHolder*& pHostObjectHolder) const
{
if (m_Type == Type::HostObject)
{
pHostObjectHolder = m_Data.pHostObjectHolder;
return true;
}
return false;
}
~V8Value()
{
Dispose();
}
private:
enum class Type: std::uint16_t
{
Nonexistent,
Undefined,
Null,
Boolean,
Number,
Int32,
UInt32,
String,
V8Object,
HostObject
};
union Data
{
bool BooleanValue;
double DoubleValue;
std::int32_t Int32Value;
std::uint32_t UInt32Value;
const StdString* pString;
V8ObjectHolder* pV8ObjectHolder;
HostObjectHolder* pHostObjectHolder;
};
void Copy(const V8Value& that)
{
m_Type = that.m_Type;
m_Subtype = that.m_Subtype;
if (m_Type == Type::Boolean)
{
m_Data.BooleanValue = that.m_Data.BooleanValue;
}
else if (m_Type == Type::Number)
{
m_Data.DoubleValue = that.m_Data.DoubleValue;
}
else if (m_Type == Type::Int32)
{
m_Data.Int32Value = that.m_Data.Int32Value;
}
else if (m_Type == Type::UInt32)
{
m_Data.UInt32Value = that.m_Data.UInt32Value;
}
else if (m_Type == Type::String)
{
m_Data.pString = new StdString(*that.m_Data.pString);
}
else if (m_Type == Type::V8Object)
{
m_Data.pV8ObjectHolder = that.m_Data.pV8ObjectHolder->Clone();
}
else if (m_Type == Type::HostObject)
{
m_Data.pHostObjectHolder = that.m_Data.pHostObjectHolder->Clone();
}
}
void Move(V8Value& that)
{
m_Type = that.m_Type;
m_Subtype = that.m_Subtype;
m_Data = that.m_Data;
that.m_Type = Type::Undefined;
}
void Dispose()
{
if (m_Type == Type::String)
{
delete m_Data.pString;
}
else if (m_Type == Type::V8Object)
{
delete m_Data.pV8ObjectHolder;
}
else if (m_Type == Type::HostObject)
{
delete m_Data.pHostObjectHolder;
}
}
Type m_Type;
Subtype m_Subtype;
Data m_Data;
};