Skip to content

Commit

Permalink
Overhaul some parts of serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Sep 4, 2015
1 parent 85f3c61 commit 491e9c1
Show file tree
Hide file tree
Showing 23 changed files with 657 additions and 463 deletions.
18 changes: 15 additions & 3 deletions base/lib/iscore/serialization/DataStreamVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Visitor<Reader<DataStream>> : public AbstractVisitor
readFrom(obj.id());
}

template<typename T>
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
void readFrom(const T&);

template<typename T>
Expand All @@ -99,6 +99,12 @@ class Visitor<Reader<DataStream>> : public AbstractVisitor
template<typename... Args>
void readFrom(const eggs::variants::variant<Args...>&);

template<typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
void readFrom(const T& elt)
{
m_stream << (int32_t) elt;
}

/**
* @brief insertDelimiter
*
Expand Down Expand Up @@ -162,7 +168,7 @@ class Visitor<Writer<DataStream>> : public AbstractVisitor
obj.setId(std::move(id));
}

template<typename T>
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
void writeTo(T&);

template<typename T>
Expand All @@ -173,7 +179,13 @@ class Visitor<Writer<DataStream>> : public AbstractVisitor
template<typename... Args>
void writeTo(eggs::variants::variant<Args...>&);


template<typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
void writeTo(T& elt)
{
int32_t e;
m_stream >> e;
elt = static_cast<T>(e);
}

/**
* @brief checkDelimiter
Expand Down
17 changes: 15 additions & 2 deletions base/lib/iscore/serialization/JSONValueVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QVector>
#include <QMap>


template<typename T>
T fromJsonObject(QJsonValue&& json);

Expand Down Expand Up @@ -36,9 +37,15 @@ class Visitor<Reader<JSONValue>> : public AbstractVisitor

VisitorVariant toVariant() { return {*this, JSONValue::type()}; }

template<typename T>
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
void readFrom(const T&);

template<typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
void readFrom(const T& elt)
{
val = (int32_t) elt;
}

template<typename T>
void readFrom(const Id<T>& obj)
{
Expand Down Expand Up @@ -66,9 +73,15 @@ class Visitor<Writer<JSONValue>> : public AbstractVisitor
Visitor<Writer<JSONValue>> (QJsonValue&& obj) :
val{std::move(obj) } {}

template<typename T>
template<typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
void writeTo(T&);

template<typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
void writeTo(T& elt)
{
elt = static_cast<T>(val.toInt());
}

template<typename T>
void writeTo(Id<T>& obj)
{
Expand Down
22 changes: 22 additions & 0 deletions base/lib/iscore/serialization/VisitorInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,25 @@ using enable_if_deserializer = typename std::enable_if_t<std::decay<Deserializer
#define ISCORE_SERIALIZE_FRIENDS(Type, Serializer) \
friend void Visitor<Reader< Serializer >>::readFrom< Type > (const Type &); \
friend void Visitor<Writer< Serializer >>::writeTo< Type > (Type &);


// Inherit from this to have
// the type treated as a value in the serialization context. Useful
// for choice between JSONObject / JSONValue
template<typename T>
struct is_value_tag {
static const constexpr bool value = false;
};
#define ISCORE_DECL_VALUE_TYPE(Type) \
template<> struct is_value_tag<Type> { static const constexpr bool value = true; };

template<typename T>
struct is_value_t
{
static const constexpr bool value{
std::is_arithmetic<T>::value
|| std::is_enum<T>::value
|| is_value_tag<T>::value
};
};

45 changes: 42 additions & 3 deletions base/lib/iscore/tools/VariantBasedNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,31 @@ void Visitor<Writer<DataStream>>::writeTo(eggs::variant<Args...>& var)
template<typename T>
class TypeToName;

// This part is required because it isn't as straightforward to save variant data
// in JSON as it is to save it in a DataStream.
// Basically, each variant member has an associated name that will be the
// key in the JSON parent object. This name is defined by specializing
// template<> class TypeToName<T>.
// For instance:
// template<> class TypeToName<iscore::Address>
// { public: static constexpr const char * name() { return "Address"; } };

// This allows easy store and retrieval under a familiar name



// The _eggs_impl functions are because enum's don't need full-fledged objects in json.
template<typename T, std::enable_if_t<!is_value_t<T>::value>* = nullptr>
QJsonValue readFrom_eggs_impl(const T& res)
{
return toJsonObject(res);
}
template<typename T, std::enable_if_t<is_value_t<T>::value>* = nullptr>
QJsonValue readFrom_eggs_impl(const T& res)
{
return toJsonValue(res);
}

template<typename... Args>
void Visitor<Reader<JSONObject>>::readFrom(const eggs::variant<Args...>& var)
{
Expand All @@ -139,13 +164,27 @@ void Visitor<Reader<JSONObject>>::readFrom(const eggs::variant<Args...>& var)

if(auto res = var.template target<current_type>())
{
this->m_obj[TypeToName<current_type>::name()] = toJsonObject(*res);
this->m_obj[TypeToName<current_type>::name()] = readFrom_eggs_impl(*res);
done = true;
}
});
}
}

/**
* These two methods are because enum's don't need full-fledged objects.
*/
template<typename T, std::enable_if_t<!is_value_t<T>::value>* = nullptr>
auto writeTo_eggs_impl(const QJsonValue& res)
{
return fromJsonObject<T>(res.toObject());
}
template<typename T, std::enable_if_t<is_value_t<T>::value>* = nullptr>
auto writeTo_eggs_impl(const QJsonValue& res)
{
return fromJsonValue<T>(res);
}

template<typename... Args>
void Visitor<Writer<JSONObject>>::writeTo(eggs::variant<Args...>& var)
{
Expand All @@ -158,8 +197,8 @@ void Visitor<Writer<JSONObject>>::writeTo(eggs::variant<Args...>& var)

if(m_obj.contains(TypeToName<current_type>::name()))
{
typename std::remove_reference<decltype(elt)>::type data;
fromJsonObject(m_obj[TypeToName<current_type>::name()].toObject(), data);
current_type data = writeTo_eggs_impl<current_type>(m_obj[TypeToName<current_type>::name()]);

var = data;
done = true;
}
Expand Down
4 changes: 4 additions & 0 deletions base/plugins/iscore-lib-state/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
set(SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/State/AddressSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/ValueSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/RelationSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/MessageSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/DynamicStateSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/StateSerialization.cpp"

"${CMAKE_CURRENT_SOURCE_DIR}/State/Address.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/Value.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/Relation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/Expression.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/ExpressionParser.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/ExpressionSerialization.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/State/StateItemModel.cpp"

"${CMAKE_CURRENT_SOURCE_DIR}/State/Widgets/AddressLineEdit.cpp"
Expand Down
Loading

0 comments on commit 491e9c1

Please sign in to comment.