LSLiteral.h
// LSLiteral.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2006
#pragma once
#ifndef Ceda_cxMacroExpander_LSLiteral_H
#define Ceda_cxMacroExpander_LSLiteral_H
#include "cxMacroExpander.h"
#include "Ceda/cxUtils/xstring.h"
#include "Ceda/cxUtils/CedaAssert.h"
#include "Ceda/cxUtils/IException.h"
#include <type_traits>
namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// LSLiteral
struct cxMacroExpander_API LiteralException : public IException
{
LiteralException(ConstStringZ description) :
m_description(description)
{
}
virtual void Write(xostream& os) const { os << m_description; }
xstring m_description;
};
enum ELiteral
{
LITERAL_UNDEF,
LITERAL_VOID,
LITERAL_BOOL,
LITERAL_INT64,
LITERAL_FLOAT64,
LITERAL_CHAR,
LITERAL_STRING
};
struct cxMacroExpander_API LSLiteral
{
LSLiteral() : m_type(LITERAL_UNDEF) {}
LSLiteral(bool x) : m_type(LITERAL_BOOL), m_bool(x) {}
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
LSLiteral(T x) : m_type(LITERAL_INT64), m_int64( static_cast<int64>(x) ) {}
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
LSLiteral(T x) : m_type(LITERAL_FLOAT64), m_float64( static_cast<float64>(x) ) {}
LSLiteral(const xstring& x) : m_type(LITERAL_STRING), m_string(x) {}
// Needed since xchar might match int8
static LSLiteral MakeChar(xchar x)
{
LSLiteral l;
l.m_type = LITERAL_CHAR;
l.m_char = x;
return l;
}
LSLiteral operator[](const LSLiteral& index) const;
// Used for strings or vector types
ssize_t GetLength() const;
bool operator==(ELiteral type) const { return m_type == type; }
bool operator!=(ELiteral type) const { return m_type != type; }
// The lhs must be an L-value. Currently no l-value literals are supported
void Assign(const LSLiteral& rhs);
// Coercion functions.
// allowDataLoss indicates whether a conversion that results in data loss is permitted.
// throwExceptions indicates whether exceptions should be thrown if a conversion can't be achieved
bool AsBool(bool& v, bool allowDataLoss, bool throwExceptions) const;
bool AsInt8(int8& v, bool allowDataLoss, bool throwExceptions) const;
bool AsInt16(int16& v, bool allowDataLoss, bool throwExceptions) const;
bool AsInt32(int32& v, bool allowDataLoss, bool throwExceptions) const;
bool AsInt64(int64& v, bool allowDataLoss, bool throwExceptions) const;
bool AsUInt8(uint8& v, bool allowDataLoss, bool throwExceptions) const;
bool AsUInt16(uint16& v, bool allowDataLoss, bool throwExceptions) const;
bool AsUInt32(uint32& v, bool allowDataLoss, bool throwExceptions) const;
bool AsUInt64(uint64& v, bool allowDataLoss, bool throwExceptions) const;
bool AsFloat32(float32& v, bool allowDataLoss, bool throwExceptions) const;
bool AsFloat64(float64& v, bool allowDataLoss, bool throwExceptions) const;
bool AsChar(xchar& v, bool allowDataLoss, bool throwExceptions) const;
bool AsString(xstring& v, bool allowDataLoss, bool throwExceptions) const;
bool CoercibleToBool() const { bool v; return AsBool(v,false,false); }
bool AsBool(bool allowDataLoss = false) const { bool v; cxVerify(AsBool(v,allowDataLoss,true)); return v; }
bool CoercibleToInt8() const { int8 v; return AsInt8(v,false,false); }
int8 AsInt8(bool allowDataLoss = false) const { int8 v; cxVerify(AsInt8(v,allowDataLoss,true)); return v; }
bool CoercibleToInt16() const { int16 v; return AsInt16(v,false,false); }
int16 AsInt16(bool allowDataLoss = false) const { int16 v; cxVerify(AsInt16(v,allowDataLoss,true)); return v; }
bool CoercibleToInt32() const { int32 v; return AsInt32(v,false,false); }
int32 AsInt32(bool allowDataLoss = false) const { int32 v; cxVerify(AsInt32(v,allowDataLoss,true)); return v; }
bool CoercibleToInt64() const { int64 v; return AsInt64(v,false,false); }
int64 AsInt64(bool allowDataLoss = false) const { int64 v; cxVerify(AsInt64(v,allowDataLoss,true)); return v; }
bool CoercibleToUInt8() const { uint8 v; return AsUInt8(v,false,false); }
uint8 AsUInt8(bool allowDataLoss = false) const { uint8 v; cxVerify(AsUInt8(v,allowDataLoss,true)); return v; }
bool CoercibleToUInt16() const { uint16 v; return AsUInt16(v,false,false); }
uint16 AsUInt16(bool allowDataLoss = false) const { uint16 v; cxVerify(AsUInt16(v,allowDataLoss,true)); return v; }
bool CoercibleToUInt32() const { uint32 v; return AsUInt32(v,false,false); }
uint32 AsUInt32(bool allowDataLoss = false) const { uint32 v; cxVerify(AsUInt32(v,allowDataLoss,true)); return v; }
bool CoercibleToUInt64() const { uint64 v; return AsUInt64(v,false,false); }
uint64 AsUInt64(bool allowDataLoss = false) const { uint64 v; cxVerify(AsUInt64(v,allowDataLoss,true)); return v; }
bool CoercibleToFloat32() const { float32 v; return AsFloat32(v,false,false); }
float32 AsFloat32(bool allowDataLoss = false) const { float32 v; cxVerify(AsFloat32(v,allowDataLoss,true)); return v; }
bool CoercibleToFloat64() const { float64 v; return AsFloat64(v,false,false); }
float64 AsFloat64(bool allowDataLoss = false) const { float64 v; cxVerify(AsFloat64(v,allowDataLoss,true)); return v; }
bool CoercibleToChar() const { xchar v; return AsChar(v,false,false); }
xchar AsChar(bool allowDataLoss = false) const { xchar v; cxVerify(AsChar(v,allowDataLoss,true)); return v; }
bool CoercibleToString() const { xstring v; return AsString(v,false,false); }
void AsString(xstring& v, bool allowDataLoss = false) const { cxVerify(AsString(v,allowDataLoss,true)); }
xstring AsString(bool allowDataLoss = false) const { xstring v; AsString(v,allowDataLoss); return v; }
ELiteral m_type;
union
{
bool m_bool;
int64 m_int64;
float64 m_float64;
xchar m_char;
};
xstring m_string;
};
// Binary arithmetic operations
cxMacroExpander_API const LSLiteral operator+(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator-(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator*(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator/(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator%(const LSLiteral& x, const LSLiteral& y);
// Binary shift operations
cxMacroExpander_API const LSLiteral operator<<(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator>>(const LSLiteral& x, const LSLiteral& y);
// Binary logical operations
cxMacroExpander_API const LSLiteral operator||(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator&&(const LSLiteral& x, const LSLiteral& y);
// Binary bitwise operations
cxMacroExpander_API const LSLiteral operator|(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator&(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API const LSLiteral operator^(const LSLiteral& x, const LSLiteral& y);
// Unary operations
cxMacroExpander_API bool operator!(const LSLiteral& x);
cxMacroExpander_API LSLiteral operator+(const LSLiteral& x);
cxMacroExpander_API LSLiteral operator-(const LSLiteral& x);
cxMacroExpander_API LSLiteral operator~(const LSLiteral& x);
// Comparision assuming value semantics (ie equivalence of value only)
cxMacroExpander_API bool IsEqual(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API bool IsLess(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API bool IsLessThanOrEqual(const LSLiteral& x, const LSLiteral& y);
// Comparision assuming object semantics
cxMacroExpander_API bool operator==(const LSLiteral& x, const LSLiteral& y);
cxMacroExpander_API inline bool operator!=(const LSLiteral& x, const LSLiteral& y) { return !(x == y); }
// Uses a total ordering as a C++ type
//cxMacroExpander_API bool operator<(const LSLiteral& x, const LSLiteral& y);
//cxMacroExpander_API bool operator<=(const LSLiteral& x, const LSLiteral& y);
//inline bool operator>(const LSLiteral& x, const LSLiteral& y) { return y < x; }
//inline bool operator>=(const LSLiteral& x, const LSLiteral& y) { return y <= x; }
cxMacroExpander_API LSLiteral Power(const LSLiteral& x, const LSLiteral& y);
} // namespace ceda
#endif // include guard