Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 1 | // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef BUFFET_COMMANDS_SCHEMA_UTILS_H_ |
| 6 | #define BUFFET_COMMANDS_SCHEMA_UTILS_H_ |
| 7 | |
| 8 | #include <limits> |
| 9 | #include <map> |
| 10 | #include <memory> |
| 11 | #include <string> |
| 12 | #include <type_traits> |
| 13 | #include <vector> |
| 14 | |
| 15 | #include <base/values.h> |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 16 | #include <chromeos/any.h> |
Alex Vakulenko | a8b95bc | 2014-08-27 11:00:57 -0700 | [diff] [blame] | 17 | #include <chromeos/errors/error.h> |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 18 | |
| 19 | namespace buffet { |
| 20 | |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 21 | class PropType; |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 22 | class PropValue; |
| 23 | class ObjectSchema; |
| 24 | |
| 25 | namespace native_types { |
| 26 | // C++ representation of object values. |
Alex Vakulenko | aa3a559 | 2014-08-07 07:24:06 -0700 | [diff] [blame] | 27 | using Object = std::map<std::string, std::shared_ptr<const PropValue>>; |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 28 | } // namespace native_types |
| 29 | // Converts an object to string. |
| 30 | std::string ToString(const native_types::Object& obj); |
| 31 | |
| 32 | // InheritableAttribute class is used for specifying various command parameter |
| 33 | // attributes that can be inherited from a base (parent) schema. |
| 34 | // The |value| still specifies the actual attribute values, whether it |
| 35 | // is inherited or overridden, while |is_inherited| can be used to identify |
| 36 | // if the attribute was inherited (true) or overridden (false). |
| 37 | template<typename T> |
| 38 | class InheritableAttribute { |
| 39 | public: |
| 40 | InheritableAttribute() = default; |
| 41 | explicit InheritableAttribute(T val) |
| 42 | : value(std::move(val)), is_inherited(true) {} |
| 43 | InheritableAttribute(T val, bool inherited) |
| 44 | : value(std::move(val)), is_inherited(inherited) {} |
| 45 | T value{}; |
| 46 | bool is_inherited{true}; |
| 47 | }; |
| 48 | |
| 49 | // A bunch of helper function to create base::Value for specific C++ classes, |
| 50 | // including vectors of types. These are used in template classes below |
| 51 | // to simplify specialization logic. |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 52 | std::unique_ptr<base::Value> TypedValueToJson(bool value, |
| 53 | chromeos::ErrorPtr* error); |
| 54 | std::unique_ptr<base::Value> TypedValueToJson(int value, |
| 55 | chromeos::ErrorPtr* error); |
| 56 | std::unique_ptr<base::Value> TypedValueToJson(double value, |
| 57 | chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 58 | std::unique_ptr<base::Value> TypedValueToJson(const std::string& value, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 59 | chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 60 | std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 61 | chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 62 | template<typename T> |
| 63 | std::unique_ptr<base::Value> TypedValueToJson(const std::vector<T>& values, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 64 | chromeos::ErrorPtr* error) { |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 65 | std::unique_ptr<base::ListValue> list(new base::ListValue); |
| 66 | for (const auto& v : values) { |
| 67 | auto json = TypedValueToJson(v, error); |
| 68 | if (!json) |
| 69 | return std::unique_ptr<base::Value>(); |
| 70 | list->Append(json.release()); |
| 71 | } |
| 72 | return std::move(list); |
| 73 | } |
| 74 | |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 75 | // Similarly to TypedValueToJson() function above, the following overloaded |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 76 | // helper methods allow to extract specific C++ data types from base::Value. |
| 77 | // Also used in template classes below to simplify specialization logic. |
| 78 | bool TypedValueFromJson(const base::Value* value_in, |
| 79 | const ObjectSchema* object_schema, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 80 | bool* value_out, chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 81 | bool TypedValueFromJson(const base::Value* value_in, |
| 82 | const ObjectSchema* object_schema, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 83 | int* value_out, chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 84 | bool TypedValueFromJson(const base::Value* value_in, |
| 85 | const ObjectSchema* object_schema, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 86 | double* value_out, chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 87 | bool TypedValueFromJson(const base::Value* value_in, |
| 88 | const ObjectSchema* object_schema, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 89 | std::string* value_out, chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 90 | bool TypedValueFromJson(const base::Value* value_in, |
| 91 | const ObjectSchema* object_schema, |
Alex Vakulenko | 5f47206 | 2014-08-14 17:54:04 -0700 | [diff] [blame] | 92 | native_types::Object* value_out, |
| 93 | chromeos::ErrorPtr* error); |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 94 | |
| 95 | bool operator==(const native_types::Object& obj1, |
| 96 | const native_types::Object& obj2); |
| 97 | |
| 98 | // CompareValue is a helper function to help with implementing EqualsTo operator |
| 99 | // for various data types. For most scalar types it is using operator==(), |
| 100 | // however, for floating point values, rounding errors in binary representation |
| 101 | // of IEEE floats/doubles can cause straight == comparison to fail for seemingly |
| 102 | // equivalent values. For these, use approximate comparison with the error |
| 103 | // margin equal to the epsilon value defined for the corresponding data type. |
| 104 | // This is used when looking up values for implementation of OneOf constraints |
| 105 | // which should work reliably for floating points also ("number" type). |
| 106 | |
| 107 | // Compare exact types using ==. |
| 108 | template<typename T> |
| 109 | inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type |
| 110 | CompareValue(const T& v1, const T& v2) { |
| 111 | return v1 == v2; |
| 112 | } |
| 113 | |
| 114 | // Compare non-exact types (such as double) using precision margin (epsilon). |
| 115 | template<typename T> |
| 116 | inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type |
| 117 | CompareValue(const T& v1, const T& v2) { |
| 118 | return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon(); |
| 119 | } |
| 120 | |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 121 | // Converts PropValue to Any in a format understood by D-Bus data serialization. |
| 122 | // Has special handling for Object types where native_types::Object are |
Alex Vakulenko | 576c979 | 2014-09-22 16:49:45 -0700 | [diff] [blame^] | 123 | // converted to chromeos::VariantDictionary. |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 124 | chromeos::Any PropValueToDBusVariant(const PropValue* value); |
| 125 | // Converts D-Bus variant to PropValue. |
Alex Vakulenko | 576c979 | 2014-09-22 16:49:45 -0700 | [diff] [blame^] | 126 | // Has special handling for Object types where chromeos::VariantDictionary |
Alex Vakulenko | a32d83a | 2014-09-19 15:05:24 -0700 | [diff] [blame] | 127 | // is converted to native_types::Object. |
| 128 | std::shared_ptr<const PropValue> PropValueFromDBusVariant( |
| 129 | const PropType* type, |
| 130 | const chromeos::Any& value, |
| 131 | chromeos::ErrorPtr* error); |
| 132 | |
Alex Vakulenko | 66ec292 | 2014-06-17 15:30:22 -0700 | [diff] [blame] | 133 | } // namespace buffet |
| 134 | |
| 135 | #endif // BUFFET_COMMANDS_SCHEMA_UTILS_H_ |