KV work
This commit is contained in:
parent
1f17ee7fbb
commit
11d3111ec1
|
@ -68,6 +68,11 @@ namespace orange::stream
|
||||||
return Consume(first, end, " \t");
|
return Consume(first, end, " \t");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t ConsumeSpaceAndNewLine(const char*& first, const char* end)
|
||||||
|
{
|
||||||
|
return Consume(first, end, " \t\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
template <typename OutArray = SmallVector<char, 1>>
|
template <typename OutArray = SmallVector<char, 1>>
|
||||||
size_t ReadOrAdvance(const char*& first, const char* end, StringView delims, size_t advancement = 0, OutArray* array = nullptr)
|
size_t ReadOrAdvance(const char*& first, const char* end, StringView delims, size_t advancement = 0, OutArray* array = nullptr)
|
||||||
{
|
{
|
||||||
|
@ -118,4 +123,18 @@ namespace orange::stream
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsCPPComment(StringView fullRange, const char* first)
|
||||||
|
{
|
||||||
|
if (*first != '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fullRange.end() == first + 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*(first + 1) != '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Orange/Core/Types.h>
|
#include <Orange/Core/Types.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace orange
|
namespace orange
|
||||||
{
|
{
|
||||||
|
@ -80,6 +81,13 @@ namespace orange
|
||||||
: Span<const char>{str, strlen(str)} {}
|
: Span<const char>{str, strlen(str)} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator << (std::ostream& os, StringView view)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < view.size; i++)
|
||||||
|
os << view[i];
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
struct Buffer : public BufferView
|
struct Buffer : public BufferView
|
||||||
{
|
{
|
||||||
using BufferView::BufferView;
|
using BufferView::BufferView;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace orange
|
||||||
|
|
||||||
SmallVector() {}
|
SmallVector() {}
|
||||||
SmallVector(size_t size) { resize(size); }
|
SmallVector(size_t size) { resize(size); }
|
||||||
SmallVector(Span<T> span)
|
SmallVector(Span<const T> span)
|
||||||
{
|
{
|
||||||
reserve(span.size);
|
reserve(span.size);
|
||||||
for (const auto& val : span)
|
for (const auto& val : span)
|
||||||
|
@ -38,6 +38,7 @@ namespace orange
|
||||||
reserve(x.size());
|
reserve(x.size());
|
||||||
for (const auto& val : x)
|
for (const auto& val : x)
|
||||||
push_back(val);
|
push_back(val);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~SmallVector()
|
~SmallVector()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Orange/Core/Variant.h>
|
#include <Orange/Core/Variant.h>
|
||||||
|
#include <Orange/Core/Vector.h>
|
||||||
#include <Orange/Core/Parse.h>
|
#include <Orange/Core/Parse.h>
|
||||||
#include <Orange/Core/Span.h>
|
#include <Orange/Core/Span.h>
|
||||||
#include <Orange/Graphics/Color.h>
|
#include <Orange/Graphics/Color.h>
|
||||||
|
@ -33,10 +34,12 @@ namespace orange::kv
|
||||||
|
|
||||||
class KeyValues;
|
class KeyValues;
|
||||||
|
|
||||||
|
|
||||||
class KeyValuesVariant
|
class KeyValuesVariant
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using KeyValuesChild = std::unique_ptr<KeyValues>;
|
using KeyValuesChild = std::unique_ptr<KeyValues>;
|
||||||
|
using KeyValuesString = SmallVector<char, 8>;
|
||||||
|
|
||||||
KeyValuesVariant()
|
KeyValuesVariant()
|
||||||
{
|
{
|
||||||
|
@ -64,7 +67,7 @@ namespace orange::kv
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case Types::String:
|
case Types::String:
|
||||||
m_data.Destruct<std::string>();
|
m_str.clear();
|
||||||
break;
|
break;
|
||||||
case Types::KeyValues:
|
case Types::KeyValues:
|
||||||
m_data.Destruct<KeyValuesChild>();
|
m_data.Destruct<KeyValuesChild>();
|
||||||
|
@ -76,19 +79,11 @@ namespace orange::kv
|
||||||
m_data.Clear();
|
m_data.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetString() const
|
template <typename T>
|
||||||
{
|
T Get() 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(const std::string& val) { Clear(); m_type = Types::String; m_str = KeyValuesString{ StringView{ val } }; }
|
||||||
void Set(StringView val) { Clear(); m_type = Types::String; m_data.Construct<std::string>(val.data, val.data + val.size); }
|
void Set(StringView val) { Clear(); m_type = Types::String; m_str = KeyValuesString{ val }; }
|
||||||
void Set(int32_t val) { Clear(); m_type = Types::Int; m_data.Get<int64_t>() = val; }
|
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(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(float val) { Clear(); m_type = Types::Float; m_data.Get<double>() = val; }
|
||||||
|
@ -98,11 +93,20 @@ namespace orange::kv
|
||||||
void Set(uint32_t val) { Clear(); m_type = Types::Uint64; m_data.Get<uint64_t>() = 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(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); }
|
void Set(KeyValuesChild val) { Clear(); m_type = Types::KeyValues; m_data.Get<KeyValuesChild>() = Move(val); }
|
||||||
|
|
||||||
|
KeyValuesVariant& operator [](const char *string);
|
||||||
|
|
||||||
|
const KeyValuesVariant& operator [](const char *string) const;
|
||||||
|
|
||||||
|
static KeyValuesVariant& GetEmptyValue() { return s_Nothing; }
|
||||||
private:
|
private:
|
||||||
|
static KeyValuesVariant s_Nothing;
|
||||||
|
|
||||||
KeyValuesType m_type = Types::None;
|
KeyValuesType m_type = Types::None;
|
||||||
|
|
||||||
|
KeyValuesString m_str;
|
||||||
|
|
||||||
Variant<
|
Variant<
|
||||||
std::string,
|
|
||||||
int64_t,
|
int64_t,
|
||||||
double,
|
double,
|
||||||
void*,
|
void*,
|
||||||
|
@ -120,7 +124,38 @@ namespace orange::kv
|
||||||
const char *end = buffer.end();
|
const char *end = buffer.end();
|
||||||
return ParseChild(start, end);
|
return ParseChild(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
static KeyValues s_Nothing;
|
||||||
|
|
||||||
static std::unique_ptr<KeyValues> ParseChild(const char*& start, const char* end)
|
static std::unique_ptr<KeyValues> ParseChild(const char*& start, const char* end)
|
||||||
{
|
{
|
||||||
StringView range = StringView(start, end);
|
StringView range = StringView(start, end);
|
||||||
|
@ -128,12 +163,12 @@ namespace orange::kv
|
||||||
if (start == end)
|
if (start == end)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
stream::ConsumeSpace(start, end);
|
stream::ConsumeSpaceAndNewLine(start, end);
|
||||||
|
|
||||||
if (*start != '{')
|
if (*start != '{')
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto kv = std::unique_ptr<KeyValues>();
|
auto kv = std::make_unique<KeyValues>();
|
||||||
|
|
||||||
bool inString = false;
|
bool inString = false;
|
||||||
|
|
||||||
|
@ -141,21 +176,31 @@ namespace orange::kv
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
|
start++;
|
||||||
while (start != end)
|
while (start != end)
|
||||||
{
|
{
|
||||||
start++;
|
|
||||||
if (stream::IsStringToken(range, start))
|
if (stream::IsStringToken(range, start))
|
||||||
|
{
|
||||||
inString = !inString;
|
inString = !inString;
|
||||||
|
start++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!inString)
|
if (!inString)
|
||||||
{
|
{
|
||||||
if (*start == '\r')
|
if (stream::IsCPPComment(range, start))
|
||||||
|
{
|
||||||
|
stream::AdvancePast(start, end, "\r\n");
|
||||||
|
stream::ConsumeSpaceAndNewLine(start, end);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (*start == '{')
|
if (*start == '{')
|
||||||
{
|
{
|
||||||
|
fprintf(stdout, "Adding block child: %s - {\n", key.c_str());
|
||||||
auto child = ParseChild(start, end);
|
auto child = ParseChild(start, end);
|
||||||
kv->m_children.emplace(key, Move(child));
|
kv->m_children.emplace(key, Move(child));
|
||||||
|
fprintf(stdout, "Adding block child: }\n");
|
||||||
|
|
||||||
fillingInValue = false;
|
fillingInValue = false;
|
||||||
key.clear();
|
key.clear();
|
||||||
|
@ -168,30 +213,33 @@ namespace orange::kv
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*start == ' ' || *start == '\t' || *start == '\n')
|
if (*start == ' ' || *start == '\t' || *start == '\n' || *start == '\r')
|
||||||
{
|
{
|
||||||
|
fillingInValue = !fillingInValue;
|
||||||
|
|
||||||
if (!fillingInValue)
|
if (!fillingInValue)
|
||||||
{
|
{
|
||||||
fillingInValue = true;
|
fprintf(stdout, "Adding child: %s - %s\n", key.c_str(), value.c_str());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kv->m_children.emplace(key, value);
|
kv->m_children.emplace(key, value);
|
||||||
|
|
||||||
fillingInValue = false;
|
|
||||||
key.clear();
|
key.clear();
|
||||||
value.clear();
|
value.clear();
|
||||||
}
|
}
|
||||||
|
else if (*start == '\n' || *start == '\r')
|
||||||
|
{
|
||||||
|
fillingInValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
stream::ConsumeSpace(start, end);
|
stream::ConsumeSpaceAndNewLine(start, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fillingInValue)
|
if (fillingInValue)
|
||||||
value += *start;
|
value.push_back(*start);
|
||||||
else
|
else
|
||||||
key += *start;
|
key.push_back(*start);
|
||||||
|
|
||||||
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return kv;
|
return kv;
|
||||||
|
@ -199,4 +247,49 @@ namespace orange::kv
|
||||||
|
|
||||||
std::unordered_multimap<std::string, KeyValuesVariant> m_children;
|
std::unordered_multimap<std::string, KeyValuesVariant> m_children;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline StringView KeyValuesVariant::Get() const
|
||||||
|
{
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
case Types::String:
|
||||||
|
return m_str;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,21 @@ int main(int argc, char** argv)
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto r_vmf = fs::OpenFileIntoTextBuffer("/home/joshua/Code/Desolation/game/sdk_content/maps/hl2_sdk/sdk_phys_constraint.vmf");
|
||||||
|
|
||||||
|
auto r_vmfkv = kv::KeyValues::ParseFromUTF8(*r_vmf);
|
||||||
|
if (!r_vmfkv)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Parsing VMF failed!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kv::KeyValues &vmfkv = *r_vmfkv;
|
||||||
|
|
||||||
|
std::cout << "editorversion: " << vmfkv["versioninfo"]["editorversion"].Get<StringView>() << std::endl;
|
||||||
|
|
||||||
|
|
||||||
auto newVertexSlice = *pooler.AllocSlice(sizeof(StaticVertex) * r_mesh->vertexData.VertexCount(), sizeof(StaticVertex));
|
auto newVertexSlice = *pooler.AllocSlice(sizeof(StaticVertex) * r_mesh->vertexData.VertexCount(), sizeof(StaticVertex));
|
||||||
auto newIndexSlice = *pooler.AllocSlice(sizeof(IndexType) * r_mesh->indices.size(), sizeof(IndexType));
|
auto newIndexSlice = *pooler.AllocSlice(sizeof(IndexType) * r_mesh->indices.size(), sizeof(IndexType));
|
||||||
r_mesh->vertexData.GetStaticVertices().copy((uint8_t*)(r_buffer->ptr) + newVertexSlice.offset);
|
r_mesh->vertexData.GetStaticVertices().copy((uint8_t*)(r_buffer->ptr) + newVertexSlice.offset);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <Orange/Formats/KeyValues.h>
|
||||||
|
|
||||||
|
namespace orange::kv
|
||||||
|
{
|
||||||
|
KeyValuesVariant KeyValuesVariant::s_Nothing;
|
||||||
|
KeyValues KeyValues::s_Nothing;
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ orange_src = files([
|
||||||
'Core/Filesystem.cpp',
|
'Core/Filesystem.cpp',
|
||||||
'Core/Log.cpp',
|
'Core/Log.cpp',
|
||||||
|
|
||||||
|
'Formats/KeyValues.cpp',
|
||||||
|
|
||||||
'Graphics/Mesh.cpp',
|
'Graphics/Mesh.cpp',
|
||||||
|
|
||||||
'Render/Input.cpp',
|
'Render/Input.cpp',
|
||||||
|
|
Loading…
Reference in New Issue