/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include template <> struct std::less { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x < b.x && a.x < b.y; } }; template <> struct std::less { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x < b.x && a.x < b.y && a.z < b.z; } }; template <> struct std::less { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w; } }; template <> struct std::less { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x < b.x && a.x < b.y; } }; template <> struct std::less { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x < b.x && a.x < b.y && a.z < b.z; } }; template <> struct std::less { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w; } }; template <> struct std::less { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x < b.x && a.x < b.y; } }; template <> struct std::less { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x < b.x && a.x < b.y && a.z < b.z; } }; template <> struct std::less { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w; } }; template <> struct std::less_equal { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x <= b.x && a.x <= b.y; } }; template <> struct std::less_equal { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z; } }; template <> struct std::less_equal { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w; } }; template <> struct std::less_equal { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x <= b.x && a.x <= b.y; } }; template <> struct std::less_equal { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z; } }; template <> struct std::less_equal { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w; } }; template <> struct std::less_equal { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x <= b.x && a.x <= b.y; } }; template <> struct std::less_equal { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z; } }; template <> struct std::less_equal { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w; } }; template <> struct std::greater { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x > b.x && a.x > b.y; } }; template <> struct std::greater { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x > b.x && a.x > b.y && a.z > b.z; } }; template <> struct std::greater { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w; } }; template <> struct std::greater { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x > b.x && a.x > b.y; } }; template <> struct std::greater { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x > b.x && a.x > b.y && a.z > b.z; } }; template <> struct std::greater { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w; } }; template <> struct std::greater { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x > b.x && a.x > b.y; } }; template <> struct std::greater { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x > b.x && a.x > b.y && a.z > b.z; } }; template <> struct std::greater { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w; } }; template <> struct std::greater_equal { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x >= b.x && a.x >= b.y; } }; template <> struct std::greater_equal { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z; } }; template <> struct std::greater_equal { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w; } }; template <> struct std::greater_equal { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x >= b.x && a.x >= b.y; } }; template <> struct std::greater_equal { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z; } }; template <> struct std::greater_equal { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w; } }; template <> struct std::greater_equal { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x >= b.x && a.x >= b.y; } }; template <> struct std::greater_equal { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z; } }; template <> struct std::greater_equal { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w; } }; template <> struct std::equal_to { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x == b.x && a.x == b.y; } }; template <> struct std::equal_to { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x == b.x && a.x == b.y && a.z == b.z; } }; template <> struct std::equal_to { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w; } }; template <> struct std::equal_to { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x == b.x && a.x == b.y; } }; template <> struct std::equal_to { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x == b.x && a.x == b.y && a.z == b.z; } }; template <> struct std::equal_to { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w; } }; template <> struct std::equal_to { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x == b.x && a.x == b.y; } }; template <> struct std::equal_to { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x == b.x && a.x == b.y && a.z == b.z; } }; template <> struct std::equal_to { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w; } }; template <> struct std::not_equal_to { bool operator()(const glm::vec2& a, const glm::vec2& b) const { return a.x != b.x && a.x != b.y; } }; template <> struct std::not_equal_to { bool operator()(const glm::vec3& a, const glm::vec3& b) const { return a.x != b.x && a.x != b.y && a.z != b.z; } }; template <> struct std::not_equal_to { bool operator()(const glm::vec4& a, const glm::vec4& b) const { return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w; } }; template <> struct std::not_equal_to { bool operator()(const glm::ivec2& a, const glm::ivec2& b) const { return a.x != b.x && a.x != b.y; } }; template <> struct std::not_equal_to { bool operator()(const glm::ivec3& a, const glm::ivec3& b) const { return a.x != b.x && a.x != b.y && a.z != b.z; } }; template <> struct std::not_equal_to { bool operator()(const glm::ivec4& a, const glm::ivec4& b) const { return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w; } }; template <> struct std::not_equal_to { bool operator()(const glm::dvec2& a, const glm::dvec2& b) const { return a.x != b.x && a.x != b.y; } }; template <> struct std::not_equal_to { bool operator()(const glm::dvec3& a, const glm::dvec3& b) const { return a.x != b.x && a.x != b.y && a.z != b.z; } }; template <> struct std::not_equal_to { bool operator()(const glm::dvec4& a, const glm::dvec4& b) const { return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w; } }; namespace openspace::documentation { template <> TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const; template <> TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const; template <> TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const; template TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res; if (dict.hasValue(key)) { res.success = true; } else { res.success = false; if (dict.hasKey(key)) { TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; res.offenses.push_back(o); } else { TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::MissingKey; res.offenses.push_back(o); } } return res; } template std::string TemplateVerifier::documentation() const { return "Value of type '" + type() + "'"; } template std::string Vector2Verifier::type() const { if constexpr (std::is_same_v) { return "Vector2"; } else if constexpr (std::is_same_v) { return "Vector2"; } else { return std::string("Vector2<") + typeid(T).name() + ">"; } } template std::string Vector3Verifier::type() const { if constexpr (std::is_same_v) { return "Vector3"; } else if constexpr (std::is_same_v) { return "Vector3"; } else { return std::string("Vector3<") + typeid(T).name() + ">"; } } template std::string Vector4Verifier::type() const { if constexpr (std::is_same_v) { return "Vector4"; } else if constexpr (std::is_same_v) { return "Vector4"; } else { return std::string("Vector4<") + typeid(T).name() + ">"; } } template std::string Matrix2x2Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix2x2"; } else if constexpr (std::is_same_v) { return "Matrix2x2"; } else { return std::string("Matrix2x2<") + typeid(T).name() + ">"; } } template std::string Matrix2x3Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix2x3"; } else if constexpr (std::is_same_v) { return "Matrix2x3"; } else { return std::string("Matrix2x3<") + typeid(T).name() + ">"; } } template std::string Matrix2x4Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix2x4"; } else if constexpr (std::is_same_v) { return "Matrix2x4"; } else { return std::string("Matrix2x4<") + typeid(T).name() + ">"; } } template std::string Matrix3x2Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix3x2"; } else if constexpr (std::is_same_v) { return "Matrix3x2"; } else { return std::string("Matrix3x2<") + typeid(T).name() + ">"; } } template std::string Matrix3x3Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix3x3"; } else if constexpr (std::is_same_v) { return "Matrix3x3"; } else { return std::string("Matrix3x3<") + typeid(T).name() + ">"; } } template std::string Matrix3x4Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix3x4"; } else if constexpr (std::is_same_v) { return "Matrix3x4"; } else { return std::string("Matrix3x4<") + typeid(T).name() + ">"; } } template std::string Matrix4x2Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix4x2"; } else if constexpr (std::is_same_v) { return "Matrix4x2"; } else { return std::string("Matrix4x2<") + typeid(T).name() + ">"; } } template std::string Matrix4x3Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix4x3"; } else if constexpr (std::is_same_v) { return "Matrix4x3"; } else { return std::string("Matrix4x3<") + typeid(T).name() + ">"; } } template std::string Matrix4x4Verifier::type() const { if constexpr (std::is_same_v) { return "Matrix4x4"; } else if constexpr (std::is_same_v) { return "Matrix4x4"; } else { return std::string("Matrix4x4<") + typeid(T).name() + ">"; } } template OperatorVerifier::OperatorVerifier(typename T::Type val) : value(std::move(val)) {} template TestResult OperatorVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { typename T::Type val; if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { const double d = dict.value(key); double intPart; bool isInt = modf(d, &intPart) == 0.0; if (isInt) { val = static_cast(d); } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); return r; } } else { val = dict.value(key); } if (Operator()(val, value)) { return { true, {}, {} }; } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); return r; } } else { return res; } } template std::string LessVerifier::documentation() const { return "Less than: " + ghoul::to_string(value); } template std::string LessEqualVerifier::documentation() const { return "Less or equal to: " + ghoul::to_string(value); } template std::string GreaterVerifier::documentation() const { return "Greater than: " + ghoul::to_string(value); } template std::string GreaterEqualVerifier::documentation() const { return "Greater or equal to: " + ghoul::to_string(value); } template std::string EqualVerifier::documentation() const { return "Equal to: " + ghoul::to_string(value); } template std::string UnequalVerifier::documentation() const { return "Unequal to: " + ghoul::to_string(value); } template InListVerifier::InListVerifier(std::vector vals) : values(std::move(vals)) {} template TestResult InListVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { typename T::Type val; if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { const double d = dict.value(key); double intPart; bool isInt = modf(d, &intPart) == 0.0; if (isInt) { val = static_cast(d); } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); return r; } } else { val = dict.value(key); } auto it = std::find(values.begin(), values.end(), val); if (it != values.end()) { return { true, {}, {} }; } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); return r; } } else { return res; } } template std::string InListVerifier::documentation() const { std::string result = "In list { "; std::stringstream s; std::copy( values.begin(), values.end(), std::ostream_iterator(s, ",") ); std::string joined = s.str(); // We need to remove a trailing ',' at the end of the string result += joined.substr(0, joined.size() - 1); result += " }"; return result; } template NotInListVerifier::NotInListVerifier(std::vector vals) : values(std::move(vals)) {} template TestResult NotInListVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { typename T::Type val; if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { const double d = dict.value(key); double intPart; bool isInt = modf(d, &intPart) == 0.0; if (isInt) { val = static_cast(d); } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); return r; } } else { val = dict.value(key); } auto it = std::find(values.begin(), values.end(), val); if (it == values.end()) { return { true, {}, {} }; } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); return r; } } else { return res; } } template std::string NotInListVerifier::documentation() const { std::string result = "Not in list { "; std::stringstream s; std::copy( values.begin(), values.end(), std::ostream_iterator(s, ",") ); std::string joined = s.str(); // We need to remove a trailing ',' at the end of the string result += joined.substr(0, joined.size() - 1); result += " }"; return result; } template InRangeVerifier::InRangeVerifier(typename T::Type l, typename T::Type u) : lower(std::move(l)) , upper(std::move(u)) { if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); } else if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); ghoul_assert(lower.z <= upper.z, "lower must be smaller or equal to upper for z"); } else if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); ghoul_assert(lower.z <= upper.z, "lower must be smaller or equal to upper for z"); ghoul_assert(lower.w <= upper.w, "lower must be smaller or equal to upper for w"); } else { ghoul_assert(lower <= upper, "lower must be smaller or equal to upper"); } } template TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { typename T::Type val; if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { const double d = dict.value(key); double intPart; bool isInt = modf(d, &intPart) == 0.0; if (isInt) { val = static_cast(d); } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); return r; } } else { val = dict.value(key); } if (std::greater_equal()(val, lower) && std::less_equal()(val, upper)) { return { true, {}, {} }; } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); return r; } } else { return res; } } template std::string InRangeVerifier::documentation() const { return "In range: ( " + ghoul::to_string(lower) + "," + ghoul::to_string(upper) + " )"; } template NotInRangeVerifier::NotInRangeVerifier(typename T::Type l, typename T::Type u) : lower(std::move(l)) , upper(std::move(u)) { if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); } else if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); ghoul_assert(lower.z <= upper.z, "lower must be smaller or equal to upper for z"); } else if constexpr (std::is_same_v || std::is_same_v) { ghoul_assert(lower.x <= upper.x, "lower must be smaller or equal to upper for x"); ghoul_assert(lower.y <= upper.y, "lower must be smaller or equal to upper for y"); ghoul_assert(lower.z <= upper.z, "lower must be smaller or equal to upper for z"); ghoul_assert(lower.w <= upper.w, "lower must be smaller or equal to upper for w"); } else { ghoul_assert(lower <= upper, "lower must be smaller or equal to upper"); } } template TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { typename T::Type val; if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { val = dict.value(key); } else if constexpr (std::is_same_v) { const double d = dict.value(key); double intPart; bool isInt = modf(d, &intPart) == 0.0; if (isInt) { val = static_cast(d); } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); return r; } } else { val = dict.value(key); } if (std::less()(val, lower) || std::greater()(val, upper)) { return { true, {}, {} }; } else { TestResult r; r.success = false; TestResult::Offense o; o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); return r; } } else { return res; } } template std::string NotInRangeVerifier::documentation() const { return "Not in range: ( " + ghoul::to_string(lower) + "," + ghoul::to_string(upper) + " )"; } template AnnotationVerifier::AnnotationVerifier(std::string a) : annotation(std::move(a)) { } template std::string AnnotationVerifier::documentation() const { return annotation; } template TestResult DeprecatedVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); TestResult::Warning w; w.offender = key; w.reason = TestResult::Warning::Reason::Deprecated; res.warnings.push_back(w); return res; } template std::string DeprecatedVerifier::documentation() const { return T::documentation() + " (deprecated)"; } } // namespace openspace::documentation