/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2022, Google Inc. * * yaml_parser.h - libcamera YAML parsing helper */ #pragma once #include #include #include #include #include #include #include namespace libcamera { class File; class YamlParserContext; class YamlObject { private: struct Value { Value(std::string &&k, std::unique_ptr &&v) : key(std::move(k)), value(std::move(v)) { } std::string key; std::unique_ptr value; }; using Container = std::vector; using ListContainer = std::vector>; public: #ifndef __DOXYGEN__ template class Iterator { public: using difference_type = std::ptrdiff_t; using iterator_category = std::forward_iterator_tag; Iterator(typename Container::const_iterator it) : it_(it) { } Derived &operator++() { ++it_; return *static_cast(this); } Derived operator++(int) { Derived it = *static_cast(this); it_++; return it; } friend bool operator==(const Iterator &a, const Iterator &b) { return a.it_ == b.it_; } friend bool operator!=(const Iterator &a, const Iterator &b) { return a.it_ != b.it_; } protected: Container::const_iterator it_; }; template class Adapter { public: Adapter(const Container &container) : container_(container) { } Iterator begin() const { return Iterator{ container_.begin() }; } Iterator end() const { return Iterator{ container_.end() }; } protected: const Container &container_; }; class ListIterator : public Iterator { public: using value_type = const YamlObject &; using pointer = const YamlObject *; using reference = value_type; value_type operator*() const { return *it_->value.get(); } pointer operator->() const { return it_->value.get(); } }; class DictIterator : public Iterator { public: using value_type = std::pair; using pointer = value_type *; using reference = value_type &; value_type operator*() const { return { it_->key, *it_->value.get() }; } }; class DictAdapter : public Adapter { public: using key_type = std::string; }; class ListAdapter : public Adapter { }; #endif /* __DOXYGEN__ */ YamlObject(); ~YamlObject(); bool isValue() const { return type_ == Type::Value; } bool isList() const { return type_ == Type::List; } bool isDictionary() const { return type_ == Type::Dictionary; } std::size_t size() const; #ifndef __DOXYGEN__ template || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v> * = nullptr> #else template #endif std::optional get() const; template T get(const T &defaultValue) const { return get().value_or(defaultValue); } #ifndef __DOXYGEN__ template || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v> * = nullptr> #else template #endif std::optional> getList() const; DictAdapter asDict() const { return DictAdapter{ list_ }; } ListAdapter asList() const { return ListAdapter{ list_ }; } const YamlObject &operator[](std::size_t index) const; bool contains(const std::string &key) const; const YamlObject &operator[](const std::string &key) const; private: LIBCAMERA_DISABLE_COPY_AND_MOVE(YamlObject) friend class YamlParserContext; enum class Type { Dictionary, List, Value, }; Type type_; std::string value_; Container list_; std::map dictionary_; }; class YamlParser final { public: static std::unique_ptr parse(File &file); }; } /* namespace libcamera */