#pragma once #include #include #include #include #include #include #include namespace phosphor { namespace network { namespace config { /** @brief Compare in (case insensitive) vs expected (sensitive) */ bool icaseeq(std::string_view in, std::string_view expected) noexcept; /** @brief Turns a systemd bool string into a c++ bool */ std::optional parseBool(std::string_view in) noexcept; namespace fs = std::filesystem; fs::path pathForIntfConf(const fs::path& dir, std::string_view intf); fs::path pathForIntfDev(const fs::path& dir, std::string_view intf); template class Checked { public: struct unchecked {}; template constexpr Checked(Args&&... args) : t(conCheck(std::forward(args)...)) {} template constexpr Checked(unchecked, Args&&... args) : t(std::forward(args)...) {} constexpr const T& get() const noexcept { return t; } constexpr operator const T&() const noexcept { return t; } template constexpr bool operator==(const Checked& rhs) const noexcept { static_assert(std::is_same_v); return t == rhs.t; } constexpr bool operator==(const auto& rhs) const noexcept { return t == rhs; } private: T t; template static constexpr T conCheck(Args&&... args) { T t(std::forward(args)...); Check{}(t); return t; } }; struct KeyCheck { void operator()(std::string_view s); }; struct SectionCheck { void operator()(std::string_view s); }; struct ValueCheck { void operator()(std::string_view s); }; struct string_hash : public std::hash { using is_transparent = void; template inline size_t operator()(const Checked& t) const { return static_cast&>(*this)(t.get()); } template inline size_t operator()(const T& t) const { return static_cast&>(*this)(t); } }; using Key = Checked; using Section = Checked; using Value = Checked; using ValueList = std::vector; using KeyValuesMap = std::unordered_map>; using KeyValuesMapList = std::vector; using SectionMapInt = std::unordered_map>; class SectionMap : public SectionMapInt { public: const std::string* getLastValueString(std::string_view section, std::string_view key) const noexcept; inline auto getValues(std::string_view section, std::string_view key, auto&& conv) const { std::vector> values; auto sit = find(section); if (sit == end()) { return values; } for (const auto& secv : sit->second) { auto kit = secv.find(key); if (kit == secv.end()) { continue; } for (auto v : kit->second) { values.push_back(conv(v)); } } return values; } std::vector getValueStrings(std::string_view section, std::string_view key) const; }; class Parser { public: SectionMap map; Parser() = default; /** @brief Constructor * @param[in] filename - Absolute path of the file which will be parsed. */ Parser(const fs::path& filename); /** @brief Determine if the loaded file exists */ inline bool getFileExists() const noexcept { return fileExists; } /** @brief Determine if there were warnings parsing the file * @return The number of parsing issues in the file */ inline const std::vector& getWarnings() const noexcept { return warnings; } /** @brief Get the filename last parsed successfully * @return file path */ inline const fs::path& getFilename() const noexcept { return filename; } /** @brief Set the file name and parse it. * @param[in] filename - Absolute path of the file. */ void setFile(const fs::path& filename); /** @brief Write the current config to a file */ void writeFile() const; void writeFile(const fs::path& filename); private: bool fileExists = false; fs::path filename; std::vector warnings; }; } // namespace config } // namespace network } // namespace phosphor