blob: 3390c12215dc536f7a69734716ca9eb4f956a0e5 [file] [log] [blame] [edit]
/* Copyright 2022 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <string>
#include <vector>
#include <base/strings/string_util.h>
#include <base/strings/string_number_conversions.h>
#include "cros-camera/common.h"
#include "hal/fake/value_util.h"
namespace cros {
DottedPath DottedPath::extend(const std::string& p) const {
DottedPath ret = *this;
ret.segments.push_back(p);
return ret;
}
std::ostream& operator<<(std::ostream& s, const DottedPath& path) {
s << "$";
for (const auto& p : path.segments) {
s << "." << p;
}
return s;
}
const ListWithPath::Iterator& ListWithPath::Iterator::operator++() {
idx++;
return *this;
}
ValueWithPath ListWithPath::Iterator::operator*() const {
return ValueWithPath{&(*value)[idx], path.extend(base::NumberToString(idx))};
}
bool ListWithPath::Iterator::operator!=(const Iterator& o) const {
return idx != o.idx;
}
ListWithPath::Iterator ListWithPath::begin() const {
return Iterator{path, value, 0};
}
ListWithPath::Iterator ListWithPath::end() const {
return Iterator{path, value, value->size()};
}
#define WARN_MALFORMED(path, type, value) \
LOGF(WARNING) << "malformed entry at " << path << ": " << type \
<< " expected, got:\n" \
<< value
#define WARN_MISSING(path) LOGF(WARNING) << "missing required key at " << path
#define WARN_MISSING_WITH_TYPE(path, type) \
WARN_MISSING(path) << ": " << type << " expected"
std::optional<DictWithPath> GetIfDict(const ValueWithPath& v) {
auto ret = v->GetIfDict();
if (ret == nullptr) {
WARN_MALFORMED(v.path, "dictionary", *v.value);
return std::nullopt;
}
return DictWithPath{ret, v.path};
}
std::optional<ListWithPath> GetIfList(const ValueWithPath& v) {
auto ret = v->GetIfList();
if (ret == nullptr) {
WARN_MALFORMED(v.path, "list", *v.value);
return std::nullopt;
}
return ListWithPath{ret, v.path};
}
template <>
std::optional<ValueWithPath> GetValue<ValueWithPath>(const DictWithPath& dict,
std::string_view key) {
auto child = dict->Find(key);
if (child == nullptr) {
return std::nullopt;
}
return ValueWithPath{child, dict.path.extend(std::string(key))};
}
template <>
std::optional<ValueWithPath> GetRequiredValue<ValueWithPath>(
const DictWithPath& dict, std::string_view key) {
auto val = GetValue<ValueWithPath>(dict, key);
if (!val.has_value()) {
WARN_MISSING(dict.path << "." << key);
}
return val;
}
#define GENERATE_TYPED_GETTER(c_type, value_type, type_name, return_wrapper) \
template <> \
std::optional<c_type> GetRequiredValue<c_type>(const DictWithPath& dict, \
std::string_view key) { \
auto child = dict->Find(key); \
if (child == nullptr) { \
WARN_MISSING_WITH_TYPE(dict.path << "." << key, #type_name); \
return std::nullopt; \
} \
auto ret = child->GetIf##value_type(); \
if (!ret) { \
WARN_MALFORMED(dict.path << "." << key, #type_name, *child); \
return std::nullopt; \
} \
return return_wrapper(ret, dict.path.extend(std::string(key))); \
} \
\
template <> \
std::optional<c_type> GetValue<c_type>(const DictWithPath& dict, \
std::string_view key) { \
auto child = dict->Find(key); \
if (child == nullptr) { \
return std::nullopt; \
} \
auto ret = child->GetIf##value_type(); \
if (!ret) { \
WARN_MALFORMED(dict.path << "." << key, #type_name, *child); \
return std::nullopt; \
} \
return return_wrapper(ret, dict.path.extend(std::string(key))); \
}
#define DEREF_RET(x, y) *x
#define DICT_WITH_PATH_WRAPPER(x, y) \
DictWithPath { \
x, y \
}
#define LIST_WITH_PATH_WRAPPER(x, y) \
ListWithPath { \
x, y \
}
GENERATE_TYPED_GETTER(int, Int, integer, DEREF_RET);
GENERATE_TYPED_GETTER(bool, Bool, boolean, DEREF_RET);
GENERATE_TYPED_GETTER(double, Double, number, DEREF_RET);
GENERATE_TYPED_GETTER(std::string, String, string, DEREF_RET);
GENERATE_TYPED_GETTER(DictWithPath, Dict, dict, DICT_WITH_PATH_WRAPPER);
GENERATE_TYPED_GETTER(ListWithPath, List, list, LIST_WITH_PATH_WRAPPER);
#undef LIST_WITH_PATH_WRAPPER
#undef DICT_WITH_PATH_WRAPPER
#undef DEREF_RET
#undef GENERATE_TYPED_GETTER
#undef WARN_MISSING_WITH_TYPE
#undef WARN_MISSING
#undef WARN_MALFORMED
} // namespace cros