Skip to content

Instantly share code, notes, and snippets.

@CookiePLMonster
Last active May 16, 2021 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CookiePLMonster/fb390e2bf48864e0cf54fdee779f2fa1 to your computer and use it in GitHub Desktop.
Save CookiePLMonster/fb390e2bf48864e0cf54fdee779f2fa1 to your computer and use it in GitHub Desktop.
Simple VDF (Valve Data Format) parser
#pragma once
#include <fstream>
#include <istream>
#include <iomanip>
#include <memory>
#include <unordered_map>
#include <variant>
class VDFParser
{
public:
class DataNode;
using SubkeyType = std::unordered_map<std::string, const DataNode>;
class DataNode : std::variant<std::string, SubkeyType>
{
public:
const DataNode& operator[](const std::string key) const
{
return std::get<SubkeyType>(*this).at(key);
}
void SetString(std::string val)
{
*static_cast<std::variant<std::string, SubkeyType>*>(this) = std::move(val);
}
void SetSubkey(SubkeyType val)
{
*static_cast<std::variant<std::string, SubkeyType>*>(this) = std::move(val);
}
auto Value() const
{
std::string val;
if (auto* ptr = std::get_if<std::string>(this); ptr != nullptr)
{
val = *ptr;
}
return val;
}
};
static SubkeyType Load(const wchar_t* fileName)
{
SubkeyType result;
std::ifstream file(fileName);
if (file)
{
result = ReadSubkey(file);
}
return result;
}
private:
static SubkeyType ReadSubkey(std::istream& stream)
{
SubkeyType result;
while (stream.good())
{
stream >> std::ws;
int ch = stream.peek(); // TODO: EOF?
if (ch == '"')
{
std::string key;
stream >> std::quoted(key);
result.emplace(std::move(key), ReadValue(stream));
}
else if (ch == '}')
{
stream.ignore(); // Advance past the closing bracket
break;
}
}
return result;
}
static DataNode ReadValue(std::istream& stream)
{
DataNode result;
stream >> std::ws;
int ch = stream.peek(); // TODO: EOF?
if (ch == '"')
{
std::string value;
stream >> std::quoted(value);
result.SetString(std::move(value));
}
else if (ch == '{')
{
stream.ignore(); // Advance past the opening bracket
result.SetSubkey(ReadSubkey(stream));
}
return result;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment