updated properties
This commit is contained in:
parent
0effba90d9
commit
6930b27d1f
120
proptest.cpp
Normal file
120
proptest.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/model/properties/property.hpp"
|
||||
|
||||
template <class Buffer>
|
||||
struct JsonWriter
|
||||
{
|
||||
public:
|
||||
JsonWriter(Buffer& buffer) : buffer(buffer)
|
||||
{
|
||||
buffer << '{';
|
||||
};
|
||||
|
||||
void handle(const std::string& key, Property& value, bool first)
|
||||
{
|
||||
if(!first)
|
||||
buffer << ',';
|
||||
|
||||
buffer << '"' << key << "\":";
|
||||
value.accept(*this);
|
||||
}
|
||||
|
||||
void handle(Null&)
|
||||
{
|
||||
buffer << "NULL";
|
||||
}
|
||||
|
||||
void handle(Bool& b)
|
||||
{
|
||||
buffer << (b.value() ? "true" : "false");
|
||||
}
|
||||
|
||||
void handle(String& s)
|
||||
{
|
||||
buffer << '"' << s.value << '"';
|
||||
}
|
||||
|
||||
void handle(Int32& int32)
|
||||
{
|
||||
buffer << std::to_string(int32.value);
|
||||
}
|
||||
|
||||
void handle(Int64& int64)
|
||||
{
|
||||
buffer << std::to_string(int64.value);
|
||||
}
|
||||
|
||||
void handle(Float& f)
|
||||
{
|
||||
buffer << std::to_string(f.value);
|
||||
}
|
||||
|
||||
void handle(Double& d)
|
||||
{
|
||||
buffer << std::to_string(d.value);
|
||||
}
|
||||
|
||||
void finish()
|
||||
{
|
||||
buffer << '}';
|
||||
}
|
||||
|
||||
private:
|
||||
Buffer& buffer;
|
||||
};
|
||||
|
||||
class StringBuffer
|
||||
{
|
||||
public:
|
||||
StringBuffer& operator<<(const std::string& str)
|
||||
{
|
||||
data += str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuffer& operator<<(const char* str)
|
||||
{
|
||||
data += str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBuffer& operator<<(char c)
|
||||
{
|
||||
data += c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string& str()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string data;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
StringBuffer buffer;
|
||||
auto handler = JsonWriter<StringBuffer>(buffer);
|
||||
|
||||
Properties props;
|
||||
props.emplace<Null>("sadness");
|
||||
props.emplace<Bool>("awesome", true);
|
||||
props.emplace<Bool>("lame", false);
|
||||
props.emplace<Int32>("age", 32);
|
||||
props.emplace<Int64>("money", 12345678910111213);
|
||||
props.emplace<String>("name", "caca");
|
||||
props.emplace<Float>("pi", 3.14159265358979323846264338327950288419716939937510582097);
|
||||
props.emplace<Double>("pi2", 3.141592653589793238462643383279502884197169399375105820);
|
||||
|
||||
props.accept(handler);
|
||||
handler.finish();
|
||||
|
||||
std::cout.precision(25);
|
||||
std::cout << buffer.str() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -30,7 +30,7 @@ void Response<Req, Res>::send(const std::string& body)
|
||||
|
||||
write_req->data = &connection;
|
||||
|
||||
buffer << "HTTP/1.1 " << to_string[status] << "\r\n";
|
||||
buffer << "HTTP/1.1 " << to_string(status) << "\r\n";
|
||||
|
||||
buffer << "Content-Length:" << std::to_string(body.size()) << "\r\n";
|
||||
|
||||
|
@ -72,11 +72,15 @@ enum Status
|
||||
#undef CODE
|
||||
};
|
||||
|
||||
static std::map<Status, std::string> to_string = {
|
||||
#define CODE(a, b, c) { Status::a, #b " " #c },
|
||||
HTTP_STATUS_CODES
|
||||
std::string to_string(Status status)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
#define CODE(a, b, c) case a: return #b " " #c;
|
||||
HTTP_STATUS_CODES
|
||||
#undef CODE
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,6 @@
|
||||
#include <map>
|
||||
|
||||
#include "property.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class Properties
|
||||
{
|
||||
@ -25,6 +21,22 @@ public:
|
||||
return it == props.end() ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
void emplace(const std::string& key, Args&&... args)
|
||||
{
|
||||
auto value = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
|
||||
// try to emplace the item
|
||||
auto result = props.emplace(std::make_pair(key, std::move(value)));
|
||||
|
||||
// return if we succedded
|
||||
if(result.second)
|
||||
return;
|
||||
|
||||
// the key already exists, replace the value it holds
|
||||
result.first->second = std::move(value);
|
||||
}
|
||||
|
||||
void put(const std::string& key, Property::sptr value)
|
||||
{
|
||||
props[key] = std::move(value);
|
||||
@ -35,24 +47,22 @@ public:
|
||||
props.erase(key);
|
||||
}
|
||||
|
||||
void dump(std::string& buffer)
|
||||
template <class Handler>
|
||||
void accept(Handler& handler)
|
||||
{
|
||||
buffer += '{';
|
||||
bool first = true;
|
||||
|
||||
for(auto& kvp : props)
|
||||
for(auto& kv : props)
|
||||
{
|
||||
buffer += '"'; buffer += kvp.first; buffer += "\":";
|
||||
kvp.second->dump(buffer); buffer += ',';
|
||||
handler.handle(kv.first, *kv.second, first);
|
||||
|
||||
if(first)
|
||||
first = false;
|
||||
}
|
||||
|
||||
// replace last redundant comma with }
|
||||
buffer.back() = '}';
|
||||
}
|
||||
|
||||
private:
|
||||
props_t props;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -4,52 +4,156 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace model
|
||||
{
|
||||
#include "utils/underlying_cast.hpp"
|
||||
|
||||
class Property
|
||||
struct Property
|
||||
{
|
||||
public:
|
||||
using sptr = std::shared_ptr<Property>;
|
||||
|
||||
template <class T, class... Args>
|
||||
static Property::sptr make(Args&&... args)
|
||||
enum class Flags : unsigned
|
||||
{
|
||||
return std::shared_ptr<Property>(new T(std::forward<Args>(args)...));
|
||||
Null = 0x1,
|
||||
|
||||
Bool = 0x2,
|
||||
True = 0x4 | Bool,
|
||||
False = 0x8 | Bool,
|
||||
|
||||
String = 0x10,
|
||||
|
||||
Number = 0x20,
|
||||
Integral = 0x40 | Number,
|
||||
Int32 = 0x80 | Integral,
|
||||
Int64 = 0x100 | Integral,
|
||||
|
||||
Floating = 0x200 | Number,
|
||||
Float = 0x400 | Floating,
|
||||
Double = 0x800 | Floating,
|
||||
|
||||
Array = 0x1000,
|
||||
|
||||
type_mask = 0xFFF
|
||||
};
|
||||
|
||||
Property(Flags flags) : flags(flags) {}
|
||||
|
||||
Property(const Property&) = default;
|
||||
|
||||
template <class T>
|
||||
T* is()
|
||||
{
|
||||
return underlying_cast(flags) & T::type;
|
||||
}
|
||||
|
||||
Property() = default;
|
||||
virtual ~Property() = default;
|
||||
|
||||
virtual void dump(std::string& buffer) = 0;
|
||||
|
||||
template <class T>
|
||||
T* as()
|
||||
{
|
||||
// return dynamic_cast<T*>(this);
|
||||
|
||||
// http://stackoverflow.com/questions/579887/how-expensive-is-rtti
|
||||
// so... typeid is 20x faster! but there are some caveats, use with
|
||||
// caution. read CAREFULLY what those people are saying.
|
||||
// should be ok to use in this situation because all types used by
|
||||
// this comparison are local and compile together with this code
|
||||
// and we're compiling it only for linux with gcc/clang and we will
|
||||
// not use any classes from third party libraries in this function.
|
||||
if(typeid(T*) == typeid(this))
|
||||
if(this->is<T>())
|
||||
return static_cast<T*>(this);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
void accept(Handler& handler);
|
||||
|
||||
Flags flags;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Value : public Property
|
||||
struct Null : public Property
|
||||
{
|
||||
public:
|
||||
Value(T value) : value(value) {}
|
||||
T value;
|
||||
static constexpr Flags type = Flags::Null;
|
||||
|
||||
Null() : Property(Flags::Null) {}
|
||||
|
||||
bool is_null()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct Bool : public Property
|
||||
{
|
||||
static constexpr Flags type = Flags::Bool;
|
||||
|
||||
Bool(bool value) : Property(value ? Flags::True : Flags::False) {}
|
||||
|
||||
bool value()
|
||||
{
|
||||
unsigned flags = underlying_cast(this->flags);
|
||||
unsigned true_t = underlying_cast(Flags::True);
|
||||
|
||||
return (flags - true_t) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct String : public Property
|
||||
{
|
||||
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) {}
|
||||
|
||||
std::string 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;
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
void Property::accept(Handler& h)
|
||||
{
|
||||
switch(flags)
|
||||
{
|
||||
case Flags::Null: return h.handle(static_cast<Null&>(*this));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef MEMGRAPH_STORAGE_MODEL_PROPERTIES_STRING_HPP
|
||||
#define MEMGRAPH_STORAGE_MODEL_PROPERTIES_STRING_HPP
|
||||
|
||||
#include "property.hpp"
|
||||
|
||||
namespace model
|
||||
{
|
||||
|
||||
class String : public Value<std::string>
|
||||
{
|
||||
public:
|
||||
using Value::Value;
|
||||
|
||||
void dump(std::string& buffer) override
|
||||
{
|
||||
buffer += '"'; buffer += value; buffer += '"';
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
12
utils/underlying_cast.hpp
Normal file
12
utils/underlying_cast.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef MEMGRAPH_UTILS_UNDERLYING_CAST_HPP
|
||||
#define MEMGRAPH_UTILS_UNDERLYING_CAST_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::underlying_type<T>::type underlying_cast(T e) {
|
||||
return static_cast<typename std::underlying_type<T>::type>(e);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user