TOML Media file

The fossil_media_toml library provides a simple C API to parse TOML strings into structured tables and key-value pairs. Each table contains entries, and the entire document is represented as an array of tables. The C++ wrapper offers RAII management, move semantics, and convenient access via std::string, making it safe and easy to read TOML configuration data in Fossil Logic projects.

HEADER REFERENCE #

#ifndef FOSSIL_MEDIA_TOML_H
#define FOSSIL_MEDIA_TOML_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief Representation of a TOML key-value pair.
 */
typedef struct fossil_media_toml_entry_t {
    char *key;      /**< The key name */
    char *value;    /**< The string value (numbers are stored as strings and can be converted) */
} fossil_media_toml_entry_t;

/**
 * @brief Representation of a parsed TOML table (section).
 */
typedef struct fossil_media_toml_table_t {
    char *name;                             /**< Table name */
    fossil_media_toml_entry_t *entries;     /**< Array of key-value pairs */
    size_t entry_count;                     /**< Number of entries */
} fossil_media_toml_table_t;

/**
 * @brief Main parsed TOML document.
 */
typedef struct fossil_media_toml_t {
    fossil_media_toml_table_t *tables;  /**< Array of tables */
    size_t table_count;                 /**< Number of tables */
} fossil_media_toml_t;

/**
 * @brief Parse TOML data from a string.
 *
 * @param input The TOML string to parse.
 * @param out_toml Pointer to TOML document struct to populate.
 * @return 0 on success, nonzero on error.
 */
int fossil_media_toml_parse(const char *input, fossil_media_toml_t *out_toml);

/**
 * @brief Retrieve a value from a specific table by key.
 *
 * @param toml Pointer to parsed TOML document.
 * @param table_name Table name to search (NULL for root).
 * @param key Key name to search for.
 * @return Value string, or NULL if not found.
 */
const char *fossil_media_toml_get(const fossil_media_toml_t *toml, const char *table_name, const char *key);

/**
 * @brief Free a parsed TOML document.
 *
 * @param toml Pointer to TOML document to free.
 */
void fossil_media_toml_free(fossil_media_toml_t *toml);

#ifdef __cplusplus
}
#include <string>
#include <stdexcept>
#include <utility>

namespace fossil {

    namespace media {

        /**
         * @brief C++ wrapper for parsed TOML documents.
         *
         * Provides RAII management and convenient access to TOML data.
         */
        class Toml {
        public:
            /**
             * @brief Parse TOML data from a string.
             *
             * @param input TOML string to parse.
             * @throws std::runtime_error on parse error.
             */
            explicit Toml(const std::string& input) {
                if (fossil_media_toml_parse(input.c_str(), &doc_) != 0) {
                    throw std::runtime_error("Failed to parse TOML data");
                }
            }

            /**
             * @brief Move constructor.
             */
            Toml(Toml&& other) noexcept : doc_{other.doc_} {
                other.doc_.tables = nullptr;
                other.doc_.table_count = 0;
            }

            /**
             * @brief Move assignment operator.
             */
            Toml& operator=(Toml&& other) noexcept {
                if (this != &other) {
                    fossil_media_toml_free(&doc_);
                    doc_ = other.doc_;
                    other.doc_.tables = nullptr;
                    other.doc_.table_count = 0;
                }
                return *this;
            }

            /**
             * @brief Deleted copy constructor.
             */
            Toml(const Toml&) = delete;

            /**
             * @brief Deleted copy assignment operator.
             */
            Toml& operator=(const Toml&) = delete;

            /**
             * @brief Destructor. Frees the TOML document.
             */
            ~Toml() {
                fossil_media_toml_free(&doc_);
            }

            /**
             * @brief Retrieve a value from a specific table by key.
             *
             * @param table_name Table name to search (empty for root).
             * @param key Key name to search for.
             * @return Value string, or empty string if not found.
             */
            std::string get(const std::string& table_name, const std::string& key) const {
                const char* val = fossil_media_toml_get(
                    &doc_,
                    table_name.empty() ? nullptr : table_name.c_str(),
                    key.c_str()
                );
                return val ? std::string(val) : std::string();
            }

        private:
            fossil_media_toml_t doc_{};
        };

    } // namespace media

} // namespace fossil

#endif

#endif /* FOSSIL_MEDIA_TOML_H */

SAMPLE CODE C #

#include "fossil/media/toml.h"
#include <stdio.h>

int main() {
    const char *toml_text = 
        "[database]\n"
        "user = \"admin\"\n"
        "port = \"5432\"\n";

    fossil_media_toml_t doc;
    if (fossil_media_toml_parse(toml_text, &doc) != 0) {
        printf("Failed to parse TOML\n");
        return 1;
    }

    const char *user = fossil_media_toml_get(&doc, "database", "user");
    const char *port = fossil_media_toml_get(&doc, "database", "port");

    printf("Database user: %s\n", user ? user : "(not found)");
    printf("Database port: %s\n", port ? port : "(not found)");

    fossil_media_toml_free(&doc);
    return 0;
}

SAMPLE CODE C++ #

#include "fossil/media/toml.h"
#include <iostream>

int main() {
    const std::string toml_text = 
        "[database]\n"
        "user = \"admin\"\n"
        "port = \"5432\"\n";

    try {
        fossil::media::Toml config(toml_text);

        std::string user = config.get("database", "user");
        std::string port = config.get("database", "port");

        std::cout << "Database user: " << user << "\n";
        std::cout << "Database port: " << port << "\n";
    } catch (const std::runtime_error& e) {
        std::cerr << "Error parsing TOML: " << e.what() << "\n";
    }

    return 0;
}

What are your feelings

Updated on August 21, 2025