forstio/source/forstio/message_container.h

242 lines
6.1 KiB
C
Raw Permalink Normal View History

2021-11-29 15:08:18 +01:00
#pragma once
#include "schema.h"
2021-12-29 19:26:22 +01:00
namespace saw {
2021-12-05 16:17:23 +01:00
template <class T> class MessageContainer;
2021-11-29 15:08:18 +01:00
2021-12-27 18:47:49 +01:00
template <class T, class Container = MessageContainer<T>> class Message;
2021-11-29 15:08:18 +01:00
2021-12-05 16:17:23 +01:00
template <size_t N, class... T> struct MessageParameterPackType;
2021-11-29 15:08:18 +01:00
2021-12-05 16:17:23 +01:00
template <class TN, class... T> struct MessageParameterPackType<0, TN, T...> {
2021-12-18 17:26:14 +01:00
using Type = TN;
2021-11-29 15:08:18 +01:00
};
2021-12-05 16:17:23 +01:00
template <size_t N, class TN, class... T>
struct MessageParameterPackType<N, TN, T...> {
static_assert(sizeof...(T) > 0, "Exhausted parameters");
2021-12-05 16:17:23 +01:00
using Type = typename MessageParameterPackType<N - 1, T...>::Type;
2021-11-29 15:08:18 +01:00
};
2021-12-05 16:17:23 +01:00
template <class T, class... TL> struct MessageParameterPackIndex;
2021-11-29 15:08:18 +01:00
2021-12-05 16:17:23 +01:00
template <class T, class... TL> struct MessageParameterPackIndex<T, T, TL...> {
2021-11-29 15:08:18 +01:00
static constexpr size_t Value = 0u;
};
2021-12-05 16:17:23 +01:00
template <class T, class TL0, class... TL>
struct MessageParameterPackIndex<T, TL0, TL...> {
static constexpr size_t Value =
1u + MessageParameterPackIndex<T, TL...>::Value;
2021-11-29 15:08:18 +01:00
};
2021-12-18 20:54:51 +01:00
/*
* Nightmare inducing compiler problems found here. Somehow non-type
* StringLiterals cannot be resolved as non-type primitive template values can.
* This is the workaround
*/
template <StringLiteral V, StringLiteral Key0, StringLiteral... Keys>
struct MessageParameterKeyPackIndexHelper {
static constexpr size_t Value =
(V == Key0)
? (0u)
: (1u + MessageParameterKeyPackIndexHelper<V, Keys...>::Value);
};
2021-12-18 17:26:14 +01:00
2021-12-18 20:54:51 +01:00
template <StringLiteral V, StringLiteral Key0>
struct MessageParameterKeyPackIndexHelper<V, Key0> {
static constexpr size_t Value = (V == Key0) ? (0u) : (1u);
2021-12-18 17:26:14 +01:00
};
2021-12-18 20:54:51 +01:00
template <StringLiteral V, StringLiteral... Keys>
struct MessageParameterKeyPackIndex {
2021-12-18 17:26:14 +01:00
static constexpr size_t Value =
2021-12-18 20:54:51 +01:00
MessageParameterKeyPackIndexHelper<V, Keys...>::Value;
static_assert(Value < sizeof...(Keys),
"Provided StringLiteral doesn't exist in searched list");
2021-12-18 17:26:14 +01:00
};
2021-12-27 18:15:42 +01:00
template <class T> struct SchemaIsArray {
constexpr static bool Value = false;
};
template <class T> struct SchemaIsArray<schema::Array<T>> {
constexpr static bool Value = true;
};
2021-12-12 02:04:32 +01:00
template <class... V, StringLiteral... Keys>
class MessageContainer<schema::Struct<schema::NamedMember<V, Keys>...>> {
2021-11-29 15:08:18 +01:00
private:
using ValueType = std::tuple<Message<V, MessageContainer<V>>...>;
ValueType values;
2021-12-05 16:17:23 +01:00
2021-11-29 15:08:18 +01:00
public:
2021-12-12 02:04:32 +01:00
using SchemaType = schema::Struct<schema::NamedMember<V, Keys>...>;
2021-11-29 15:08:18 +01:00
2021-12-05 16:17:23 +01:00
template <size_t i>
using ElementType = typename MessageParameterPackType<
i, Message<V, MessageContainer<V>>...>::Type;
2021-11-29 15:08:18 +01:00
2021-12-12 02:04:32 +01:00
template <size_t i> ElementType<i> &get() { return std::get<i>(values); }
};
/*
* Union storage
*/
2021-12-12 19:46:49 +01:00
template <class... V, StringLiteral... Keys>
class MessageContainer<schema::Union<schema::NamedMember<V, Keys>...>> {
2021-12-12 02:04:32 +01:00
private:
2021-12-12 19:46:49 +01:00
using ValueType = std::variant<Message<V, MessageContainer<V>>...>;
2021-12-12 02:04:32 +01:00
ValueType value;
2021-12-12 19:46:49 +01:00
2021-12-12 02:04:32 +01:00
public:
2021-12-12 19:14:52 +01:00
using SchemaType = schema::Union<schema::NamedMember<V, Keys>...>;
2021-12-12 19:46:49 +01:00
2021-12-12 19:14:52 +01:00
template <size_t i>
using ElementType = typename MessageParameterPackType<
i, Message<V, MessageContainer<V>>...>::Type;
2021-12-12 19:14:52 +01:00
2021-12-24 23:17:57 +01:00
template <size_t i> ElementType<i> &get() {
if (i != value.index()) {
using MessageIV = typename MessageParameterPackType<i, V...>::Type;
value = Message<MessageIV, MessageContainer<MessageIV>>{};
}
return std::get<i>(value);
}
size_t index() const noexcept { return value.index(); }
2021-12-12 19:14:52 +01:00
};
/*
* Array storage
*/
2021-12-27 18:15:42 +01:00
template <class T> class MessageContainer<schema::Array<T>> {
2021-12-12 19:14:52 +01:00
private:
2021-12-27 18:15:42 +01:00
using ValueType = std::vector<Message<T, MessageContainer<T>>>;
2021-12-12 19:14:52 +01:00
ValueType values;
2021-12-27 18:15:42 +01:00
2021-12-12 19:14:52 +01:00
public:
using SchemaType = schema::Array<T>;
2021-12-27 18:15:42 +01:00
using ElementType = Message<T, MessageContainer<T>>;
Message<T, MessageContainer<T>> &get(size_t index) {
return values.at(index);
2021-12-12 19:14:52 +01:00
}
2021-12-27 18:15:42 +01:00
void resize(size_t size) { values.resize(size); }
size_t size() const { return values.size(); }
2021-11-29 15:08:18 +01:00
};
2021-12-12 19:46:49 +01:00
/*
* Tuple storage
*/
template <class... T> class MessageContainer<schema::Tuple<T...>> {
private:
2021-12-21 16:27:29 +01:00
using ValueType = std::tuple<Message<T, MessageContainer<T>>...>;
2021-12-12 19:46:49 +01:00
ValueType values;
public:
using SchemaType = schema::Tuple<T...>;
template <size_t i>
using ElementType = typename MessageParameterPackType<
i, Message<T, MessageContainer<T>>...>::Type;
2021-12-12 19:46:49 +01:00
template <size_t i> ElementType<i> &get() { return std::get<i>(values); }
};
/*
* Helper for the basic message container, so the class doesn't have to be
* specialized 10 times.
*/
template <class T> struct PrimitiveTypeHelper;
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 1>> {
using Type = int8_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 2>> {
using Type = int16_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 4>> {
using Type = int32_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 8>> {
using Type = int64_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 1>> {
using Type = uint8_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 2>> {
using Type = uint16_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 4>> {
using Type = uint32_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 8>> {
using Type = uint64_t;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::FloatingPoint, 4>> {
using Type = float;
};
2021-12-18 17:26:14 +01:00
template <>
struct PrimitiveTypeHelper<schema::Primitive<schema::FloatingPoint, 8>> {
using Type = double;
};
2021-12-18 17:26:14 +01:00
template <class T, size_t N> class MessageContainer<schema::Primitive<T, N>> {
public:
2021-12-21 16:27:29 +01:00
using SchemaType = schema::Primitive<T, N>;
using ValueType =
typename PrimitiveTypeHelper<schema::Primitive<T, N>>::Type;
private:
ValueType value;
public:
MessageContainer() : value{0} {}
void set(const ValueType &v) { value = v; }
2021-12-05 19:48:20 +01:00
const ValueType &get() const { return value; }
};
template <> class MessageContainer<schema::String> {
public:
2021-12-21 16:27:29 +01:00
using SchemaType = schema::String;
2021-12-05 19:48:20 +01:00
using ValueType = std::string;
2021-12-27 16:08:35 +01:00
using ValueViewType = std::string_view;
2021-12-21 16:27:29 +01:00
private:
2021-12-05 19:48:20 +01:00
ValueType value;
public:
2021-12-27 16:08:35 +01:00
void set(ValueType &&v) { value = std::move(v); }
2021-12-05 19:48:20 +01:00
void set(const ValueType &v) { value = v; }
2021-12-27 16:08:35 +01:00
void set(const ValueViewType v) { value = std::string{v}; }
2021-12-05 19:48:20 +01:00
const ValueType &get() const { return value; }
};
2021-12-29 19:26:22 +01:00
} // namespace saw