| // Copyright 2014 The Chromium OS 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 BUFFET_COMMANDS_SCHEMA_UTILS_H_ | 
 | #define BUFFET_COMMANDS_SCHEMA_UTILS_H_ | 
 |  | 
 | #include <limits> | 
 | #include <map> | 
 | #include <memory> | 
 | #include <string> | 
 | #include <type_traits> | 
 | #include <vector> | 
 |  | 
 | #include <base/values.h> | 
 | #include <chromeos/any.h> | 
 | #include <chromeos/errors/error.h> | 
 | #include <chromeos/variant_dictionary.h> | 
 |  | 
 | namespace buffet { | 
 |  | 
 | class PropType; | 
 | class PropValue; | 
 | class ObjectSchema; | 
 | class ObjectValue; | 
 |  | 
 | namespace native_types { | 
 | // C++ representation of object values. | 
 | using Object = std::map<std::string, std::shared_ptr<const PropValue>>; | 
 | // C++ representation of array of values. | 
 | using Array = std::vector<std::shared_ptr<const PropValue>>; | 
 | }  // namespace native_types | 
 |  | 
 | // Converts an object to string. | 
 | std::string ToString(const native_types::Object& obj); | 
 |  | 
 | // Converts an array to string. | 
 | std::string ToString(const native_types::Array& 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 { | 
 |  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::Value> TypedValueToJson(bool value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | std::unique_ptr<base::Value> TypedValueToJson(int value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | std::unique_ptr<base::Value> TypedValueToJson(double value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | std::unique_ptr<base::Value> TypedValueToJson(const std::string& value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | std::unique_ptr<base::Value> TypedValueToJson(const native_types::Array& value, | 
 |                                               chromeos::ErrorPtr* error); | 
 | template<typename T> | 
 | std::unique_ptr<base::Value> TypedValueToJson(const std::vector<T>& values, | 
 |                                               chromeos::ErrorPtr* error) { | 
 |   std::unique_ptr<base::ListValue> list(new base::ListValue); | 
 |   for (const auto& v : values) { | 
 |     auto json = TypedValueToJson(v, error); | 
 |     if (!json) | 
 |       return std::unique_ptr<base::Value>(); | 
 |     list->Append(json.release()); | 
 |   } | 
 |   return std::move(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. | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         bool* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         int* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         double* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         std::string* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         native_types::Object* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 | bool TypedValueFromJson(const base::Value* value_in, | 
 |                         const PropType* type, | 
 |                         native_types::Array* value_out, | 
 |                         chromeos::ErrorPtr* error); | 
 |  | 
 | bool operator==(const native_types::Object& obj1, | 
 |                 const native_types::Object& obj2); | 
 | bool operator==(const native_types::Array& arr1, | 
 |                 const native_types::Array& 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(); | 
 | } | 
 |  | 
 | // Converts PropValue to Any in a format understood by D-Bus data serialization. | 
 | // Has special handling for Object types where native_types::Object are | 
 | // converted to chromeos::VariantDictionary. | 
 | chromeos::Any PropValueToDBusVariant(const PropValue* value); | 
 | // Converts native_types::Object to chromeos::VariantDictionary | 
 | // with proper conversion of all nested properties. | 
 | chromeos::VariantDictionary | 
 | ObjectToDBusVariant(const native_types::Object& object); | 
 | // Converts D-Bus variant to PropValue. | 
 | // Has special handling for Object types where chromeos::VariantDictionary | 
 | // is converted to native_types::Object. | 
 | std::unique_ptr<const PropValue> PropValueFromDBusVariant( | 
 |     const PropType* type, | 
 |     const chromeos::Any& value, | 
 |     chromeos::ErrorPtr* error); | 
 | // Converts D-Bus variant to ObjectValue. | 
 | bool ObjectFromDBusVariant(const ObjectSchema* object_schema, | 
 |                            const chromeos::VariantDictionary& dict, | 
 |                            native_types::Object* obj, | 
 |                            chromeos::ErrorPtr* error); | 
 |  | 
 | }  // namespace buffet | 
 |  | 
 | #endif  // BUFFET_COMMANDS_SCHEMA_UTILS_H_ |