Initial work on KV parser
This commit is contained in:
parent
d6b03da52e
commit
5fcef94559
|
@ -98,4 +98,24 @@ namespace orange::stream
|
||||||
{
|
{
|
||||||
return ReadOrAdvance(first, end, delims, 1);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Orange/Core/Types.h>
|
#include <Orange/Core/Types.h>
|
||||||
#include <string.h>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace orange
|
namespace orange
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Span
|
struct Span
|
||||||
{
|
{
|
||||||
|
Span(std::nullptr_t) : data(nullptr), size(0) {}
|
||||||
|
|
||||||
Span(T* data, size_t size) : data(data), size(size) {}
|
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>
|
template <size_t Count>
|
||||||
Span(T (&array)[Count]) : data(array), size(Count) {}
|
Span(T (&array)[Count]) : data(array), size(Count) {}
|
||||||
|
|
||||||
|
@ -68,6 +73,9 @@ namespace orange
|
||||||
{
|
{
|
||||||
using Span<const char>::Span;
|
using Span<const char>::Span;
|
||||||
|
|
||||||
|
StringView(const std::string& string)
|
||||||
|
: Span<const char>(string.data(), string.length()) {}
|
||||||
|
|
||||||
StringView(const char* str)
|
StringView(const char* str)
|
||||||
: Span<const char>{str, strlen(str)} {}
|
: Span<const char>{str, strlen(str)} {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <Orange/Core/AlignedStorage.h>
|
#include <Orange/Core/AlignedStorage.h>
|
||||||
#include <Orange/Core/Traits.h>
|
#include <Orange/Core/Traits.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace orange
|
namespace orange
|
||||||
{
|
{
|
||||||
|
@ -19,13 +20,24 @@ namespace orange
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
Variant(Args&&... args)
|
Variant(Args&&... args)
|
||||||
{
|
{
|
||||||
Construct<T>(Forward(args)...);
|
Construct<T>(Forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
void Construct(Args&&... 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); }
|
template <typename T> T* Ptr() { return reinterpret_cast<T*> (data.data); }
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -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>;
|
||||||
|
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ namespace orange
|
||||||
return GetSkinnedVertices();
|
return GetSkinnedVertices();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return BufferView{ nullptr, 0 };
|
return BufferView{ nullptr };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <Orange/Render/Swapchain.h>
|
#include <Orange/Render/Swapchain.h>
|
||||||
#include <Orange/Render/VulkanHelpers.h>
|
#include <Orange/Render/VulkanHelpers.h>
|
||||||
#include <Orange/Render/Window.h>
|
#include <Orange/Render/Window.h>
|
||||||
|
#include <Orange/Formats/KeyValues.h>
|
||||||
|
|
||||||
#include <vs_Mesh.h>
|
#include <vs_Mesh.h>
|
||||||
#include <vs_Fullscreen.h>
|
#include <vs_Fullscreen.h>
|
||||||
|
@ -481,7 +482,7 @@ int main(int argc, char** argv)
|
||||||
.depthFormat = depthFormat,
|
.depthFormat = depthFormat,
|
||||||
.enableDepthTest = false,
|
.enableDepthTest = false,
|
||||||
.enableDepthWrites = false,
|
.enableDepthWrites = false,
|
||||||
.vertexAttributes = Span<const VkVertexInputAttributeDescription>(nullptr, 0),
|
.vertexAttributes = Span<const VkVertexInputAttributeDescription>(nullptr),
|
||||||
});
|
});
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ namespace orange
|
||||||
|
|
||||||
std::unordered_map<StaticVertex, IndexType, StaticVertexHash> indexTracker;
|
std::unordered_map<StaticVertex, IndexType, StaticVertexHash> indexTracker;
|
||||||
|
|
||||||
const char* obj = buffer.data;
|
const char* obj = buffer.begin();
|
||||||
const char* end = buffer.data + buffer.size;
|
const char* end = buffer.end();
|
||||||
while (obj != end)
|
while (obj != end)
|
||||||
{
|
{
|
||||||
SmallVector<char, 8> element;
|
SmallVector<char, 8> element;
|
||||||
|
|
Loading…
Reference in New Issue