Partially added comparators and math operations to numerical properties

This commit is contained in:
Dominik Tomičević 2016-02-13 17:59:48 +01:00
parent 694d3363d6
commit c40758363c
13 changed files with 432 additions and 93 deletions

View File

@ -0,0 +1,47 @@
#pragma once
#include "property.hpp"
class Bool : public Property
{
public:
static constexpr Flags type = Flags::Bool;
Bool(bool value) : Property(value ? Flags::True : Flags::False) {}
Bool(const Bool& other) = default;
bool value() const
{
// true when the subtraction of True from flags is equal to zero
// True 0000 0000 0000 0000 0000 0000 0000 0011
// False 0000 0000 0000 0000 0000 0000 0000 0101
//
// True - True = 0
// False - True != 0
return (underlying_cast(flags) - underlying_cast(Flags::True)) == 0;
}
explicit operator bool() const
{
return value();
}
bool operator==(const Property& other) const override
{
return other.is<Bool>() && operator==(other.as<Bool>());
}
bool operator==(const Bool& other) const
{
return other.flags == flags;
}
bool operator==(bool v) const
{
return value() == v;
}
};

View File

@ -0,0 +1,12 @@
#pragma once
#include "floating.hpp"
class Float : public Floating<Float>
{
static constexpr Flags type = Flags::Float;
Float(float value) : Floating(Flags::Float), value(value) {}
float value;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "number.hpp"
template <class Derived>
struct Floating : public Number<Derived>
{
using Number<Derived>::Number;
};

View File

@ -0,0 +1,44 @@
#pragma once
#include "integral.hpp"
class Int32 : public Integral<Int32>
{
public:
static constexpr Flags type = Flags::Int32;
Int32(int32_t value) : Integral(Flags::Int32), value(value) {}
/* friend constexpr bool operator==(const Int32& lhs, const Int32& rhs) */
/* { */
/* return lhs.value == rhs.value; */
/* } */
/* friend constexpr bool operator<(const Int32& lhs, const Int32& rhs) */
/* { */
/* return lhs.value < rhs.value; */
/* } */
/* friend constexpr bool operator==(const Int32& lhs, int32_t rhs) */
/* { */
/* return lhs.value == rhs; */
/* } */
/* friend constexpr bool operator<(const Int32& lhs, int32_t rhs) */
/* { */
/* return lhs.value < rhs; */
/* } */
/* friend constexpr bool operator==(int32_t lhs, const Int32& rhs) */
/* { */
/* return lhs == rhs.value; */
/* } */
/* friend constexpr bool operator<(int32_t lhs, const Int32& rhs) */
/* { */
/* return lhs < rhs.value; */
/* } */
int32_t value;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "number.hpp"
template <class Derived>
struct Integral : public Number<Derived>
{
using Number<Derived>::Number;
};

View File

@ -0,0 +1,41 @@
#pragma once
#include "property.hpp"
class Null : public Property
{
public:
friend class Property;
static constexpr Flags type = Flags::Null;
Null(const Null&) = delete;
Null(Null&&) = delete;
Null operator=(const Null&) = delete;
bool operator==(const Property& other) const override
{
return other.is<Null>();
}
bool operator==(const Null&) const
{
return true;
}
explicit operator bool()
{
return false;
}
private:
// the constructor for null is private, it can be constructed only as a
// value inside the Property class, Property::Null
Null() : Property(Flags::Null) {}
};
// Null is a const singleton declared in class Property
// it can be used as a type by using Null or as a value by using Property::Null
const Null Property::Null;

View File

@ -0,0 +1,38 @@
#pragma once
#include "property.hpp"
#include "utils/crtp.hpp"
#include "utils/total_ordering.hpp"
#include "utils/unary_negation.hpp"
#include "utils/math_operations.hpp"
template <class Derived>
class Number : public Property,
public Crtp<Derived>,
public TotalOrdering<Derived>,
public MathOperations<Derived>,
public UnaryNegation<Derived>
{
public:
using Property::Property;
bool operator==(const Property& other) const override
{
return other.is<Derived>() && *this == other.as<Derived>();
}
friend bool operator==(const Derived& lhs, const Derived& rhs)
{
return lhs.value == rhs.value;
}
friend bool operator<(const Derived& lhs, const Derived& rhs)
{
return lhs.value == rhs.value;
}
friend std::ostream& operator<<(std::ostream& s, const Derived& number)
{
return s << number.value;
}
};

View File

@ -3,16 +3,24 @@
#include <map>
#include "property.hpp"
#include "null.hpp"
#include "bool.hpp"
#include "string.hpp"
#include "int32.hpp"
class Properties
{
using props_t = std::map<std::string, Property::sptr>;
public:
const Property* at(const std::string& key) const
const Property& at(const std::string& key) const
{
auto it = props.find(key);
return it == props.end() ? nullptr : it->second.get();
if(it == props.end())
return Property::Null;
return *it->second.get();
}
template <class T, class... Args>
@ -59,3 +67,10 @@ public:
private:
props_t props;
};
template<>
void Properties::set<Null>(const std::string& key)
{
clear(key);
}

View File

@ -2,140 +2,144 @@
#include <memory>
#include <string>
#include <cassert>
#include "utils/underlying_cast.hpp"
struct Property
class Null;
class Property
{
public:
using sptr = std::shared_ptr<Property>;
enum class Flags : unsigned
{
Bool = 0x2,
True = 0x4 | Bool,
False = 0x8 | Bool,
// Type | Mask
// -----------+----------------------------------------
// Null | 0000 0000 0000 0000 0000 0000 0000 0000
// -----------+----------------------------------------
// Bool | 0000 0000 0000 0000 0000 0000 0000 0001
// + True | 0000 0000 0000 0000 0000 0000 0000 0011
// + False | 0000 0000 0000 0000 0000 0000 0000 0101
// -----------+----------------------------------------
// String | 0000 0000 0000 0000 0000 0000 0000 1000
// -----------+----------------------------------------
// Number | 0000 0000 0000 0000 0000 0000 0001 0000
// + Integral | 0000 0000 0000 0000 0000 0000 0011 0000
// + Int32 | 0000 0000 0000 0000 0000 0000 0111 0000
// + Int64 | 0000 0000 0000 0000 0000 0000 1011 0000
// + Floating | 0000 0000 0000 0000 0000 0001 0001 0000
// + Float | 0000 0000 0000 0000 0000 0011 0001 0000
// + Double | 0000 0000 0000 0000 0000 0101 0001 0000
// -----------+----------------------------------------
// Array | 0000 0000 0000 0000 0001 0000 0000 0000
// -----------+----------------------------------------
String = 0x10,
Null = 0x0,
Bool = 0x1,
True = 0x2 | Bool,
False = 0x4 | Bool,
Number = 0x20,
Integral = 0x40 | Number,
Int32 = 0x80 | Integral,
Int64 = 0x100 | Integral,
String = 0x8,
Floating = 0x200 | Number,
Float = 0x400 | Floating,
Double = 0x800 | Floating,
Number = 0x10,
Integral = 0x20 | Number,
Int32 = 0x40 | Integral,
Int64 = 0x80 | Integral,
Floating = 0x100 | Number,
Float = 0x200 | Floating,
Double = 0x400 | Floating,
Array = 0x1000,
type_mask = 0xFFF
};
static const Null Null;
Property(Flags flags) : flags(flags) {}
Property(const Property&) = default;
// this is giving problems with default constructors in derived classes
// Property(const Property&) = delete;
// Property(Property&&) = delete;
template <class T>
T* is()
virtual bool operator==(const Property& other) const = 0;
bool operator!=(const Property& other) const
{
return underlying_cast(flags) & T::type;
return !operator==(other);
}
template <class T>
T* as()
bool is() const
{
if(this->is<T>())
return static_cast<T*>(this);
return underlying_cast(flags) & underlying_cast(T::type);
}
return nullptr;
template <class T>
T& as()
{
assert(this->is<T>());
return *static_cast<T*>(this);
}
template <class T>
const T& as() const
{
assert(this->is<T>());
return *static_cast<const T*>(this);
}
template <class Handler>
void accept(Handler& handler);
Flags flags;
const Flags flags;
};
struct Bool : public Property
{
static constexpr Flags type = Flags::Bool;
/* struct Int64 : public Property */
/* { */
/* static constexpr Flags type = Flags::Int64; */
Bool(bool value) : Property(value ? Flags::True : Flags::False) {}
/* Int64(int64_t value) */
/* : Property(Flags::Int64), value(value) {} */
bool value()
{
unsigned flags = underlying_cast(this->flags);
unsigned true_t = underlying_cast(Flags::True);
/* int64_t value; */
/* }; */
return (flags - true_t) == 0;
}
};
/* struct Float : public Property */
/* { */
/* static constexpr Flags type = Flags::Float; */
struct String : public Property
{
static constexpr Flags type = Flags::String;
/* Float(float value) */
/* : Property(Flags::Float), value(value) {} */
String(const std::string& value)
: Property(Flags::String), value(value) {}
/* float value; */
/* }; */
String(std::string&& value)
: Property(Flags::String), value(value) {}
/* struct Double : public Property */
/* { */
/* static constexpr Flags type = Flags::Double; */
std::string value;
};
/* Double(double value) */
/* : Property(Flags::Double), value(value) {} */
struct Int32 : public Property
{
static constexpr Flags type = Flags::Int32;
Int32(int32_t value)
: Property(Flags::Int32), value(value) {}
int32_t value;
};
struct Int64 : public Property
{
static constexpr Flags type = Flags::Int64;
Int64(int64_t value)
: Property(Flags::Int64), value(value) {}
int64_t value;
};
struct Float : public Property
{
static constexpr Flags type = Flags::Float;
Float(float value)
: Property(Flags::Float), value(value) {}
float value;
};
struct Double : public Property
{
static constexpr Flags type = Flags::Double;
Double(double value)
: Property(Flags::Double), value(value) {}
double value;
};
/* double value; */
/* }; */
template <class Handler>
void Property::accept(Handler& h)
{
switch(flags)
{
case Flags::True: return h.handle(static_cast<Bool&>(*this));
case Flags::False: return h.handle(static_cast<Bool&>(*this));
case Flags::String: return h.handle(static_cast<String&>(*this));
case Flags::Int32: return h.handle(static_cast<Int32&>(*this));
case Flags::Int64: return h.handle(static_cast<Int64&>(*this));
case Flags::Float: return h.handle(static_cast<Float&>(*this));
case Flags::Double: return h.handle(static_cast<Double&>(*this));
default: return;
}
/* switch(flags) */
/* { */
/* case Flags::True: return h.handle(static_cast<Bool&>(*this)); */
/* case Flags::False: return h.handle(static_cast<Bool&>(*this)); */
/* case Flags::String: return h.handle(static_cast<String&>(*this)); */
/* case Flags::Int32: return h.handle(static_cast<Int32&>(*this)); */
/* case Flags::Int64: return h.handle(static_cast<Int64&>(*this)); */
/* case Flags::Float: return h.handle(static_cast<Float&>(*this)); */
/* case Flags::Double: return h.handle(static_cast<Double&>(*this)); */
/* default: return; */
/* } */
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "property.hpp"
class String : public Property
{
public:
static constexpr Flags type = Flags::String;
String(const std::string& value) : Property(Flags::String), value(value) {}
String(std::string&& value) : Property(Flags::String), value(value) {}
String(const String&) = default;
String(String&&) = default;
operator const std::string&() const
{
return value;
}
bool operator==(const Property& other) const override
{
return other.is<String>() && operator==(other.as<String>());
}
bool operator==(const String& other) const
{
return value == other.value;
}
bool operator==(const std::string& other) const
{
return value == other;
}
std::string value;
};

View File

@ -0,0 +1,25 @@
#pragma once
template <class Derived>
struct MathOperations
{
friend Derived operator+(const Derived& lhs, const Derived& rhs)
{
return Derived(lhs.value + rhs.value);
}
friend Derived operator-(const Derived& lhs, const Derived& rhs)
{
return Derived(lhs.value - rhs.value);
}
friend Derived operator*(const Derived& lhs, const Derived& rhs)
{
return Derived(lhs.value * rhs.value);
}
friend Derived operator/(const Derived& lhs, const Derived& rhs)
{
return Derived(lhs.value / rhs.value);
}
};

View File

@ -0,0 +1,12 @@
#pragma once
#include "utils/crtp.hpp"
template <class Derived>
struct UnaryNegation : Crtp<Derived>
{
Derived operator-() const
{
return Derived(-this->derived().value);
}
};

View File

@ -0,0 +1,45 @@
#pragma once
template <class Derived, class T>
struct TotalOrderingWith
{
friend constexpr bool operator!=(const Derived& a, const T& b)
{
return !(a == b);
}
friend constexpr bool operator<=(const Derived& a, const T& b)
{
return a < b || a == b;
}
friend constexpr bool operator>(const Derived& a, const T& b)
{
return !(a <= b);
}
friend constexpr bool operator>=(const Derived& a, const T& b)
{
return !(a < b);
}
friend constexpr bool operator!=(const T& a, const Derived& b)
{
return !(a == b);
}
friend constexpr bool operator<=(const T& a, const Derived& b)
{
return a < b || a == b;
}
friend constexpr bool operator>(const T& a, const Derived& b)
{
return !(a <= b);
}
friend constexpr bool operator>=(const T& a, const Derived& b)
{
return !(a < b);
}
};