blob: ff9d4615edf5920ca73652a1c700e286452825e8 [file] [log] [blame]
Alex Vakulenko66ec2922014-06-17 15:30:22 -07001// 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>
16
17#include <buffet/error.h>
18
19namespace buffet {
20
21class PropValue;
22class ObjectSchema;
23
24namespace native_types {
25// C++ representation of object values.
26using Object = std::map<std::string, std::shared_ptr<PropValue>>;
27} // namespace native_types
28// Converts an object to string.
29std::string ToString(const native_types::Object& obj);
30
31// InheritableAttribute class is used for specifying various command parameter
32// attributes that can be inherited from a base (parent) schema.
33// The |value| still specifies the actual attribute values, whether it
34// is inherited or overridden, while |is_inherited| can be used to identify
35// if the attribute was inherited (true) or overridden (false).
36template<typename T>
37class InheritableAttribute {
38 public:
39 InheritableAttribute() = default;
40 explicit InheritableAttribute(T val)
41 : value(std::move(val)), is_inherited(true) {}
42 InheritableAttribute(T val, bool inherited)
43 : value(std::move(val)), is_inherited(inherited) {}
44 T value{};
45 bool is_inherited{true};
46};
47
48// A bunch of helper function to create base::Value for specific C++ classes,
49// including vectors of types. These are used in template classes below
50// to simplify specialization logic.
51std::unique_ptr<base::Value> TypedValueToJson(bool value, ErrorPtr* error);
52std::unique_ptr<base::Value> TypedValueToJson(int value, ErrorPtr* error);
53std::unique_ptr<base::Value> TypedValueToJson(double value, ErrorPtr* error);
54std::unique_ptr<base::Value> TypedValueToJson(const std::string& value,
55 ErrorPtr* error);
56std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value,
57 ErrorPtr* error);
58template<typename T>
59std::unique_ptr<base::Value> TypedValueToJson(const std::vector<T>& values,
60 ErrorPtr* error) {
61 std::unique_ptr<base::ListValue> list(new base::ListValue);
62 for (const auto& v : values) {
63 auto json = TypedValueToJson(v, error);
64 if (!json)
65 return std::unique_ptr<base::Value>();
66 list->Append(json.release());
67 }
68 return std::move(list);
69}
70
71// Similarly to CreateTypedValue() function above, the following overloaded
72// helper methods allow to extract specific C++ data types from base::Value.
73// Also used in template classes below to simplify specialization logic.
74bool TypedValueFromJson(const base::Value* value_in,
75 const ObjectSchema* object_schema,
76 bool* value_out, ErrorPtr* error);
77bool TypedValueFromJson(const base::Value* value_in,
78 const ObjectSchema* object_schema,
79 int* value_out, ErrorPtr* error);
80bool TypedValueFromJson(const base::Value* value_in,
81 const ObjectSchema* object_schema,
82 double* value_out, ErrorPtr* error);
83bool TypedValueFromJson(const base::Value* value_in,
84 const ObjectSchema* object_schema,
85 std::string* value_out, ErrorPtr* error);
86bool TypedValueFromJson(const base::Value* value_in,
87 const ObjectSchema* object_schema,
88 native_types::Object* value_out, ErrorPtr* error);
89
90bool operator==(const native_types::Object& obj1,
91 const native_types::Object& obj2);
92
93// CompareValue is a helper function to help with implementing EqualsTo operator
94// for various data types. For most scalar types it is using operator==(),
95// however, for floating point values, rounding errors in binary representation
96// of IEEE floats/doubles can cause straight == comparison to fail for seemingly
97// equivalent values. For these, use approximate comparison with the error
98// margin equal to the epsilon value defined for the corresponding data type.
99// This is used when looking up values for implementation of OneOf constraints
100// which should work reliably for floating points also ("number" type).
101
102// Compare exact types using ==.
103template<typename T>
104inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
105CompareValue(const T& v1, const T& v2) {
106 return v1 == v2;
107}
108
109// Compare non-exact types (such as double) using precision margin (epsilon).
110template<typename T>
111inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type
112CompareValue(const T& v1, const T& v2) {
113 return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
114}
115
116} // namespace buffet
117
118#endif // BUFFET_COMMANDS_SCHEMA_UTILS_H_