Orange/include/Orange/Formats/KeyValues.h

375 lines
9.9 KiB
C
Raw Normal View History

2023-01-18 08:39:29 +00:00
#pragma once
#include <Orange/Core/Variant.h>
2023-01-18 10:16:34 +00:00
#include <Orange/Core/Vector.h>
2023-01-18 08:39:29 +00:00
#include <Orange/Core/Parse.h>
#include <Orange/Core/Span.h>
#include <Orange/Graphics/Color.h>
#include <unordered_map>
#include <cstdint>
#include <string>
#include <cstring>
#include <memory>
namespace orange::kv
{
namespace Types
{
enum KVVariantType
{
None,
String,
Int,
Float,
Ptr,
Color,
Uint64,
KeyValues,
Count,
};
}
using KeyValuesType = Types::KVVariantType;
class KeyValues;
2023-01-18 10:16:34 +00:00
2023-01-18 08:39:29 +00:00
class KeyValuesVariant
{
public:
using KeyValuesChild = std::unique_ptr<KeyValues>;
2023-01-18 10:16:34 +00:00
using KeyValuesString = SmallVector<char, 8>;
2023-01-18 08:39:29 +00:00
KeyValuesVariant()
{
}
template <typename T>
KeyValuesVariant(const T& arg)
{
Set(arg);
}
template <typename T>
KeyValuesVariant(T&& arg)
{
Set(Move(arg));
}
~KeyValuesVariant()
{
Clear();
}
void Clear()
{
switch (m_type)
{
case Types::String:
2023-01-18 10:16:34 +00:00
m_str.clear();
2023-01-18 08:39:29 +00:00
break;
case Types::KeyValues:
m_data.Destruct<KeyValuesChild>();
break;
default:
break;
}
m_type = Types::None;
m_data.Clear();
}
2023-01-18 10:16:34 +00:00
template <typename T>
T Get() const;
2023-01-18 08:39:29 +00:00
2023-01-18 21:28:26 +00:00
operator StringView();
operator int64_t();
operator int32_t();
operator float();
operator double();
operator void*();
operator RGBAColor32();
operator uint32_t();
operator uint64_t();
2023-01-18 10:16:34 +00:00
void Set(const std::string& val) { Clear(); m_type = Types::String; m_str = KeyValuesString{ StringView{ val } }; }
void Set(StringView val) { Clear(); m_type = Types::String; m_str = KeyValuesString{ val }; }
2023-01-18 08:39:29 +00:00
void Set(int32_t val) { Clear(); m_type = Types::Int; m_data.Get<int64_t>() = val; }
void Set(int64_t val) { Clear(); m_type = Types::Int; m_data.Get<int64_t>() = val; }
void Set(float val) { Clear(); m_type = Types::Float; m_data.Get<double>() = val; }
void Set(double val) { Clear(); m_type = Types::Float; m_data.Get<double>() = val; }
void Set(void* val) { Clear(); m_type = Types::Ptr; m_data.Get<void*>() = val; }
void Set(RGBAColor32 val) { Clear(); m_type = Types::Color; m_data.Construct<RGBAColor32>(val); }
void Set(uint32_t val) { Clear(); m_type = Types::Uint64; m_data.Get<uint64_t>() = val; }
void Set(uint64_t val) { Clear(); m_type = Types::Uint64; m_data.Get<uint64_t>() = val; }
void Set(KeyValuesChild val) { Clear(); m_type = Types::KeyValues; m_data.Get<KeyValuesChild>() = Move(val); }
2023-01-18 10:16:34 +00:00
KeyValuesVariant& operator [](const char *string);
const KeyValuesVariant& operator [](const char *string) const;
static KeyValuesVariant& GetEmptyValue() { return s_Nothing; }
2023-01-18 08:39:29 +00:00
private:
2023-01-18 10:16:34 +00:00
static KeyValuesVariant s_Nothing;
2023-01-18 08:39:29 +00:00
KeyValuesType m_type = Types::None;
2023-01-18 10:16:34 +00:00
KeyValuesString m_str;
2023-01-18 08:39:29 +00:00
Variant<
int64_t,
double,
void*,
uint64_t,
RGBAColor32,
KeyValuesChild> m_data;
};
class KeyValues
{
public:
static std::unique_ptr<KeyValues> ParseFromUTF8(StringView buffer)
{
const char *start = buffer.begin();
const char *end = buffer.end();
return ParseChild(start, end);
}
2023-01-18 10:16:34 +00:00
static KeyValues& Nothing()
{
return s_Nothing;
}
KeyValuesVariant& operator [](const char *string)
{
auto iter = m_children.find(string);
if (iter == m_children.end())
{
std::cerr << "Returning KeyValuesVariant empty value: " << string << std::endl;
return KeyValuesVariant::GetEmptyValue();
}
return iter->second;
}
const KeyValuesVariant& operator [] (const char *string) const
{
auto iter = m_children.find(string);
if (iter == m_children.end())
{
std::cerr << "Returning KeyValuesVariant empty value: " << string << std::endl;
return KeyValuesVariant::GetEmptyValue();
}
return iter->second;
}
2023-01-18 08:39:29 +00:00
private:
2023-01-18 10:16:34 +00:00
static KeyValues s_Nothing;
2023-01-18 08:39:29 +00:00
static std::unique_ptr<KeyValues> ParseChild(const char*& start, const char* end)
{
StringView range = StringView(start, end);
if (start == end)
return nullptr;
2023-01-18 10:16:34 +00:00
stream::ConsumeSpaceAndNewLine(start, end);
2023-01-18 08:39:29 +00:00
if (*start != '{')
return nullptr;
2023-01-18 10:16:34 +00:00
auto kv = std::make_unique<KeyValues>();
2023-01-18 08:39:29 +00:00
bool inString = false;
bool fillingInValue = false;
std::string key;
std::string value;
2023-01-18 10:16:34 +00:00
start++;
2023-01-18 08:39:29 +00:00
while (start != end)
{
if (stream::IsStringToken(range, start))
2023-01-18 10:16:34 +00:00
{
2023-01-18 08:39:29 +00:00
inString = !inString;
2023-01-18 10:16:34 +00:00
start++;
continue;
}
2023-01-18 08:39:29 +00:00
if (!inString)
{
2023-01-18 10:16:34 +00:00
if (stream::IsCPPComment(range, start))
{
2023-01-18 21:28:26 +00:00
stream::AdvancePast(start, end, stream::NewlineDelimiters);
2023-01-18 10:16:34 +00:00
stream::ConsumeSpaceAndNewLine(start, end);
2023-01-18 08:39:29 +00:00
continue;
2023-01-18 10:16:34 +00:00
}
2023-01-18 08:39:29 +00:00
if (*start == '{')
{
auto child = ParseChild(start, end);
kv->m_children.emplace(key, Move(child));
fillingInValue = false;
key.clear();
value.clear();
}
if (*start == '}')
{
start++;
break;
}
2023-01-18 21:28:26 +00:00
if (stream::IsWhitespace(*start) || stream::IsNewLine(*start))
2023-01-18 08:39:29 +00:00
{
2023-01-18 10:16:34 +00:00
fillingInValue = !fillingInValue;
2023-01-18 08:39:29 +00:00
if (!fillingInValue)
{
kv->m_children.emplace(key, value);
key.clear();
value.clear();
}
2023-01-18 21:28:26 +00:00
else if (stream::IsNewLine(*start))
2023-01-18 10:16:34 +00:00
{
fillingInValue = false;
}
2023-01-18 08:39:29 +00:00
2023-01-18 10:16:34 +00:00
stream::ConsumeSpaceAndNewLine(start, end);
2023-01-18 08:39:29 +00:00
continue;
}
}
if (fillingInValue)
2023-01-18 10:16:34 +00:00
value.push_back(*start);
2023-01-18 08:39:29 +00:00
else
2023-01-18 10:16:34 +00:00
key.push_back(*start);
start++;
2023-01-18 08:39:29 +00:00
}
return kv;
}
std::unordered_multimap<std::string, KeyValuesVariant> m_children;
};
2023-01-18 10:16:34 +00:00
template <>
inline StringView KeyValuesVariant::Get() const
{
switch (m_type)
{
case Types::String:
return m_str;
default:
return "";
}
}
2023-01-18 21:28:26 +00:00
// todo josh:
// make the ::Get variant return a result
// return un-resulted version of that with the
// operators
template <>
inline int64_t KeyValuesVariant::Get() const
{
switch (m_type)
{
case Types::String:
return *stream::Parse<int64_t>(m_str);
default:
return 0;
}
}
template <>
inline int32_t KeyValuesVariant::Get() const
{
return Get<int64_t>();
}
template <>
inline float KeyValuesVariant::Get() const
{
switch (m_type)
{
case Types::String:
return *stream::Parse<float>(m_str);
default:
return 0;
}
}
2023-01-18 10:16:34 +00:00
template <>
inline KeyValues& KeyValuesVariant::Get() const
{
switch (m_type)
{
case Types::KeyValues:
{
auto value = m_data.Get<KeyValuesChild>().get();
if (value)
return *value;
}
[[fallthrough]];
default:
return KeyValues::Nothing();
}
}
inline KeyValuesVariant& KeyValuesVariant::operator [](const char *string)
{
if (m_type != Types::KeyValues)
abort();
return Get<kv::KeyValues&>()[string];
}
inline const KeyValuesVariant& KeyValuesVariant::operator [](const char *string) const
{
if (m_type != Types::KeyValues)
abort();
return Get<const kv::KeyValues&>()[string];
}
2023-01-18 21:28:26 +00:00
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator StringView()
2023-01-18 21:28:26 +00:00
{
return Get<StringView>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator int64_t()
2023-01-18 21:28:26 +00:00
{
return Get<int64_t>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator int32_t()
2023-01-18 21:28:26 +00:00
{
return Get<int32_t>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator float()
2023-01-18 21:28:26 +00:00
{
return Get<float>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator double()
2023-01-18 21:28:26 +00:00
{
return Get<double>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator void*()
2023-01-18 21:28:26 +00:00
{
return Get<void*>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator RGBAColor32()
2023-01-18 21:28:26 +00:00
{
return Get<RGBAColor32>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator uint32_t()
2023-01-18 21:28:26 +00:00
{
return Get<uint32_t>();
}
2023-03-24 00:16:39 +00:00
inline KeyValuesVariant::operator uint64_t()
2023-01-18 21:28:26 +00:00
{
return Get<uint64_t>();
}
2023-01-18 08:39:29 +00:00
}