datactl/streammeta.h

datactl/streammeta.h

datactl/streammeta.h

Namespaces

Name
Syntalos

Classes

Name
structSyntalos::MetaSize
Represents the dimensions of a two-dimensional object with width and height.
structSyntalos::MetaArray
Array of values used for stream metadata.
structSyntalos::MetaStringMap
Mapping of values used for stream metadata.
structSyntalos::MetaValue
Data type that can be used as stream metadata.

Source code

/*
 * Copyright (C) 2024-2026 Matthias Klumpp <matthias@tenstral.net>
 *
 * Licensed under the GNU Lesser General Public License Version 3
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the license, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <variant>
#include <vector>

namespace Syntalos
{

struct MetaSize {
    int32_t width = 0;
    int32_t height = 0;

    constexpr MetaSize() = default;
    constexpr MetaSize(int32_t w, int32_t h)
        : width(w),
          height(h)
    {
    }

    [[nodiscard]] constexpr bool isEmpty() const
    {
        return width <= 0 || height <= 0;
    }

    bool operator==(const MetaSize &) const = default;
};

inline std::ostream &operator<<(std::ostream &os, const MetaSize &sz)
{
    os << "MetaSize(" << sz.width << ", " << sz.height << ")";
    return os;
}

struct MetaValue;

struct MetaArray : std::vector<MetaValue> {
    using vector::vector;
    bool operator==(const MetaArray &) const = default;
};

struct MetaStringMap : std::map<std::string, MetaValue> {
    using map::map;

    auto value(const std::string &key) const -> std::optional<const MetaValue>;
    const MetaValue &valueOr(const std::string &key, const MetaValue &fallback) const;

    template<typename T>
    [[nodiscard]] std::optional<T> value(const std::string &key) const;
    template<typename T>
    [[nodiscard]] T valueOr(const std::string &key, T fallback) const;
};

std::ostream &operator<<(std::ostream &os, const MetaArray &arr);
std::ostream &operator<<(std::ostream &os, const MetaValue &v);
std::ostream &operator<<(std::ostream &os, const MetaStringMap &map);

struct MetaValue
    : std::variant<std::nullptr_t, bool, int64_t, double, std::string, MetaSize, MetaArray, MetaStringMap> {
    using Base = std::variant<std::nullptr_t, bool, int64_t, double, std::string, MetaSize, MetaArray, MetaStringMap>;
    using variant::variant;

    MetaValue(const char *s)
        : variant(std::string{s})
    {
    }

    MetaValue(int32_t v)
        : variant(static_cast<int64_t>(v))
    {
    }

    bool operator==(const MetaValue &other) const
    {
        return static_cast<const Base &>(*this) == static_cast<const Base &>(other);
    }

    template<typename T>
    [[nodiscard]] std::optional<T> get() const
    {
        const T *ptr = std::get_if<T>(this);
        return ptr ? std::optional<T>(*ptr) : std::nullopt;
    }

    template<typename T>
    [[nodiscard]] T getOr(T fallback) const
    {
        const T *ptr = std::get_if<T>(this);
        return ptr ? *ptr : std::move(fallback);
    }
};

inline auto MetaStringMap::value(const std::string &key) const -> std::optional<const MetaValue>
{
    auto it = find(key);
    if (it != end())
        return it->second;
    return std::nullopt;
}

inline const MetaValue &MetaStringMap::valueOr(const std::string &key, const MetaValue &fallback) const
{
    auto it = find(key);
    return it != end() ? it->second : fallback;
}

template<typename T>
[[nodiscard]] std::optional<T> MetaStringMap::value(const std::string &key) const
{
    const auto v = this->value(key);
    return v.has_value() ? v->template get<T>() : std::nullopt;
}

template<typename T>
[[nodiscard]] T MetaStringMap::valueOr(const std::string &key, T fallback) const
{
    const auto v = this->value(key);
    return v.has_value() ? v->template getOr<T>(std::move(fallback)) : std::move(fallback);
}

inline std::ostream &operator<<(std::ostream &os, const MetaArray &arr)
{
    os << '[';
    bool first = true;
    for (const auto &v : arr) {
        if (!first)
            os << ", ";
        first = false;
        os << v;
    }
    os << ']';
    return os;
}

inline std::ostream &operator<<(std::ostream &os, const MetaStringMap &map)
{
    os << '{';
    bool first = true;
    for (const auto &[key, value] : map) {
        if (!first)
            os << ", ";
        first = false;
        os << '"' << key << "\": " << value;
    }
    os << '}';
    return os;
}

inline std::ostream &operator<<(std::ostream &os, const MetaValue &v)
{
    std::visit(
        [&os](const auto &value) {
            using T = std::decay_t<decltype(value)>;

            if constexpr (std::is_same_v<T, std::nullptr_t>) {
                os << "null";
            } else if constexpr (std::is_same_v<T, bool>) {
                os << (value ? "true" : "false");
            } else if constexpr (std::is_same_v<T, std::string>) {
                os << '"' << value << '"';
            } else {
                os << value;
            }
        },
        static_cast<const MetaValue::Base &>(v));

    return os;
}

} // namespace Syntalos

Updated on 2026-04-20 at 00:59:18 +0000