YAML Media file

The fossil_media_yaml library provides a simple, linked-list-based parser for YAML key-value pairs. Each node stores a key, a value, and its indentation level. The library allows parsing YAML strings, retrieving values by key, printing the node list for debugging, and freeing memory. The C++ wrapper provides RAII management, move semantics, and convenient methods for value lookup and debug printing.

HEADER REFERENCE #

#ifndef FOSSIL_MEDIA_YAML_H
#define FOSSIL_MEDIA_YAML_H

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

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief YAML key-value pair node.
 */
typedef struct fossil_media_yaml_node_t {
    char *key;                           /**< YAML key string */
    char *value;                         /**< YAML value string */
    size_t indent;                       /**< Indentation level */
    struct fossil_media_yaml_node_t *next; /**< Next node in linked list */
} fossil_media_yaml_node_t;

/**
 * @brief Parse YAML string into a linked list of nodes.
 * @param input YAML text (null-terminated)
 * @return Head of linked list, or NULL on failure.
 */
fossil_media_yaml_node_t *fossil_media_yaml_parse(const char *input);

/**
 * @brief Free a linked list of YAML nodes.
 * @param head Head of the linked list
 */
void fossil_media_yaml_free(fossil_media_yaml_node_t *head);

/**
 * @brief Get the value for a given key (first match).
 * @param head YAML node list
 * @param key Key string to search
 * @return Value string, or NULL if not found.
 */
const char *fossil_media_yaml_get(const fossil_media_yaml_node_t *head, const char *key);

/**
 * @brief Print the YAML node list to stdout (debug).
 * @param head YAML node list
 */
void fossil_media_yaml_print(const fossil_media_yaml_node_t *head);

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

namespace fossil {

    namespace media {

        /**
         * @brief C++ wrapper for YAML parsing and manipulation.
         */
        class Yaml {
        public:
            /**
             * @brief Construct a Yaml object by parsing a YAML string.
             * @param input YAML text (null-terminated)
             * @throw std::runtime_error on parse failure
             */
            explicit Yaml(const char* input)
            : head_(::fossil_media_yaml_parse(input)) {
                if (!head_) {
                    throw std::runtime_error("Failed to parse YAML input");
                }
            }

            /**
             * @brief Destructor. Frees the linked list of YAML nodes.
             */
            ~Yaml() {
                ::fossil_media_yaml_free(head_);
            }

            // Non-copyable
            Yaml(const Yaml&) = delete;
            Yaml& operator=(const Yaml&) = delete;

            // Movable
            Yaml(Yaml&& other) noexcept : head_(other.head_) {
                other.head_ = nullptr;
                }
                Yaml& operator=(Yaml&& other) noexcept {
                if (this != &other) {
                    ::fossil_media_yaml_free(head_);
                    head_ = other.head_;
                    other.head_ = nullptr;
                }
                return *this;
            }

            /**
             * @brief Get the value for a given key (first match).
             * @param key Key string to search
             * @return Value string, or nullptr if not found.
             */
            const char* get(const char* key) const {
                return ::fossil_media_yaml_get(head_, key);
            }

            /**
             * @brief Print the YAML node list to stdout (debug).
             */
            void print() const {
                ::fossil_media_yaml_print(head_);
            }

        private:
            fossil_media_yaml_node_t* head_;
        };

    } // namespace media

} // namespace fossil

#endif

#endif /* FOSSIL_MEDIA_YAML_H */

SAMPLE CODE C #

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

int main() {
    const char *yaml_text =
        "name: John Doe\n"
        "age: 30\n"
        "city: New York\n";

    fossil_media_yaml_node_t *root = fossil_media_yaml_parse(yaml_text);
    if (!root) {
        printf("Failed to parse YAML\n");
        return 1;
    }

    const char *name = fossil_media_yaml_get(root, "name");
    const char *age = fossil_media_yaml_get(root, "age");
    const char *city = fossil_media_yaml_get(root, "city");

    printf("Name: %s\nAge: %s\nCity: %s\n", 
           name ? name : "(none)", 
           age ? age : "(none)", 
           city ? city : "(none)");

    fossil_media_yaml_free(root);
    return 0;
}

SAMPLE CODE C++ #

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

int main() {
    const char* yaml_text =
        "name: John Doe\n"
        "age: 30\n"
        "city: New York\n";

    try {
        fossil::media::Yaml doc(yaml_text);

        std::cout << "Name: " << (doc.get("name") ? doc.get("name") : "(none)") << "\n";
        std::cout << "Age: " << (doc.get("age") ? doc.get("age") : "(none)") << "\n";
        std::cout << "City: " << (doc.get("city") ? doc.get("city") : "(none)") << "\n";

        std::cout << "\nYAML Debug Print:\n";
        doc.print();

    } catch (const std::runtime_error& e) {
        std::cerr << "YAML error: " << e.what() << "\n";
    }
}

What are your feelings

Updated on August 21, 2025