diff options
author | pommicket <pommicket@gmail.com> | 2025-09-16 21:30:01 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-09-16 21:30:01 -0400 |
commit | 49000be20eb598db55c24a1e982a3b6b0b581eeb (patch) | |
tree | 85cc9766ee7cecd9b64364c9f034b440bf7c3264 | |
parent | ea7b73aac55177d1d556d0c9dba04b0870d3aaf6 (diff) |
Finish documenting libpom++
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | Doxyfile | 2 | ||||
-rw-r--r-- | cpp/Doxyfile | 2 | ||||
-rw-r--r-- | cpp/pom.cpp | 31 | ||||
-rw-r--r-- | cpp/pom.hpp | 118 |
5 files changed, 118 insertions, 41 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a44c39..4a3b896 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,12 @@ -cmake_minimum_required(VERSION 3.0...3.31) +# NB: ≥3.8 required for C++17 +cmake_minimum_required(VERSION 3.8...3.31) project(pom) option(LIBPOM_CXX "Build C++ library" ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + if (MSVC) add_compile_options(/W4) else() @@ -20,7 +20,7 @@ AUTOLINK_SUPPORT = NO DISTRIBUTE_GROUP_DOC = YES EXTRACT_STATIC = YES COLLABORATION_GRAPH = NO -WARN_IF_UNDOCUMENTED = NO +WARN_IF_UNDOCUMENTED = YES QUIET = YES INCLUDE_GRAPH = NO WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/cpp/Doxyfile b/cpp/Doxyfile index 03da967..5c4d038 100644 --- a/cpp/Doxyfile +++ b/cpp/Doxyfile @@ -19,7 +19,7 @@ AUTOLINK_SUPPORT = NO DISTRIBUTE_GROUP_DOC = YES EXTRACT_STATIC = YES COLLABORATION_GRAPH = NO -WARN_IF_UNDOCUMENTED = NO +WARN_IF_UNDOCUMENTED = YES QUIET = YES INCLUDE_GRAPH = NO WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/cpp/pom.cpp b/cpp/pom.cpp index 058040e..29dc7e1 100644 --- a/cpp/pom.cpp +++ b/cpp/pom.cpp @@ -192,30 +192,13 @@ std::vector<std::string> Configuration::keys() const { return keys; } -class ItemImpl: public Item { -public: - ItemImpl(const pom_item *C) { - m_key = C->key; - m_value = C->value; - m_file = C->file; - m_line = C->line; - } - virtual ~ItemImpl() {} - virtual std::string_view key() const noexcept override { return m_key; } - virtual std::string_view value() const noexcept override { return m_value; } - virtual std::string_view file() const noexcept override { return m_file; } - virtual uint64_t line() const noexcept override { return m_line; } - std::string m_key, m_value, m_file; - uint64_t m_line; -}; - -std::vector<std::shared_ptr<Item>> Configuration::items() const { +std::vector<std::unique_ptr<Item>> Configuration::items() const { if (!C) return {}; - std::vector<std::shared_ptr<Item>> items; + std::vector<std::unique_ptr<Item>> items; pom_item_iter *iter = nullptr; const pom_item *item; while ((item = pom_conf_next_item(static_cast<const pom_conf *>(C), &iter))) { - items.push_back(std::shared_ptr<Item>(new ItemImpl(item))); + items.push_back(std::unique_ptr<Item>(new Item(item->key, item->value, item->file, item->line))); } return items; } @@ -314,7 +297,7 @@ Configuration &Configuration::operator=(const Configuration &other) { } std::ostream &operator<<(std::ostream &o, const Configuration &conf) { - for (auto item: conf.items()) + for (const auto &item: conf.items()) o << item->key() << ": " << item->value() << "\n"; return o; } @@ -330,6 +313,12 @@ std::optional<Location> Configuration::location(std::string_view key) const { return {}; } +bool Configuration::has(std::string_view key) const { + if (!C) return false; + std::string key_str(key); + return pom_conf_has(static_cast<const pom_conf *>(C), key_str.c_str()); +} + std::ostream &operator<<(std::ostream &o, const Location &location) { return o << location.file() << ":" << location.line(); } diff --git a/cpp/pom.hpp b/cpp/pom.hpp index 4e20727..ba65b25 100644 --- a/cpp/pom.hpp +++ b/cpp/pom.hpp @@ -42,6 +42,7 @@ #include <memory> #include <optional> +/// libpom++ namespace namespace pom { /// A libpom++ error. @@ -100,12 +101,11 @@ public: inline Settings() {} /// Set language for error messages. /// - /// `lang` should be an IETF-like language tag. + /// Currently supported languages: `en`, `fr`. /// + /// \param lang IETF-like language tag. /// The closest supported language will be used /// (e.g. `fr-CA` will currently redirect to `fr`). - /// - /// Currently supported: `en`, `fr`. void set_error_language(std::string_view lang); private: void check_version() const; @@ -122,25 +122,51 @@ private: class Reader { public: /// Read up to `count` bytes of data into `buf`. + /// + /// This method will not be called excessively/with lots of tiny reads—it's + /// okay to do unbuffered reads in it. + /// + /// \param buf Place to put data. + /// \param count (Non-zero) number of bytes to read + /// + /// \returns 0 to indicate the end of the file, + /// or a positive value ≤ `count`, to indicate the number of bytes read. virtual size_t read(char *buf, size_t count) = 0; }; -/// An item in a configuration -/// -/// This is an abstract class so that items can be given -/// more members in the future. +/// An item in a configuration (returned by \ref Configuration::items). class Item { public: - inline virtual ~Item() {}; - virtual std::string_view key() const noexcept = 0; - virtual std::string_view value() const noexcept = 0; - virtual std::string_view file() const noexcept = 0; - virtual uint64_t line() const noexcept = 0; + /// Name of the key. + /// + /// The returned string view is valid for the lifetime of `this`. + std::string_view key() const noexcept { return m_key; } + /// Value of the key. + /// + /// The returned string view is valid for the lifetime of `this`. + std::string_view value() const noexcept { return m_value; } + /// File name where key was defined. + /// + /// The returned string view is valid for the lifetime of `this`. + std::string_view file() const noexcept { return m_file; } + /// Line number where key was defined. + uint64_t line() const noexcept { return m_line; } +private: + Item(std::string_view key, std::string_view value, std::string_view file, uint64_t line): + m_key(key), m_value(value), m_file(file), m_line(line) {} + friend class Configuration; + std::string m_key, m_value, m_file; + uint64_t m_line; }; +/// A source location. class Location { public: + /// File name + /// + /// The returned string view is valid for the lifetime of `this`. inline std::string_view file() const { return m_file; } + /// Line number inline uint64_t line() const { return m_line; } private: inline Location(std::string file, uint64_t line): @@ -151,40 +177,100 @@ private: // to allow for future extensions without breaking backwards compatibility const uint32_t version = 1; }; +/// Print location as `file``:``line` (exact format may change in future). std::ostream &operator<<(std::ostream &, const Location &); +/// A POM configuration. class Configuration { public: + /// Create empty configuration. Configuration(); + /// Set `this` to `other`, deleting the current configuration in `this`. Configuration &operator=(const Configuration &other); + /// Copy configuration from `other`. inline Configuration(const Configuration &other) { *this = other; }; /// Load configuration from abstract \ref Reader. /// /// Most of the time, you will be able to use another constructor to load a configuration. /// But if you have special functions for performing reads, you may need this. + /// + /// \param filename File name for error messages. + /// \param source Abstract reader to get file data from. + /// \param settings Settings for parsing the file, or `nullptr` to use defaults. Configuration(std::string_view filename, Reader &source, const Settings *settings = nullptr); + /// Load configuration from a `std::istream`. + /// + /// \param filename File name for error messages. + /// \param stream Stream to read file from. + /// \param settings Settings for parsing the file, or `nullptr` to use defaults. Configuration(std::string_view filename, std::istream &stream, const Settings *settings = nullptr); + /// Load configuration from a file path. + /// + /// \param path File name for error messages and to load configuration from. + /// \param settings Settings for parsing the file, or `nullptr` to use defaults. Configuration(std::string_view path, const Settings *settings = nullptr); + /// Load configuration from a string. + /// + /// \param filename File name for error messages. + /// \param string String containing the configuration. + /// \param settings Settings for parsing the file, or `nullptr` to use defaults. Configuration(std::string_view filename, std::string_view string, const Settings *settings = nullptr); ~Configuration(); - std::optional<Location> location(std::string_view key) const; + /// Get value of `key` in configuration. std::optional<std::string> get(std::string_view key) const; + /// Get value of `key` in configuration, or `dflt` if `key` isn't defined. std::string get_or_default(std::string_view key, std::string_view dflt) const; + /// Get signed integer value of `key` in configuration. + /// + /// Throws an \ref Error if `key` exists but isn't a valid signed integer. std::optional<int64_t> get_int(std::string_view key) const; + /// Get signed integer value of `key` in configuration, or `dflt` if `key` isn't defined. + /// + /// Throws an \ref Error if `key` exists but isn't a valid signed integer. int64_t get_int_or_default(std::string_view key, int64_t dflt) const; + /// Get unsigned integer value of `key` in configuration. + /// + /// Throws an \ref Error if `key` exists but isn't a valid unsigned integer. std::optional<uint64_t> get_uint(std::string_view key) const; + /// Get unsigned integer value of `key` in configuration, or `dflt` if `key` isn't defined. + /// + /// Throws an \ref Error if `key` exists but isn't a valid unsigned integer. uint64_t get_uint_or_default(std::string_view key, uint64_t dflt) const; + /// Get floating-point value of `key` in configuration. + /// + /// Throws an \ref Error if `key` exists but isn't a valid floating-point number. std::optional<double> get_float(std::string_view key) const; + /// Get floating-point value of `key` in configuration, or `dflt` if `key` isn't defined. + /// + /// Throws an \ref Error if `key` exists but isn't a valid floating-point number. double get_float_or_default(std::string_view key, double dflt) const; + /// Get boolean value of `key` in configuration. + /// + /// Throws an \ref Error if `key` exists but isn't a valid boolean (`on`/`off`/`yes`/`no`/`true`/`false`). std::optional<bool> get_bool(std::string_view key) const; + /// Get boolean value of `key` in configuration, or `dflt` if `key` isn't defined. + /// + /// Throws an \ref Error if `key` exists but isn't a valid boolean (`on`/`off`/`yes`/`no`/`true`/`false`). bool get_bool_or_default(std::string_view key, bool dflt) const; + /// Get list value of `key` in configuration. std::optional<std::vector<std::string>> get_list(std::string_view key) const; + /// Get list value of `key` in configuration, or `dflt` if `key` isn't defined. std::vector<std::string> get_list_or_default(std::string_view key, const std::vector<std::string> &dflt) const; + /// Returns whether `key` is in this configuration. + bool has(std::string_view key) const; + /// Returns location of `key` in this configuration. + std::optional<Location> location(std::string_view key) const; + /// Extract section of configuration consisting of all keys starting with `name.` and their values. Configuration section(std::string_view name) const; /// Get list of keys which haven't been the target of a `get_*` method. std::vector<std::string> unread_keys() const; + /// Get list of all "direct" keys (unique first components of keys) in this configuration. std::vector<std::string> keys() const; - std::vector<std::shared_ptr<Item>> items() const; + /// Get all key-value pairs in this configuration. + /// + /// This returns a vector of pointers, so that more fields can be added to items in the future + /// without breaking binary backwards compatibility. + std::vector<std::unique_ptr<Item>> items() const; /// Merge `other` configuration into `this`. /// /// Puts all the key-value pairs of `other` into this configuration. @@ -196,11 +282,9 @@ private: explicit Configuration(void *c): C(c) {} void *C; }; +/// Print configuration. std::ostream &operator<<(std::ostream &, const Configuration &); - - - } // namespace pom #endif // POM_HPP_ |