blob: 826bab80d34e6c775a65ef3f448c45e21354ce68 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenko66ec2922014-06-17 15:30:22 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Vitaly Buka912b6982015-07-06 11:13:03 -07005#ifndef LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
6#define LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_
Alex Vakulenko66ec2922014-06-17 15:30:22 -07007
8#include <limits>
9#include <map>
10#include <memory>
11#include <string>
12#include <type_traits>
13#include <vector>
14
Vitaly Buka0d501072015-08-18 18:09:46 -070015#include <base/logging.h>
Alex Vakulenko66ec2922014-06-17 15:30:22 -070016#include <base/values.h>
Vitaly Buka0801a1f2015-08-14 10:03:46 -070017#include <weave/error.h>
Alex Vakulenko66ec2922014-06-17 15:30:22 -070018
Vitaly Bukab6f015a2015-07-09 14:59:23 -070019namespace weave {
Alex Vakulenko66ec2922014-06-17 15:30:22 -070020
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070021class PropType;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070022class PropValue;
23class ObjectSchema;
Anton Muhincfde8692014-11-25 03:36:59 +040024class ObjectValue;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070025
Alex Vakulenko66ec2922014-06-17 15:30:22 -070026// C++ representation of object values.
Vitaly Buka774cdf52015-07-21 13:55:00 -070027using ValueMap = std::map<std::string, std::shared_ptr<const PropValue>>;
28
Alex Vakulenko29e64442015-03-20 13:59:19 -070029// C++ representation of array of values.
Vitaly Buka774cdf52015-07-21 13:55:00 -070030using ValueVector = std::vector<std::shared_ptr<const PropValue>>;
Alex Vakulenko29e64442015-03-20 13:59:19 -070031
Alex Vakulenko66ec2922014-06-17 15:30:22 -070032// Converts an object to string.
Vitaly Buka774cdf52015-07-21 13:55:00 -070033std::string ToString(const ValueMap& obj);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070034
Alex Vakulenko29e64442015-03-20 13:59:19 -070035// Converts an array to string.
Vitaly Buka774cdf52015-07-21 13:55:00 -070036std::string ToString(const ValueVector& arr);
Alex Vakulenko29e64442015-03-20 13:59:19 -070037
Alex Vakulenko66ec2922014-06-17 15:30:22 -070038// InheritableAttribute class is used for specifying various command parameter
39// attributes that can be inherited from a base (parent) schema.
40// The |value| still specifies the actual attribute values, whether it
41// is inherited or overridden, while |is_inherited| can be used to identify
42// if the attribute was inherited (true) or overridden (false).
Vitaly Bukaa647c852015-07-06 14:51:01 -070043template <typename T>
Alex Vakulenko534a3122015-05-22 15:48:53 -070044class InheritableAttribute final {
Alex Vakulenko66ec2922014-06-17 15:30:22 -070045 public:
46 InheritableAttribute() = default;
47 explicit InheritableAttribute(T val)
48 : value(std::move(val)), is_inherited(true) {}
49 InheritableAttribute(T val, bool inherited)
50 : value(std::move(val)), is_inherited(inherited) {}
51 T value{};
52 bool is_inherited{true};
53};
54
55// A bunch of helper function to create base::Value for specific C++ classes,
56// including vectors of types. These are used in template classes below
57// to simplify specialization logic.
Vitaly Buka6942e1f2015-07-28 15:33:55 -070058std::unique_ptr<base::FundamentalValue> TypedValueToJson(bool value);
59std::unique_ptr<base::FundamentalValue> TypedValueToJson(int value);
60std::unique_ptr<base::FundamentalValue> TypedValueToJson(double value);
61std::unique_ptr<base::StringValue> TypedValueToJson(const std::string& value);
62std::unique_ptr<base::DictionaryValue> TypedValueToJson(const ValueMap& value);
63std::unique_ptr<base::ListValue> TypedValueToJson(const ValueVector& value);
Vitaly Bukaa647c852015-07-06 14:51:01 -070064template <typename T>
Vitaly Buka6942e1f2015-07-28 15:33:55 -070065std::unique_ptr<base::ListValue> TypedValueToJson(
66 const std::vector<T>& values) {
Alex Vakulenko66ec2922014-06-17 15:30:22 -070067 std::unique_ptr<base::ListValue> list(new base::ListValue);
68 for (const auto& v : values) {
Vitaly Buka6942e1f2015-07-28 15:33:55 -070069 auto json = TypedValueToJson(v);
70 CHECK(json);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070071 list->Append(json.release());
72 }
Vitaly Buka39ef1952015-07-21 20:32:11 -070073 return list;
Alex Vakulenko66ec2922014-06-17 15:30:22 -070074}
75
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -070076// Similarly to TypedValueToJson() function above, the following overloaded
Alex Vakulenko66ec2922014-06-17 15:30:22 -070077// helper methods allow to extract specific C++ data types from base::Value.
78// Also used in template classes below to simplify specialization logic.
Vitaly Bukad7be9052015-07-28 19:22:55 -070079// TODO(vitalybuka): Fix this. Interface is misleading. Seeing PropType internal
80// type validation is expected. In reality only ValueMap and ValueVector do
81// validation.
Alex Vakulenko66ec2922014-06-17 15:30:22 -070082bool TypedValueFromJson(const base::Value* value_in,
Alex Vakulenkod94656e2015-03-18 09:54:37 -070083 const PropType* type,
84 bool* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -070085 ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070086bool TypedValueFromJson(const base::Value* value_in,
Alex Vakulenkod94656e2015-03-18 09:54:37 -070087 const PropType* type,
88 int* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -070089 ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070090bool TypedValueFromJson(const base::Value* value_in,
Alex Vakulenkod94656e2015-03-18 09:54:37 -070091 const PropType* type,
92 double* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -070093 ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070094bool TypedValueFromJson(const base::Value* value_in,
Alex Vakulenkod94656e2015-03-18 09:54:37 -070095 const PropType* type,
96 std::string* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -070097 ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -070098bool TypedValueFromJson(const base::Value* value_in,
Alex Vakulenkod94656e2015-03-18 09:54:37 -070099 const PropType* type,
Vitaly Buka774cdf52015-07-21 13:55:00 -0700100 ValueMap* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700101 ErrorPtr* error);
Alex Vakulenko29e64442015-03-20 13:59:19 -0700102bool TypedValueFromJson(const base::Value* value_in,
103 const PropType* type,
Vitaly Buka774cdf52015-07-21 13:55:00 -0700104 ValueVector* value_out,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700105 ErrorPtr* error);
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700106
Vitaly Buka774cdf52015-07-21 13:55:00 -0700107bool operator==(const ValueMap& obj1, const ValueMap& obj2);
108bool operator==(const ValueVector& arr1, const ValueVector& arr2);
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700109
110// CompareValue is a helper function to help with implementing EqualsTo operator
111// for various data types. For most scalar types it is using operator==(),
112// however, for floating point values, rounding errors in binary representation
113// of IEEE floats/doubles can cause straight == comparison to fail for seemingly
114// equivalent values. For these, use approximate comparison with the error
115// margin equal to the epsilon value defined for the corresponding data type.
116// This is used when looking up values for implementation of OneOf constraints
117// which should work reliably for floating points also ("number" type).
118
119// Compare exact types using ==.
Vitaly Bukaa647c852015-07-06 14:51:01 -0700120template <typename T>
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700121inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
122CompareValue(const T& v1, const T& v2) {
123 return v1 == v2;
124}
125
126// Compare non-exact types (such as double) using precision margin (epsilon).
Vitaly Bukaa647c852015-07-06 14:51:01 -0700127template <typename T>
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700128inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type
129CompareValue(const T& v1, const T& v2) {
130 return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
131}
132
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700133} // namespace weave
Alex Vakulenko66ec2922014-06-17 15:30:22 -0700134
Vitaly Buka912b6982015-07-06 11:13:03 -0700135#endif // LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_