| // Copyright 2015 The Weave Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_ |
| #define LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_ |
| |
| #include <cmath> |
| #include <limits> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <type_traits> |
| #include <vector> |
| |
| #include <base/logging.h> |
| #include <base/values.h> |
| #include <weave/error.h> |
| |
| namespace weave { |
| |
| class PropType; |
| class PropValue; |
| class ObjectSchema; |
| class ObjectValue; |
| |
| // C++ representation of object values. |
| using ValueMap = std::map<std::string, std::shared_ptr<const PropValue>>; |
| |
| // C++ representation of array of values. |
| using ValueVector = std::vector<std::shared_ptr<const PropValue>>; |
| |
| // Converts an object to string. |
| std::string ToString(const ValueMap& obj); |
| |
| // Converts an array to string. |
| std::string ToString(const ValueVector& arr); |
| |
| // InheritableAttribute class is used for specifying various command parameter |
| // attributes that can be inherited from a base (parent) schema. |
| // The |value| still specifies the actual attribute values, whether it |
| // is inherited or overridden, while |is_inherited| can be used to identify |
| // if the attribute was inherited (true) or overridden (false). |
| template <typename T> |
| class InheritableAttribute final { |
| public: |
| InheritableAttribute() = default; |
| explicit InheritableAttribute(T val) |
| : value(std::move(val)), is_inherited(true) {} |
| InheritableAttribute(T val, bool inherited) |
| : value(std::move(val)), is_inherited(inherited) {} |
| T value{}; |
| bool is_inherited{true}; |
| }; |
| |
| // A bunch of helper function to create base::Value for specific C++ classes, |
| // including vectors of types. These are used in template classes below |
| // to simplify specialization logic. |
| std::unique_ptr<base::FundamentalValue> TypedValueToJson(bool value); |
| std::unique_ptr<base::FundamentalValue> TypedValueToJson(int value); |
| std::unique_ptr<base::FundamentalValue> TypedValueToJson(double value); |
| std::unique_ptr<base::StringValue> TypedValueToJson(const std::string& value); |
| std::unique_ptr<base::DictionaryValue> TypedValueToJson(const ValueMap& value); |
| std::unique_ptr<base::ListValue> TypedValueToJson(const ValueVector& value); |
| template <typename T> |
| std::unique_ptr<base::ListValue> TypedValueToJson( |
| const std::vector<T>& values) { |
| std::unique_ptr<base::ListValue> list(new base::ListValue); |
| for (const auto& v : values) { |
| auto json = TypedValueToJson(v); |
| CHECK(json); |
| list->Append(json.release()); |
| } |
| return list; |
| } |
| |
| // Similarly to TypedValueToJson() function above, the following overloaded |
| // helper methods allow to extract specific C++ data types from base::Value. |
| // Also used in template classes below to simplify specialization logic. |
| // TODO(vitalybuka): Fix this. Interface is misleading. Seeing PropType internal |
| // type validation is expected. In reality only ValueMap and ValueVector do |
| // validation. |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| bool* value_out, |
| ErrorPtr* error); |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| int* value_out, |
| ErrorPtr* error); |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| double* value_out, |
| ErrorPtr* error); |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| std::string* value_out, |
| ErrorPtr* error); |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| ValueMap* value_out, |
| ErrorPtr* error); |
| bool TypedValueFromJson(const base::Value* value_in, |
| const PropType* type, |
| ValueVector* value_out, |
| ErrorPtr* error); |
| |
| bool operator==(const ValueMap& obj1, const ValueMap& obj2); |
| bool operator==(const ValueVector& arr1, const ValueVector& arr2); |
| |
| // CompareValue is a helper function to help with implementing EqualsTo operator |
| // for various data types. For most scalar types it is using operator==(), |
| // however, for floating point values, rounding errors in binary representation |
| // of IEEE floats/doubles can cause straight == comparison to fail for seemingly |
| // equivalent values. For these, use approximate comparison with the error |
| // margin equal to the epsilon value defined for the corresponding data type. |
| // This is used when looking up values for implementation of OneOf constraints |
| // which should work reliably for floating points also ("number" type). |
| |
| // Compare exact types using ==. |
| template <typename T> |
| inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type |
| CompareValue(const T& v1, const T& v2) { |
| return v1 == v2; |
| } |
| |
| // Compare non-exact types (such as double) using precision margin (epsilon). |
| template <typename T> |
| inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type |
| CompareValue(const T& v1, const T& v2) { |
| return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon(); |
| } |
| |
| } // namespace weave |
| |
| #endif // LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_ |