pluto-src 0.1.1+0.10.4

Sources of Pluto (Lua 5.4 dialect) and logic to build it.
Documentation
#pragma once

#include <cstdint>
#include <string>
#include <vector>

#include "Endian.hpp"
#include "IntStruct.hpp"

NAMESPACE_SOUP
{
	using u8_t = uint8_t;
	using u16_t = uint16_t;
	using u32_t = uint32_t;
	using u64_t = uint64_t;

	SOUP_INT_STRUCT(u24_t, u32_t);
	SOUP_INT_STRUCT(u40_t, u64_t);
	SOUP_INT_STRUCT(u48_t, u64_t);
	SOUP_INT_STRUCT(u56_t, u64_t);

	SOUP_INT_STRUCT(u16be_t, u16_t);
	SOUP_INT_STRUCT(u24be_t, u32_t);
	SOUP_INT_STRUCT(u32be_t, u32_t);

	SOUP_INT_STRUCT(u16le_t, u16_t);
	SOUP_INT_STRUCT(u24le_t, u32_t);
	SOUP_INT_STRUCT(u32le_t, u32_t);

	class ioVirtualBase
	{
	protected:
		ioVirtualBase() noexcept
		{
		}

	public:
		virtual ~ioVirtualBase() = default;

		virtual bool raw(void* data, size_t len) noexcept = 0;
		[[nodiscard]] virtual size_t getPosition() = 0;

		bool b(bool& v) noexcept
		{
			return u8(*(uint8_t*)&v);
		}

		bool c(char& v) noexcept
		{
			return u8(*(uint8_t*)&v);
		}

		bool u8(uint8_t& v) noexcept
		{
			return raw(&v, sizeof(v));
		}
	};

	template <bool is_read>
	class ioBase : public ioVirtualBase
	{
	protected:
		using ioVirtualBase::ioVirtualBase;

	public:
		[[nodiscard]] static constexpr bool isRead() noexcept
		{
			return is_read;
		}

		[[nodiscard]] static constexpr bool isWrite() noexcept
		{
			return !isRead();
		}

		template <typename T>
		bool ser(T& v) noexcept;

		[[deprecated("Renamed to u16be")]] bool u16_be(uint16_t& v) noexcept { return u16be(v); }
		[[deprecated("Renamed to u16le")]] bool u16_le(uint16_t& v) noexcept { return u16le(v); }

		bool u16be(uint16_t& v) noexcept
		{
			return u16<ENDIAN_NATIVE == ENDIAN_BIG>(v);
		}

		bool u16le(uint16_t& v) noexcept
		{
			return u16<ENDIAN_NATIVE == ENDIAN_LITTLE>(v);
		}

	protected:
		template <bool native_endianness>
		bool u16(uint16_t& v) noexcept
		{
			if constexpr (native_endianness)
			{
				return raw(&v, sizeof(v));
			}
			else
			{
				if constexpr (is_read)
				{
					return raw(&v, sizeof(v))
						&& (v = Endianness::invert(v), true)
						;
				}
				else
				{
					auto tmp = Endianness::invert(v);
					return raw(&tmp, sizeof(v));
				}
			}
		}

	public:
		[[deprecated("Renamed to u32be")]] bool u32_be(uint32_t& v) noexcept { return u32be(v); }
		[[deprecated("Renamed to u32le")]] bool u32_le(uint32_t& v) noexcept { return u32le(v); }

		bool u32be(uint32_t& v) noexcept
		{
			return u32<ENDIAN_NATIVE == ENDIAN_BIG>(v);
		}

		bool u32le(uint32_t& v) noexcept
		{
			return u32<ENDIAN_NATIVE == ENDIAN_LITTLE>(v);
		}

	protected:
		template <bool native_endianness>
		bool u32(uint32_t& v) noexcept
		{
			if constexpr (native_endianness)
			{
				return raw(&v, sizeof(v));
			}
			else
			{
				if constexpr (is_read)
				{
					return raw(&v, sizeof(v))
						&& (v = Endianness::invert(v), true)
						;
				}
				else
				{
					auto tmp = Endianness::invert(v);
					return raw(&tmp, sizeof(v));
				}
			}
		}

	public:
		[[deprecated("Renamed to u64be")]] bool u64_be(uint64_t& v) noexcept { return u64be(v); }
		[[deprecated("Renamed to u64le")]] bool u64_le(uint64_t& v) noexcept { return u64le(v); }

		bool u64be(uint64_t& v) noexcept
		{
			return u64<ENDIAN_NATIVE == ENDIAN_BIG>(v);
		}

		bool u64le(uint64_t& v) noexcept
		{
			return u64<ENDIAN_NATIVE == ENDIAN_LITTLE>(v);
		}

	protected:
		template <bool native_endianness>
		bool u64(uint64_t& v) noexcept
		{
			if constexpr (native_endianness)
			{
				return raw(&v, sizeof(v));
			}
			else
			{
				if constexpr (is_read)
				{
					return raw(&v, sizeof(v))
						&& (v = Endianness::invert(v), true)
						;
				}
				else
				{
					auto tmp = Endianness::invert(v);
					return raw(&tmp, sizeof(v));
				}
			}
		}

	public:
		bool i8(int8_t& v) noexcept
		{
			return u8(*(uint8_t*)&v);
		}

		bool i16(int16_t& v) noexcept { return u16(*(uint16_t*)&v); }
		bool i16le(int16_t& v) noexcept { return u16le(*(uint16_t*)&v); }
		bool i16be(int16_t& v) noexcept { return u16be(*(uint16_t*)&v); }

		bool i32(int32_t& v) noexcept { return u32(*(uint32_t*)&v); }
		bool i32le(int32_t& v) noexcept { return u32le(*(uint32_t*)&v); }
		bool i32be(int32_t& v) noexcept { return u32be(*(uint32_t*)&v); }

		bool i64(int64_t& v) noexcept { return u64(*(uint64_t*)&v); }
		bool i64le(int64_t& v) noexcept { return u64le(*(uint64_t*)&v); }
		bool i64be(int64_t& v) noexcept { return u64be(*(uint64_t*)&v); }

		[[deprecated("Renamed to u24be")]] bool u24_be(uint32_t& v) noexcept { return u24be(v); }
		[[deprecated("Renamed to u24le")]] bool u24_le(uint32_t& v) noexcept { return u24le(v); }

		bool u24be(uint32_t& v) noexcept
		{
			return u24<ENDIAN_NATIVE == ENDIAN_BIG>(v);
		}

		bool u24le(uint32_t& v) noexcept
		{
			return u24<ENDIAN_NATIVE == ENDIAN_LITTLE>(v);
		}

	protected:
		template <bool native_endianness>
		bool u24(uint32_t& v) noexcept
		{
			if constexpr (is_read)
			{
				v = 0;
			}
			if constexpr (native_endianness)
			{
				return u8(((uint8_t*)&v)[0])
					&& u8(((uint8_t*)&v)[1])
					&& u8(((uint8_t*)&v)[2]);
			}
			else
			{
				return u8(((uint8_t*)&v)[2])
					&& u8(((uint8_t*)&v)[1])
					&& u8(((uint8_t*)&v)[0]);
			}
		}

	public:
		bool f32(float& v) noexcept
		{
			return u32le(*reinterpret_cast<uint32_t*>(&v));
		}

		bool f64(double& v) noexcept
		{
			return u64le(*reinterpret_cast<uint64_t*>(&v));
		}
	};

#define IOBASE_SER_METHOD_IMPL(t) IOBASE_SER_METHOD_IMPL_2(t, true) IOBASE_SER_METHOD_IMPL_2(t, false)

#define IOBASE_SER_METHOD_IMPL_2(t, is_read) template<> template<> inline bool ioBase<is_read>::ser<t ## _t>(t ## _t& v) noexcept { return t(v); }


	IOBASE_SER_METHOD_IMPL(u8)

	IOBASE_SER_METHOD_IMPL(u16be)
	IOBASE_SER_METHOD_IMPL(u24be)
	IOBASE_SER_METHOD_IMPL(u32be)

	IOBASE_SER_METHOD_IMPL(u16le)
	IOBASE_SER_METHOD_IMPL(u24le)
	IOBASE_SER_METHOD_IMPL(u32le)
}