diff --git a/base/lib/iscore/serialization/DataStreamVisitor.hpp b/base/lib/iscore/serialization/DataStreamVisitor.hpp index 02fa31937d..72593865e5 100644 --- a/base/lib/iscore/serialization/DataStreamVisitor.hpp +++ b/base/lib/iscore/serialization/DataStreamVisitor.hpp @@ -88,7 +88,7 @@ class Visitor> : public AbstractVisitor readFrom(obj.id()); } - template + template::value>* = nullptr> void readFrom(const T&); template @@ -99,6 +99,12 @@ class Visitor> : public AbstractVisitor template void readFrom(const eggs::variants::variant&); + template::value>* = nullptr> + void readFrom(const T& elt) + { + m_stream << (int32_t) elt; + } + /** * @brief insertDelimiter * @@ -162,7 +168,7 @@ class Visitor> : public AbstractVisitor obj.setId(std::move(id)); } - template + template::value>* = nullptr> void writeTo(T&); template @@ -173,7 +179,13 @@ class Visitor> : public AbstractVisitor template void writeTo(eggs::variants::variant&); - + template::value>* = nullptr> + void writeTo(T& elt) + { + int32_t e; + m_stream >> e; + elt = static_cast(e); + } /** * @brief checkDelimiter diff --git a/base/lib/iscore/serialization/JSONValueVisitor.hpp b/base/lib/iscore/serialization/JSONValueVisitor.hpp index 4e7cdca7ab..1a7d7c8859 100644 --- a/base/lib/iscore/serialization/JSONValueVisitor.hpp +++ b/base/lib/iscore/serialization/JSONValueVisitor.hpp @@ -6,6 +6,7 @@ #include #include + template T fromJsonObject(QJsonValue&& json); @@ -36,9 +37,15 @@ class Visitor> : public AbstractVisitor VisitorVariant toVariant() { return {*this, JSONValue::type()}; } - template + template::value>* = nullptr> void readFrom(const T&); + template::value>* = nullptr> + void readFrom(const T& elt) + { + val = (int32_t) elt; + } + template void readFrom(const Id& obj) { @@ -66,9 +73,15 @@ class Visitor> : public AbstractVisitor Visitor> (QJsonValue&& obj) : val{std::move(obj) } {} - template + template::value>* = nullptr> void writeTo(T&); + template::value>* = nullptr> + void writeTo(T& elt) + { + elt = static_cast(val.toInt()); + } + template void writeTo(Id& obj) { diff --git a/base/lib/iscore/serialization/VisitorInterface.hpp b/base/lib/iscore/serialization/VisitorInterface.hpp index bc9f44c453..8ca7e55fe5 100644 --- a/base/lib/iscore/serialization/VisitorInterface.hpp +++ b/base/lib/iscore/serialization/VisitorInterface.hpp @@ -59,3 +59,25 @@ using enable_if_deserializer = typename std::enable_if_t>::readFrom< Type > (const Type &); \ friend void Visitor>::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 +struct is_value_tag { + static const constexpr bool value = false; +}; +#define ISCORE_DECL_VALUE_TYPE(Type) \ + template<> struct is_value_tag { static const constexpr bool value = true; }; + +template +struct is_value_t +{ + static const constexpr bool value{ + std::is_arithmetic::value + || std::is_enum::value + || is_value_tag::value + }; +}; + diff --git a/base/lib/iscore/tools/VariantBasedNode.hpp b/base/lib/iscore/tools/VariantBasedNode.hpp index 93555ccc5d..caf6eb23c7 100644 --- a/base/lib/iscore/tools/VariantBasedNode.hpp +++ b/base/lib/iscore/tools/VariantBasedNode.hpp @@ -124,6 +124,31 @@ void Visitor>::writeTo(eggs::variant& var) template 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. +// For instance: +// template<> class TypeToName +// { 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::value>* = nullptr> +QJsonValue readFrom_eggs_impl(const T& res) +{ + return toJsonObject(res); +} +template::value>* = nullptr> +QJsonValue readFrom_eggs_impl(const T& res) +{ + return toJsonValue(res); +} + template void Visitor>::readFrom(const eggs::variant& var) { @@ -139,13 +164,27 @@ void Visitor>::readFrom(const eggs::variant& var) if(auto res = var.template target()) { - this->m_obj[TypeToName::name()] = toJsonObject(*res); + this->m_obj[TypeToName::name()] = readFrom_eggs_impl(*res); done = true; } }); } } +/** + * These two methods are because enum's don't need full-fledged objects. + */ +template::value>* = nullptr> +auto writeTo_eggs_impl(const QJsonValue& res) +{ + return fromJsonObject(res.toObject()); +} +template::value>* = nullptr> +auto writeTo_eggs_impl(const QJsonValue& res) +{ + return fromJsonValue(res); +} + template void Visitor>::writeTo(eggs::variant& var) { @@ -158,8 +197,8 @@ void Visitor>::writeTo(eggs::variant& var) if(m_obj.contains(TypeToName::name())) { - typename std::remove_reference::type data; - fromJsonObject(m_obj[TypeToName::name()].toObject(), data); + current_type data = writeTo_eggs_impl(m_obj[TypeToName::name()]); + var = data; done = true; } diff --git a/base/plugins/iscore-lib-state/CMakeLists.txt b/base/plugins/iscore-lib-state/CMakeLists.txt index 692407e828..756ec1ff60 100644 --- a/base/plugins/iscore-lib-state/CMakeLists.txt +++ b/base/plugins/iscore-lib-state/CMakeLists.txt @@ -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" diff --git a/base/plugins/iscore-lib-state/State/Expression.cpp b/base/plugins/iscore-lib-state/State/Expression.cpp index 9c32422a5a..72da937299 100644 --- a/base/plugins/iscore-lib-state/State/Expression.cpp +++ b/base/plugins/iscore-lib-state/State/Expression.cpp @@ -1,315 +1,5 @@ #include "Expression.hpp" #include -/* -bool checkLeaves(const iscore::Expression* e) -{ - auto c = e->children(); // TODO see why this isn't a const ref return. - if(c.isEmpty()) - { - return e->is(); - } - else - { - return std::all_of( - c.cbegin(), c.cend(), - [] (auto e) { - return checkLeaves(e); - }); - } -} - -bool validate(const iscore::Expression& expr) -{ - // Check that all the leaves are relations. - return checkLeaves(&expr); -} -*/ -/* -void test_parse_addr() -{ - using namespace qi; - - - const QStringList rels{"==", "!=", ">", "<", ">=", "<="}; - - - - std::string str("minuit:/device/lol"); - - typedef std::string::const_iterator iterator_type; - using qi::parse; - using ascii::space; - - address_parser parser; - auto first = str.cbegin(), last = str.cend(); - iscore::Address addr; - bool r = parse(first, last, parser, addr); - - qDebug() << "parsed?" << r; - qDebug() << addr.device; - for(auto& elt : addr.path) - qDebug() << elt; - //if (first!=last) std::cerr << "unparsed: '" << std::string(first, last) << "'\n"; -} - -void test_parse_value() -{ - std::vector str_list{ - "[1,2,3]", - "[1]", - "[ 1 ]", - "[ 1, 2, 3 ]", - "[ 1, 2.3, 3, 'c' ]", - "1", - "1.23", - "'c'", - "\"lala\"", - "\"lala lala\"" - }; - - for(const auto& str : str_list) - { - - typedef std::string::const_iterator iterator_type; - using qi::parse; - - value_parser parser; - auto first = str.cbegin(), last = str.cend(); - iscore::Value val; - bool r = parse(first, last, parser, val); - - qDebug() << str.c_str() << r << val.val << " "; - } -} - - -void test_parse_rel_member() -{ - std::vector str_list{ - "minuit:/device" - "1234" - }; - - for(const auto& str : str_list) - { - typedef std::string::const_iterator iterator_type; - using qi::parse; - - RelationMember_parser parser; - auto first = str.cbegin(), last = str.cend(); - iscore::RelationMember val; - bool r = parse(first, last, parser, val); - - qDebug() << str.c_str() << r << val.which(); - } -} - -void test_parse_rel() -{ - std::vector str_list{ - "minuit:/device<=1234", - "minuit:/device <= 1234" - }; - - for(const auto& str : str_list) - { - typedef std::string::const_iterator iterator_type; - using qi::parse; - - Relation_parser parser; - auto first = str.cbegin(), last = str.cend(); - iscore::Relation val; - bool r = parse(first, last, parser, val); - - qDebug() << str.c_str() << r << val.lhs.target()->path << val.rhs.target()->val << " "; - } -} - - -void test_parse_expr() -{ - for (auto& input : std::list { - "(dev:/minuit <= 5) and (a:/b == 1.34);", - "(dev:/minuit != [1, 2, 3.12, 'c']) and not (a:/b >= c:/d/e/f);" - }) - { - auto f(std::begin(input)), l(std::end(input)); - parser p; - - try - { - expr result; - bool ok = qi::phrase_parse(f,l,p > ';',qi::space,result); - - if (!ok) - qDebug() << "invalid input\n"; - //else - // qDebug() << "result: " << result << "\n"; - - } catch (const qi::expectation_failure& e) - { - qDebug() << "expectation_failure at '" << QString::fromStdString(std::string(e.first, e.last)) << "'\n"; - } - - if (f!=l) qDebug() << "unparsed: '" << QString::fromStdString(std::string(f,l)) << "'\n"; - } - - exit(0); -} -void expr_parse_test() -{ - test_parse_addr(); - test_parse_value(); - - test_parse_rel_member(); - test_parse_rel(); - test_parse_expr(); -} - -QDebug operator<<(QDebug dbg, const iscore::Address& a) -{ - dbg << a.toString() - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::Value& v) -{ - dbg << v.val; - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::RelationMember& v) -{ - using namespace eggs::variants; - switch(v.which()) - { - case 0: - dbg << get(v); - break; - case 1: - dbg << get(v); - break; - } - - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::Relation::Operator& v) -{ - switch(v) - { - case iscore::Relation::Operator::Different: - dbg << "!="; break; - case iscore::Relation::Operator::Equal: - dbg << "=="; break; - case iscore::Relation::Operator::Greater: - dbg << ">"; break; - case iscore::Relation::Operator::GreaterEqual: - dbg << ">="; break; - case iscore::Relation::Operator::Lower: - dbg << "<"; break; - case iscore::Relation::Operator::LowerEqual: - dbg << "<="; break; - } - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::Relation& v) -{ - dbg << v.lhs << v.op << v.rhs; - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::BinaryOperator& v) -{ - switch(v) - { - case iscore::BinaryOperator::And: - dbg << "and"; break; - case iscore::BinaryOperator::Or: - dbg << "or"; break; - case iscore::BinaryOperator::Xor: - dbg << "xor"; break; - } - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::UnaryOperator& v) -{ - switch(v) - { - case iscore::UnaryOperator::Not: - dbg << "not"; break; - } - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::ExprData& v) -{ - if(v.is()) - dbg << v.get(); - else if(v.is()) - dbg << v.get(); - else if(v.is()) - dbg << v.get(); - - return dbg; -} - -QDebug operator<<(QDebug dbg, const iscore::Expression& v) -{ - dbg << "("; - dbg << static_cast(v); - for(auto& child : v.children()) - { - dbg << *child; - } - dbg << ")"; - return dbg; -} - - -void test_parse_expr_full() -{ - for (auto& input : std::list { - "(dev:/minuit != [1, 2, 3.12, 'c']) and not (a:/b >= c:/d/e/f);" -}) - { - auto f(std::begin(input)), l(std::end(input)); - Expression_parser p; - - try - { - expr result; - bool ok = qi::phrase_parse(f,l,p > ';',qi::space,result); - - if (!ok) - { - qDebug() << "invalid input\n"; - return; - } - - iscore::Expression e; - - Expression_builder bldr{&e}; - boost::apply_visitor(bldr, result); - qDebug() << e; - - } - catch (const qi::expectation_failure& e) - { - //std::cerr << "expectation_failure at '" << std::string(e.first, e.last) << "'\n"; - } - - //if (f!=l) std::cerr << "unparsed: '" << std::string(f,l) << "'\n"; - } - - //return 0; -} - -*/ - - TreeNode::TreeNode(): ExprData{} @@ -480,83 +170,3 @@ QString TreeNode::toString() const return s; } - -namespace -{ - -QString valueToString(const QVariant& val) -{ - switch(val.type()) - { - case QMetaType::QVariantList: - { - QString s; - s += "[ "; - for(const auto& v : val.value()) - { - s += valueToString(v) + ", "; - } - s += " ]"; - return s; - } - case QMetaType::QChar: - { - return "'" + val.toString() + "'"; - } - case QMetaType::QString: - { - return "\"" + val.toString() + "\""; - } - default: - { - return val.toString(); - } - } -} -} -QString iscore::Relation::toString() const -{ - using namespace eggs::variants; - static const auto relMemberToString = [] (const auto& m) -> QString - { - switch(m.which()) - { - case 0: - return get(m).toString(); - break; - case 1: - { - return valueToString(get(m).val); - break; - } - default: - return "ERROR"; - } - }; - - static const auto opToString = [] (const auto& op) -> QString - { - switch(op) - { - case iscore::Relation::Operator::Different: - return "!="; - case iscore::Relation::Operator::Equal: - return "=="; - case iscore::Relation::Operator::Greater: - return ">"; - case iscore::Relation::Operator::GreaterEqual: - return ">="; - case iscore::Relation::Operator::Lower: - return "<"; - case iscore::Relation::Operator::LowerEqual: - return "<="; - default: - return "ERROR"; - } - }; - - return QString("%1 %2 %3") - .arg(relMemberToString(lhs)) - .arg(opToString(op)) - .arg(relMemberToString(rhs)); -} diff --git a/base/plugins/iscore-lib-state/State/Expression.hpp b/base/plugins/iscore-lib-state/State/Expression.hpp index 1e5c57a282..60b1b9562e 100644 --- a/base/plugins/iscore-lib-state/State/Expression.hpp +++ b/base/plugins/iscore-lib-state/State/Expression.hpp @@ -1,38 +1,10 @@ #pragma once -#include -#include -#include -#include +#include #include #include #include namespace iscore { -using RelationMember = eggs::variant; - -struct Relation -{ - enum Operator { - Equal, - Different, - Greater, - Lower, - GreaterEqual, - LowerEqual - } ; - - RelationMember lhs; - Operator op; - RelationMember rhs; - - friend bool operator==(const Relation& lhs, const Relation& rhs) - { - return lhs.lhs == rhs.lhs && lhs.rhs == rhs.rhs && lhs.op == rhs.op; - } - - QString toString() const; -}; - enum class BinaryOperator { And, Or, Xor }; @@ -42,6 +14,9 @@ enum class UnaryOperator { struct ExprData : public VariantBasedNode { + ISCORE_SERIALIZE_FRIENDS(ExprData, DataStream) + ISCORE_SERIALIZE_FRIENDS(ExprData, JSONObject) + ExprData() = default; template ExprData(const T& data): diff --git a/base/plugins/iscore-lib-state/State/ExpressionSerialization.cpp b/base/plugins/iscore-lib-state/State/ExpressionSerialization.cpp new file mode 100644 index 0000000000..ce1fa6537d --- /dev/null +++ b/base/plugins/iscore-lib-state/State/ExpressionSerialization.cpp @@ -0,0 +1,85 @@ +#include "Expression.hpp" +#include +#include + +#include "Relation.hpp" + +template<> +void Visitor>::readFrom(const iscore::Relation& rel) +{ + m_stream << rel.lhs + << rel.op + << rel.rhs; + + insertDelimiter(); +} + +template<> +void Visitor>::readFrom(const iscore::Relation& rel) +{ + // TODO harmonize from... with marshall(..) in VisitorCommon.hpp + m_obj["LHS"] = toJsonObject(rel.lhs); + m_obj["Op"] = toJsonValue(rel.op); + m_obj["RHS"] = toJsonObject(rel.rhs); +} + +template<> +void Visitor>::writeTo(iscore::Relation& rel) +{ + m_stream >> rel.lhs + >> rel.op + >> rel.rhs; + + checkDelimiter(); +} + +template<> +void Visitor>::writeTo(iscore::Relation& rel) +{ + fromJsonObject(m_obj["LHS"].toObject(), rel.lhs); + fromJsonObject(m_obj["RHS"].toObject(), rel.rhs); + fromJsonValue(m_obj["Op"], rel.op); +} + +template<> class TypeToName +{ public: static constexpr const char * name() { return "Address"; } }; + +template<> class TypeToName +{ public: static constexpr const char * name() { return "Value"; } }; + +template<> class TypeToName +{ public: static constexpr const char * name() { return "Relation"; } }; + +template<> class TypeToName +{ public: static constexpr const char * name() { return "BinOp"; } }; + +template<> class TypeToName +{ public: static constexpr const char * name() { return "UnOp"; } }; + + +template<> +void Visitor>::readFrom(const ExprData& state) +{ + readFrom(state.m_data); + insertDelimiter(); +} + +template<> +void Visitor>::readFrom(const ExprData& state) +{ + readFrom(state.m_data); +} + +template<> +void Visitor>::writeTo(ExprData& state) +{ + writeTo(state.m_data); + checkDelimiter(); +} + +template<> +void Visitor>::writeTo(ExprData& state) +{ + writeTo(state.m_data); +} + diff --git a/base/plugins/iscore-lib-state/State/Relation.cpp b/base/plugins/iscore-lib-state/State/Relation.cpp new file mode 100644 index 0000000000..4b1daf3551 --- /dev/null +++ b/base/plugins/iscore-lib-state/State/Relation.cpp @@ -0,0 +1,35 @@ +#include "Relation.hpp" + + +QString iscore::Relation::toString() const +{ + using namespace eggs::variants; + static const auto relMemberToString = [] (const auto& m) -> QString + { + switch(m.which()) + { + case 0: + return get(m).toString(); + case 1: + return get(m).toString(); + default: + return "ERROR"; + } + }; + + // todo boost.bimap + static const QMap opToString + { + {iscore::Relation::Operator::LowerEqual, "<="}, + {iscore::Relation::Operator::GreaterEqual, ">="}, + {iscore::Relation::Operator::Lower, "<"}, + {iscore::Relation::Operator::Greater, ">"}, + {iscore::Relation::Operator::Different, "!="}, + {iscore::Relation::Operator::Equal, "=="} + }; + + return QString("%1 %2 %3") + .arg(relMemberToString(lhs)) + .arg(opToString[op]) + .arg(relMemberToString(rhs)); +} diff --git a/base/plugins/iscore-lib-state/State/Relation.hpp b/base/plugins/iscore-lib-state/State/Relation.hpp new file mode 100644 index 0000000000..f47f48ba44 --- /dev/null +++ b/base/plugins/iscore-lib-state/State/Relation.hpp @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include + +namespace iscore +{ +using RelationMember = eggs::variant; + +struct Relation +{ + enum Operator { + Equal, + Different, + Greater, + Lower, + GreaterEqual, + LowerEqual + } ; + + RelationMember lhs; + Operator op; + RelationMember rhs; + + friend bool operator==(const Relation& lhs, const Relation& rhs) + { + return lhs.lhs == rhs.lhs && lhs.rhs == rhs.rhs && lhs.op == rhs.op; + } + + QString toString() const; +}; +} diff --git a/base/plugins/iscore-lib-state/State/RelationSerialization.cpp b/base/plugins/iscore-lib-state/State/RelationSerialization.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/base/plugins/iscore-lib-state/State/Value.cpp b/base/plugins/iscore-lib-state/State/Value.cpp new file mode 100644 index 0000000000..7b209ab2c7 --- /dev/null +++ b/base/plugins/iscore-lib-state/State/Value.cpp @@ -0,0 +1,39 @@ +#include "Value.hpp" + +namespace +{ +QString valueToString(const QVariant& val) +{ + switch(val.type()) + { + case QMetaType::QVariantList: + { + QString s; + s += "[ "; + for(const auto& v : val.value()) + { + s += valueToString(v) + ", "; + } + s += " ]"; + return s; + } + case QMetaType::QChar: + { + return "'" + val.toString() + "'"; + } + case QMetaType::QString: + { + return "\"" + val.toString() + "\""; + } + default: + { + return val.toString(); + } + } +} +} + +QString iscore::Value::toString() const +{ + return valueToString(val); +} diff --git a/base/plugins/iscore-lib-state/State/Value.hpp b/base/plugins/iscore-lib-state/State/Value.hpp index 95319205ed..74714f6fa4 100644 --- a/base/plugins/iscore-lib-state/State/Value.hpp +++ b/base/plugins/iscore-lib-state/State/Value.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include namespace iscore { @@ -54,6 +55,7 @@ struct Value return false; } + QString toString() const; /* template auto map(Fun&& f) { diff --git a/base/plugins/iscore-lib-state/State/ValueSerialization.cpp b/base/plugins/iscore-lib-state/State/ValueSerialization.cpp index 48c38e724c..d9b2903afb 100644 --- a/base/plugins/iscore-lib-state/State/ValueSerialization.cpp +++ b/base/plugins/iscore-lib-state/State/ValueSerialization.cpp @@ -177,3 +177,24 @@ iscore::Value JsonToValue(const QJsonValue &val, QMetaType::Type t) } +template<> +void Visitor>::readFrom(const iscore::Value& val) +{ + auto type = val.val.typeName(); + if(type) + { + m_obj["Type"] = QString::fromStdString(type); + m_obj["Value"] = ValueToJson(val); + } +} + +template<> +void Visitor>::writeTo(iscore::Value& val) +{ + if(m_obj.contains("Type")) + { + auto valueType = static_cast(QMetaType::type(m_obj["Type"].toString().toLatin1())); + val = JsonToValue(m_obj["Value"], valueType); + } +} + diff --git a/base/plugins/iscore-lib-state/Tests/ExpressionParsingTests.cpp b/base/plugins/iscore-lib-state/Tests/ExpressionParsingTests.cpp new file mode 100644 index 0000000000..184d9e6b9e --- /dev/null +++ b/base/plugins/iscore-lib-state/Tests/ExpressionParsingTests.cpp @@ -0,0 +1,309 @@ + +/* +bool checkLeaves(const iscore::Expression* e) +{ + auto c = e->children(); // TODO see why this isn't a const ref return. + if(c.isEmpty()) + { + return e->is(); + } + else + { + return std::all_of( + c.cbegin(), c.cend(), + [] (auto e) { + return checkLeaves(e); + }); + } +} + +bool validate(const iscore::Expression& expr) +{ + // Check that all the leaves are relations. + return checkLeaves(&expr); +} +*/ +/* +void test_parse_addr() +{ + using namespace qi; + + + const QStringList rels{"==", "!=", ">", "<", ">=", "<="}; + + + + std::string str("minuit:/device/lol"); + + typedef std::string::const_iterator iterator_type; + using qi::parse; + using ascii::space; + + address_parser parser; + auto first = str.cbegin(), last = str.cend(); + iscore::Address addr; + bool r = parse(first, last, parser, addr); + + qDebug() << "parsed?" << r; + qDebug() << addr.device; + for(auto& elt : addr.path) + qDebug() << elt; + //if (first!=last) std::cerr << "unparsed: '" << std::string(first, last) << "'\n"; +} + +void test_parse_value() +{ + std::vector str_list{ + "[1,2,3]", + "[1]", + "[ 1 ]", + "[ 1, 2, 3 ]", + "[ 1, 2.3, 3, 'c' ]", + "1", + "1.23", + "'c'", + "\"lala\"", + "\"lala lala\"" + }; + + for(const auto& str : str_list) + { + + typedef std::string::const_iterator iterator_type; + using qi::parse; + + value_parser parser; + auto first = str.cbegin(), last = str.cend(); + iscore::Value val; + bool r = parse(first, last, parser, val); + + qDebug() << str.c_str() << r << val.val << " "; + } +} + + +void test_parse_rel_member() +{ + std::vector str_list{ + "minuit:/device" + "1234" + }; + + for(const auto& str : str_list) + { + typedef std::string::const_iterator iterator_type; + using qi::parse; + + RelationMember_parser parser; + auto first = str.cbegin(), last = str.cend(); + iscore::RelationMember val; + bool r = parse(first, last, parser, val); + + qDebug() << str.c_str() << r << val.which(); + } +} + +void test_parse_rel() +{ + std::vector str_list{ + "minuit:/device<=1234", + "minuit:/device <= 1234" + }; + + for(const auto& str : str_list) + { + typedef std::string::const_iterator iterator_type; + using qi::parse; + + Relation_parser parser; + auto first = str.cbegin(), last = str.cend(); + iscore::Relation val; + bool r = parse(first, last, parser, val); + + qDebug() << str.c_str() << r << val.lhs.target()->path << val.rhs.target()->val << " "; + } +} + + +void test_parse_expr() +{ + for (auto& input : std::list { + "(dev:/minuit <= 5) and (a:/b == 1.34);", + "(dev:/minuit != [1, 2, 3.12, 'c']) and not (a:/b >= c:/d/e/f);" + }) + { + auto f(std::begin(input)), l(std::end(input)); + parser p; + + try + { + expr result; + bool ok = qi::phrase_parse(f,l,p > ';',qi::space,result); + + if (!ok) + qDebug() << "invalid input\n"; + //else + // qDebug() << "result: " << result << "\n"; + + } catch (const qi::expectation_failure& e) + { + qDebug() << "expectation_failure at '" << QString::fromStdString(std::string(e.first, e.last)) << "'\n"; + } + + if (f!=l) qDebug() << "unparsed: '" << QString::fromStdString(std::string(f,l)) << "'\n"; + } + + exit(0); +} +void expr_parse_test() +{ + test_parse_addr(); + test_parse_value(); + + test_parse_rel_member(); + test_parse_rel(); + test_parse_expr(); +} + +QDebug operator<<(QDebug dbg, const iscore::Address& a) +{ + dbg << a.toString() + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::Value& v) +{ + dbg << v.val; + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::RelationMember& v) +{ + using namespace eggs::variants; + switch(v.which()) + { + case 0: + dbg << get(v); + break; + case 1: + dbg << get(v); + break; + } + + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::Relation::Operator& v) +{ + switch(v) + { + case iscore::Relation::Operator::Different: + dbg << "!="; break; + case iscore::Relation::Operator::Equal: + dbg << "=="; break; + case iscore::Relation::Operator::Greater: + dbg << ">"; break; + case iscore::Relation::Operator::GreaterEqual: + dbg << ">="; break; + case iscore::Relation::Operator::Lower: + dbg << "<"; break; + case iscore::Relation::Operator::LowerEqual: + dbg << "<="; break; + } + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::Relation& v) +{ + dbg << v.lhs << v.op << v.rhs; + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::BinaryOperator& v) +{ + switch(v) + { + case iscore::BinaryOperator::And: + dbg << "and"; break; + case iscore::BinaryOperator::Or: + dbg << "or"; break; + case iscore::BinaryOperator::Xor: + dbg << "xor"; break; + } + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::UnaryOperator& v) +{ + switch(v) + { + case iscore::UnaryOperator::Not: + dbg << "not"; break; + } + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::ExprData& v) +{ + if(v.is()) + dbg << v.get(); + else if(v.is()) + dbg << v.get(); + else if(v.is()) + dbg << v.get(); + + return dbg; +} + +QDebug operator<<(QDebug dbg, const iscore::Expression& v) +{ + dbg << "("; + dbg << static_cast(v); + for(auto& child : v.children()) + { + dbg << *child; + } + dbg << ")"; + return dbg; +} + + +void test_parse_expr_full() +{ + for (auto& input : std::list { + "(dev:/minuit != [1, 2, 3.12, 'c']) and not (a:/b >= c:/d/e/f);" +}) + { + auto f(std::begin(input)), l(std::end(input)); + Expression_parser p; + + try + { + expr result; + bool ok = qi::phrase_parse(f,l,p > ';',qi::space,result); + + if (!ok) + { + qDebug() << "invalid input\n"; + return; + } + + iscore::Expression e; + + Expression_builder bldr{&e}; + boost::apply_visitor(bldr, result); + qDebug() << e; + + } + catch (const qi::expectation_failure& e) + { + //std::cerr << "expectation_failure at '" << std::string(e.first, e.last) << "'\n"; + } + + //if (f!=l) std::cerr << "unparsed: '" << std::string(f,l) << "'\n"; + } + + //return 0; +} + +*/ diff --git a/base/plugins/iscore-plugin-deviceexplorer/DeviceExplorer/Address/AddressSettingsSerialization.cpp b/base/plugins/iscore-plugin-deviceexplorer/DeviceExplorer/Address/AddressSettingsSerialization.cpp index daa83228cb..7a76709fed 100644 --- a/base/plugins/iscore-plugin-deviceexplorer/DeviceExplorer/Address/AddressSettingsSerialization.cpp +++ b/base/plugins/iscore-plugin-deviceexplorer/DeviceExplorer/Address/AddressSettingsSerialization.cpp @@ -10,8 +10,8 @@ void Visitor>::readFrom(const iscore::AddressSettingsCommon& { m_stream << n.value << n.domain - << (int)n.ioType - << (int)n.clipMode + << n.ioType + << n.clipMode << n.unit << n.repetitionFilter << n.rate @@ -25,8 +25,8 @@ void Visitor>::writeTo(iscore::AddressSettingsCommon& n) { m_stream >> n.value >> n.domain - >> (int&)n.ioType - >> (int&)n.clipMode + >> n.ioType + >> n.clipMode >> n.unit >> n.repetitionFilter >> n.rate @@ -89,11 +89,10 @@ void Visitor>::readFrom(const iscore::AddressSettings& n) m_obj["Tags"] = arr; // Value, domain and type + readFrom(n.value); auto type = n.value.val.typeName(); if(type) { - m_obj["Type"] = QString::fromStdString(type); - m_obj["Value"] = ValueToJson(n.value); m_obj["Domain"] = DomainToJson(n.domain); } } @@ -116,10 +115,11 @@ void Visitor>::writeTo(iscore::AddressSettings& n) for(auto&& elt : arr) n.tags.append(elt.toString()); + writeTo(n.value); + // TODO doesn't handle multi-type variants. if(m_obj.contains("Type")) { auto valueType = static_cast(QMetaType::type(m_obj["Type"].toString().toLatin1())); - n.value = JsonToValue(m_obj["Value"], valueType); n.domain = JsonToDomain(m_obj["Domain"].toObject(), valueType); } } diff --git a/base/plugins/iscore-plugin-network/DistributedScenario/GroupManagerSerialization.cpp b/base/plugins/iscore-plugin-network/DistributedScenario/GroupManagerSerialization.cpp index 6d7c94cc9c..7cf0adea1e 100644 --- a/base/plugins/iscore-plugin-network/DistributedScenario/GroupManagerSerialization.cpp +++ b/base/plugins/iscore-plugin-network/DistributedScenario/GroupManagerSerialization.cpp @@ -9,7 +9,7 @@ void Visitor>::readFrom(const GroupManager& elt) { readFrom(static_cast&>(elt)); const auto& groups = elt.groups(); - m_stream << (int) groups.size(); + m_stream << (int32_t) groups.size(); for(const auto& group : groups) { readFrom(*group); @@ -21,9 +21,9 @@ void Visitor>::readFrom(const GroupManager& elt) template<> void Visitor>::writeTo(GroupManager& elt) { - int size; + int32_t size; m_stream >> size; - for(int i = size; i --> 0; ) + for(auto i = size; i --> 0; ) { elt.addGroup(new Group{*this, &elt}); } diff --git a/base/plugins/iscore-plugin-ossia/Protocols/MIDI/MIDISpecificSettingsSerialization.cpp b/base/plugins/iscore-plugin-ossia/Protocols/MIDI/MIDISpecificSettingsSerialization.cpp index 4d1cd8928c..a80a115400 100644 --- a/base/plugins/iscore-plugin-ossia/Protocols/MIDI/MIDISpecificSettingsSerialization.cpp +++ b/base/plugins/iscore-plugin-ossia/Protocols/MIDI/MIDISpecificSettingsSerialization.cpp @@ -6,27 +6,25 @@ template<> void Visitor>::readFrom(const MIDISpecificSettings& n) { - m_stream << static_cast(n.io) << n.endpoint; + m_stream << n.io << n.endpoint; insertDelimiter(); } template<> void Visitor>::writeTo(MIDISpecificSettings& n) { - int io; - m_stream >> io >> n.endpoint; - n.io = static_cast(io); + m_stream >> n.io >> n.endpoint; checkDelimiter(); } template<> void Visitor>::readFrom(const MIDISpecificSettings& n) { - m_obj["IO"] = static_cast(n.io); + m_obj["IO"] = toJsonValue(n.io); } template<> void Visitor>::writeTo(MIDISpecificSettings& n) { - n.io = static_cast(m_obj["IO"].toInt()); + fromJsonValue(m_obj["IO"], n.io); } diff --git a/base/plugins/iscore-plugin-scenario/source/Commands/Event/SetCondition.cpp b/base/plugins/iscore-plugin-scenario/source/Commands/Event/SetCondition.cpp index 1b07c566fb..2251f93908 100644 --- a/base/plugins/iscore-plugin-scenario/source/Commands/Event/SetCondition.cpp +++ b/base/plugins/iscore-plugin-scenario/source/Commands/Event/SetCondition.cpp @@ -34,12 +34,10 @@ void SetCondition::redo() void SetCondition::serializeImpl(QDataStream& s) const { - ISCORE_TODO; - // s << m_path << m_condition << m_previousCondition; + s << m_path << m_condition << m_previousCondition; } void SetCondition::deserializeImpl(QDataStream& s) { - ISCORE_TODO; - //s >> m_path >> m_condition >> m_previousCondition; + s >> m_path >> m_condition >> m_previousCondition; } diff --git a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/ConstraintModelSerialization.cpp b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/ConstraintModelSerialization.cpp index dcde3f1c30..6902050e7f 100644 --- a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/ConstraintModelSerialization.cpp +++ b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/ConstraintModelSerialization.cpp @@ -15,14 +15,14 @@ template<> void Visitor>::readFrom(const ConstraintModel& con readFrom(constraint.metadata); // Processes - m_stream << (int) constraint.processes.size(); + m_stream << (int32_t) constraint.processes.size(); for(const auto& process : constraint.processes) { readFrom(process); } // Rackes - m_stream << (int) constraint.racks.size(); + m_stream << (int32_t) constraint.racks.size(); for(const auto& rack : constraint.racks) { readFrom(rack); @@ -49,7 +49,7 @@ template<> void Visitor>::writeTo(ConstraintModel& constraint writeTo(constraint.metadata); // Processes - int process_count; + int32_t process_count; m_stream >> process_count; for(; process_count -- > 0;) @@ -58,7 +58,7 @@ template<> void Visitor>::writeTo(ConstraintModel& constraint } // Rackes - int rack_count; + int32_t rack_count; m_stream >> rack_count; for(; rack_count -- > 0;) diff --git a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/RackModelSerialization.cpp b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/RackModelSerialization.cpp index 3abb6c7566..8825d0818a 100644 --- a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/RackModelSerialization.cpp +++ b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/RackModelSerialization.cpp @@ -10,7 +10,7 @@ template<> void Visitor>::readFrom(const RackModel& rack) m_stream << rack.slotsPositions(); const auto& theSlots = rack.slotmodels; - m_stream << (int) theSlots.size(); + m_stream << (int32_t) theSlots.size(); for(const auto& slot : theSlots) { @@ -22,7 +22,7 @@ template<> void Visitor>::readFrom(const RackModel& rack) template<> void Visitor>::writeTo(RackModel& rack) { - int slots_size; + int32_t slots_size; QList> positions; m_stream >> positions; diff --git a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/Slot/SlotModelSerialization.cpp b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/Slot/SlotModelSerialization.cpp index 07e7c20cd6..9d03f595f2 100644 --- a/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/Slot/SlotModelSerialization.cpp +++ b/base/plugins/iscore-plugin-scenario/source/Document/Constraint/Rack/Slot/SlotModelSerialization.cpp @@ -12,7 +12,7 @@ template<> void Visitor>::readFrom(const SlotModel& slot) m_stream << slot.m_frontLayerModelId; const auto& lms = slot.layers; - m_stream << (int) lms.size(); + m_stream << (int32_t) lms.size(); for(const auto& lm : lms) { @@ -29,7 +29,7 @@ template<> void Visitor>::writeTo(SlotModel& slot) Id editedProcessId; m_stream >> editedProcessId; - int lm_size; + int32_t lm_size; m_stream >> lm_size; const auto& cstr = slot.parentConstraint(); diff --git a/base/plugins/iscore-plugin-scenario/source/Process/ScenarioModelSerialization.cpp b/base/plugins/iscore-plugin-scenario/source/Process/ScenarioModelSerialization.cpp index 0c8bc96af4..a15bac3270 100644 --- a/base/plugins/iscore-plugin-scenario/source/Process/ScenarioModelSerialization.cpp +++ b/base/plugins/iscore-plugin-scenario/source/Process/ScenarioModelSerialization.cpp @@ -17,7 +17,7 @@ void Visitor>::readFrom(const ScenarioModel& scenario) // Timenodes const auto& timenodes = scenario.timeNodes; - m_stream << (int) timenodes.size(); + m_stream << (int32_t) timenodes.size(); for(const auto& timenode : timenodes) { @@ -26,7 +26,7 @@ void Visitor>::readFrom(const ScenarioModel& scenario) // Events const auto& events = scenario.events; - m_stream << (int) events.size(); + m_stream << (int32_t) events.size(); for(const auto& event : events) { @@ -35,7 +35,7 @@ void Visitor>::readFrom(const ScenarioModel& scenario) // States const auto& states = scenario.states; - m_stream << (int) states.size(); + m_stream << (int32_t) states.size(); for(const auto& state : states) { @@ -44,7 +44,7 @@ void Visitor>::readFrom(const ScenarioModel& scenario) // Constraints const auto& constraints = scenario.constraints; - m_stream << (int) constraints.size(); + m_stream << (int32_t) constraints.size(); for(const auto& constraint : constraints) { @@ -67,7 +67,7 @@ void Visitor>::writeTo(ScenarioModel& scenario) >> scenario.m_endEventId; // Timenodes - int timenode_count; + int32_t timenode_count; m_stream >> timenode_count; for(; timenode_count -- > 0;) @@ -77,7 +77,7 @@ void Visitor>::writeTo(ScenarioModel& scenario) } // Events - int event_count; + int32_t event_count; m_stream >> event_count; for(; event_count -- > 0;) @@ -87,7 +87,7 @@ void Visitor>::writeTo(ScenarioModel& scenario) } // Events - int state_count; + int32_t state_count; m_stream >> state_count; for(; state_count -- > 0;) @@ -97,7 +97,7 @@ void Visitor>::writeTo(ScenarioModel& scenario) } // Constraints - int constraint_count; + int32_t constraint_count; m_stream >> constraint_count; for(; constraint_count -- > 0;)