Initial work on KV parser

This commit is contained in:
Joshua Ashton 2023-01-18 08:39:29 +00:00
parent d6b03da52e
commit 5fcef94559
8 changed files with 307 additions and 8 deletions

View File

@ -98,4 +98,24 @@ namespace orange::stream
{
return ReadOrAdvance(first, end, delims, 1);
}
inline bool IsStringToken(StringView fullRange, const char* first)
{
if (*first != '"')
return false;
// Make sure we are in-range for the checks below.
if (fullRange.begin() == first || fullRange.begin() == first - 1)
return true;
// Handle \\"
if (*(first - 2) == '\\')
return true;
// Hanle \"
if (*(first - 1) == '\\')
return false;
return true;
}
}

View File

@ -1,15 +1,20 @@
#pragma once
#include <Orange/Core/Types.h>
#include <string.h>
#include <string>
#include <cstring>
namespace orange
{
template <typename T>
struct Span
{
Span(std::nullptr_t) : data(nullptr), size(0) {}
Span(T* data, size_t size) : data(data), size(size) {}
Span(T* begin, T* end) : data(begin), size(uintptr_t(end) - uintptr_t(begin)) {}
template <size_t Count>
Span(T (&array)[Count]) : data(array), size(Count) {}
@ -68,6 +73,9 @@ namespace orange
{
using Span<const char>::Span;
StringView(const std::string& string)
: Span<const char>(string.data(), string.length()) {}
StringView(const char* str)
: Span<const char>{str, strlen(str)} {}
};

View File

@ -2,6 +2,7 @@
#include <Orange/Core/AlignedStorage.h>
#include <Orange/Core/Traits.h>
#include <cstring>
namespace orange
{
@ -11,7 +12,7 @@ namespace orange
public:
static constexpr size_t MaxElementSize = Max({sizeof(Types)...});
static constexpr size_t Alignment = Max({alignof(Types)...});
explicit Variant()
{
}
@ -19,13 +20,24 @@ namespace orange
template <typename T, typename... Args>
Variant(Args&&... args)
{
Construct<T>(Forward(args)...);
Construct<T>(Forward<Args>(args)...);
}
template <typename T, typename... Args>
void Construct(Args&&... args)
{
new (Ptr<T>()) T(Forward(args)...);
new (Ptr<T>()) T(Forward<Args>(args)...);
}
template <typename T>
void Destruct()
{
Ptr<T>()->~T();
}
void Clear()
{
std::memset(&data, 0, sizeof(data));
}
template <typename T> T* Ptr() { return reinterpret_cast<T*> (data.data); }

View File

@ -0,0 +1,202 @@
#pragma once
#include <Orange/Core/Variant.h>
#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;
class KeyValuesVariant
{
public:
using KeyValuesChild = std::unique_ptr<KeyValues>;
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:
m_data.Destruct<std::string>();
break;
case Types::KeyValues:
m_data.Destruct<KeyValuesChild>();
break;
default:
break;
}
m_type = Types::None;
m_data.Clear();
}
std::string GetString() const
{
switch (m_type)
{
case Types::String:
return m_data.Get<std::string>();
default:
return "";
}
}
void Set(const std::string& val) { Clear(); m_type = Types::String; m_data.Construct<std::string>(val); }
void Set(StringView val) { Clear(); m_type = Types::String; m_data.Construct<std::string>(val.data, val.data + val.size); }
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); }
private:
KeyValuesType m_type = Types::None;
Variant<
std::string,
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);
}
private:
static std::unique_ptr<KeyValues> ParseChild(const char*& start, const char* end)
{
StringView range = StringView(start, end);
if (start == end)
return nullptr;
stream::ConsumeSpace(start, end);
if (*start != '{')
return nullptr;
auto kv = std::unique_ptr<KeyValues>();
bool inString = false;
bool fillingInValue = false;
std::string key;
std::string value;
while (start != end)
{
start++;
if (stream::IsStringToken(range, start))
inString = !inString;
if (!inString)
{
if (*start == '\r')
continue;
if (*start == '{')
{
auto child = ParseChild(start, end);
kv->m_children.emplace(key, Move(child));
fillingInValue = false;
key.clear();
value.clear();
}
if (*start == '}')
{
start++;
break;
}
if (*start == ' ' || *start == '\t' || *start == '\n')
{
if (!fillingInValue)
{
fillingInValue = true;
}
else
{
kv->m_children.emplace(key, value);
fillingInValue = false;
key.clear();
value.clear();
}
stream::ConsumeSpace(start, end);
continue;
}
}
if (fillingInValue)
value += *start;
else
key += *start;
}
return kv;
}
std::unordered_multimap<std::string, KeyValuesVariant> m_children;
};
}

View File

@ -0,0 +1,56 @@
#pragma once
#include <cstdint>
#include <array>
#include <limits>
namespace orange
{
template <typename T>
struct RGBAColor
{
static constexpr T NormalizedMinValue = T{};
static constexpr T NormalizedMaxValue = T{ std::is_floating_point<T>::value ? 1.0 : std::numeric_limits<T>::max() };
static constexpr T PackScale = NormalizedMaxValue / T{ 255 };
explicit RGBAColor(T r, T g, T b, T a)
: r{r}, g{g}, b{b}, a{a}
{
}
explicit RGBAColor(T r, T g, T b)
: RGBAColor{ r, g, b, NormalizedMaxValue }
{
}
explicit RGBAColor(uint32_t rgba)
: RGBAColor{ ((rgba >> 24u) & 0xFFu) * PackScale,
((rgba >> 16u) & 0xFFu) * PackScale,
((rgba >> 8u) & 0xFFu) * PackScale,
((rgba >> 0u) & 0xFFu) * PackScale }
{
}
uint32_t pack()
{
return uint32_t{ std::clamp(r / PackScale, T{ 0 }, T { 255 }) } << 24u |
uint32_t{ std::clamp(g / PackScale, T{ 0 }, T { 255 }) } << 16u |
uint32_t{ std::clamp(b / PackScale, T{ 0 }, T { 255 }) } << 8u |
uint32_t{ std::clamp(a / PackScale, T{ 0 }, T { 255 }) } << 0u;
}
union
{
std::array<T, 4> data;
struct
{
T r, g, b, a;
};
};
};
using RGBAColor32 = RGBAColor<uint8_t>;
using RGBAColorFloat = RGBAColor<float>;
}

View File

@ -57,7 +57,7 @@ namespace orange
return GetSkinnedVertices();
break;
default:
return BufferView{ nullptr, 0 };
return BufferView{ nullptr };
}
}

View File

@ -14,6 +14,7 @@
#include <Orange/Render/Swapchain.h>
#include <Orange/Render/VulkanHelpers.h>
#include <Orange/Render/Window.h>
#include <Orange/Formats/KeyValues.h>
#include <vs_Mesh.h>
#include <vs_Fullscreen.h>
@ -481,7 +482,7 @@ int main(int argc, char** argv)
.depthFormat = depthFormat,
.enableDepthTest = false,
.enableDepthWrites = false,
.vertexAttributes = Span<const VkVertexInputAttributeDescription>(nullptr, 0),
.vertexAttributes = Span<const VkVertexInputAttributeDescription>(nullptr),
});
#pragma endregion

View File

@ -29,8 +29,8 @@ namespace orange
std::unordered_map<StaticVertex, IndexType, StaticVertexHash> indexTracker;
const char* obj = buffer.data;
const char* end = buffer.data + buffer.size;
const char* obj = buffer.begin();
const char* end = buffer.end();
while (obj != end)
{
SmallVector<char, 8> element;