This commit is contained in:
Joshua Ashton 2023-01-18 10:16:34 +00:00
parent 1f17ee7fbb
commit 11d3111ec1
7 changed files with 174 additions and 29 deletions

View File

@ -68,6 +68,11 @@ namespace orange::stream
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>>
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;
}
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;
}
}

View File

@ -3,6 +3,7 @@
#include <Orange/Core/Types.h>
#include <string>
#include <cstring>
#include <iostream>
namespace orange
{
@ -80,6 +81,13 @@ namespace orange
: 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
{
using BufferView::BufferView;

View File

@ -13,7 +13,7 @@ namespace orange
SmallVector() {}
SmallVector(size_t size) { resize(size); }
SmallVector(Span<T> span)
SmallVector(Span<const T> span)
{
reserve(span.size);
for (const auto& val : span)
@ -38,6 +38,7 @@ namespace orange
reserve(x.size());
for (const auto& val : x)
push_back(val);
return *this;
}
~SmallVector()

View File

@ -1,6 +1,7 @@
#pragma once
#include <Orange/Core/Variant.h>
#include <Orange/Core/Vector.h>
#include <Orange/Core/Parse.h>
#include <Orange/Core/Span.h>
#include <Orange/Graphics/Color.h>
@ -33,10 +34,12 @@ namespace orange::kv
class KeyValues;
class KeyValuesVariant
{
public:
using KeyValuesChild = std::unique_ptr<KeyValues>;
using KeyValuesString = SmallVector<char, 8>;
KeyValuesVariant()
{
@ -64,7 +67,7 @@ namespace orange::kv
switch (m_type)
{
case Types::String:
m_data.Destruct<std::string>();
m_str.clear();
break;
case Types::KeyValues:
m_data.Destruct<KeyValuesChild>();
@ -76,19 +79,11 @@ namespace orange::kv
m_data.Clear();
}
std::string GetString() const
{
switch (m_type)
{
case Types::String:
return m_data.Get<std::string>();
default:
return "";
}
}
template <typename T>
T Get() const;
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(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 }; }
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; }
@ -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(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); }
KeyValuesVariant& operator [](const char *string);
const KeyValuesVariant& operator [](const char *string) const;
static KeyValuesVariant& GetEmptyValue() { return s_Nothing; }
private:
static KeyValuesVariant s_Nothing;
KeyValuesType m_type = Types::None;
KeyValuesString m_str;
Variant<
std::string,
int64_t,
double,
void*,
@ -120,7 +124,38 @@ namespace orange::kv
const char *end = buffer.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:
static KeyValues s_Nothing;
static std::unique_ptr<KeyValues> ParseChild(const char*& start, const char* end)
{
StringView range = StringView(start, end);
@ -128,12 +163,12 @@ namespace orange::kv
if (start == end)
return nullptr;
stream::ConsumeSpace(start, end);
stream::ConsumeSpaceAndNewLine(start, end);
if (*start != '{')
return nullptr;
auto kv = std::unique_ptr<KeyValues>();
auto kv = std::make_unique<KeyValues>();
bool inString = false;
@ -141,21 +176,31 @@ namespace orange::kv
std::string key;
std::string value;
start++;
while (start != end)
{
start++;
if (stream::IsStringToken(range, start))
{
inString = !inString;
start++;
continue;
}
if (!inString)
{
if (*start == '\r')
if (stream::IsCPPComment(range, start))
{
stream::AdvancePast(start, end, "\r\n");
stream::ConsumeSpaceAndNewLine(start, end);
continue;
}
if (*start == '{')
{
fprintf(stdout, "Adding block child: %s - {\n", key.c_str());
auto child = ParseChild(start, end);
kv->m_children.emplace(key, Move(child));
fprintf(stdout, "Adding block child: }\n");
fillingInValue = false;
key.clear();
@ -168,30 +213,33 @@ namespace orange::kv
break;
}
if (*start == ' ' || *start == '\t' || *start == '\n')
if (*start == ' ' || *start == '\t' || *start == '\n' || *start == '\r')
{
fillingInValue = !fillingInValue;
if (!fillingInValue)
{
fillingInValue = true;
}
else
{
fprintf(stdout, "Adding child: %s - %s\n", key.c_str(), value.c_str());
kv->m_children.emplace(key, value);
fillingInValue = false;
key.clear();
value.clear();
}
else if (*start == '\n' || *start == '\r')
{
fillingInValue = false;
}
stream::ConsumeSpace(start, end);
stream::ConsumeSpaceAndNewLine(start, end);
continue;
}
}
if (fillingInValue)
value += *start;
value.push_back(*start);
else
key += *start;
key.push_back(*start);
start++;
}
return kv;
@ -199,4 +247,49 @@ namespace orange::kv
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];
}
}

View File

@ -283,6 +283,21 @@ int main(int argc, char** argv)
std::cout << std::endl;
#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 newIndexSlice = *pooler.AllocSlice(sizeof(IndexType) * r_mesh->indices.size(), sizeof(IndexType));
r_mesh->vertexData.GetStaticVertices().copy((uint8_t*)(r_buffer->ptr) + newVertexSlice.offset);

View File

@ -0,0 +1,7 @@
#include <Orange/Formats/KeyValues.h>
namespace orange::kv
{
KeyValuesVariant KeyValuesVariant::s_Nothing;
KeyValues KeyValues::s_Nothing;
}

View File

@ -11,6 +11,8 @@ orange_src = files([
'Core/Filesystem.cpp',
'Core/Log.cpp',
'Formats/KeyValues.cpp',
'Graphics/Mesh.cpp',
'Render/Input.cpp',