Last active
October 5, 2023 13:20
-
-
Save romgerman/dd0ee6cf744ac8b6054623fd143200d2 to your computer and use it in GitHub Desktop.
Simple Valve Key Values parser in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ValveKeyValue.h" | |
using namespace Parsers; | |
#include <exception> | |
#include <cctype> | |
ValveKeyValue::Token ValveKeyValue::LexNext() | |
{ | |
bool readingValue = false; | |
bool readingRawValue = false; | |
bool readingComment = false; | |
std::string value = ""; | |
while (m_lexPos < m_source.size()) | |
{ | |
if (readingComment) | |
{ | |
if (m_source[m_lexPos] == '\n') | |
readingComment = false; | |
m_lexPos++; | |
continue; | |
} | |
if (readingValue || readingRawValue) | |
{ | |
/*if (m_source[m_lexPos] != '"' && | |
m_source[m_lexPos] != '{' && | |
m_source[m_lexPos] != ' ' && | |
m_source[m_lexPos] != '\t' && | |
m_source[m_lexPos] != '\r' && | |
m_source[m_lexPos] != '\n')*/ | |
if ((readingRawValue && isalnum(m_source[m_lexPos])) || (readingValue && m_source[m_lexPos] != '"')) | |
{ | |
value += m_source[m_lexPos]; | |
m_lexPos++; | |
continue; | |
} | |
else | |
{ | |
readingValue = false; | |
m_lexPos++; | |
return Token(TokenTypes::Value, value); | |
} | |
} | |
if (m_source[m_lexPos] == '"') // read value | |
{ | |
readingValue = true; | |
value = ""; | |
m_lexPos++; | |
} | |
else if (m_source[m_lexPos] == '{') | |
{ | |
m_lexPos++; | |
return Token(TokenTypes::BraceOpen, ""); | |
} | |
else if (m_source[m_lexPos] == '}') | |
{ | |
m_lexPos++; | |
return Token(TokenTypes::BraceClose, ""); | |
} | |
else if (m_source[m_lexPos] == '/') | |
{ | |
if (readingValue) | |
{ | |
value += m_source[m_lexPos]; | |
m_lexPos++; | |
} | |
else | |
{ | |
readingComment = true; | |
m_lexPos++; | |
} | |
} | |
else if (m_source[m_lexPos] == ' ' || | |
m_source[m_lexPos] == '\t' || | |
m_source[m_lexPos] == '\n' || | |
m_source[m_lexPos] == '\r') | |
{ | |
m_lexPos++; | |
} | |
else | |
{ | |
if (!isdigit(m_source[m_lexPos])) | |
{ | |
readingRawValue = true; | |
value = ""; | |
} | |
} | |
} | |
return Token(TokenTypes::End, ""); | |
} | |
void ValveKeyValue::Parse() | |
{ | |
//m_current = &data; | |
Token tok = LexNext(); | |
while (tok.type != TokenTypes::End) | |
{ | |
switch (tok.type) | |
{ | |
case TokenTypes::Value: | |
LexNext(); // Eat { | |
ParseBlock(tok, data); | |
tok = LexNext(); | |
break; | |
default: | |
throw std::exception("Unexpected token. File is invalid"); | |
break; | |
} | |
} | |
} | |
void Parsers::ValveKeyValue::ParseBlock(Token& name, KeyValue& container) | |
{ | |
Token token = LexNext(); | |
auto values = KeyValue(); | |
while (token.type != TokenTypes::BraceClose) | |
{ | |
auto key = token; | |
auto value = LexNext(); | |
if (value.type != TokenTypes::BraceOpen) | |
{ | |
values.values.emplace(key.value, value.value); | |
} | |
else | |
{ | |
auto newdata = KeyValue(); | |
ParseBlock(key, newdata); | |
values.keys.emplace(key.value, newdata); | |
} | |
token = LexNext(); | |
} | |
container.keys.emplace(name.value, values); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <map> | |
namespace Parsers | |
{ | |
class ValveKeyValue | |
{ | |
public: | |
struct KeyValue | |
{ | |
std::map<std::string, std::string> values; | |
std::map<std::string, KeyValue> keys; | |
//std::string GetValue(); | |
//KeyValue GetKey(); | |
}; | |
public: | |
KeyValue data; | |
private: | |
enum class TokenTypes | |
{ | |
Value, BraceOpen, BraceClose, End | |
}; | |
struct Token | |
{ | |
TokenTypes type; | |
std::string value; | |
Token(TokenTypes ttype, std::string tvalue) | |
{ | |
this->type = ttype; | |
this->value = tvalue; | |
} | |
}; | |
private: | |
Token LexNext(); // Do not support in-line comments | |
void Parse(); | |
void ParseBlock(Token& name, KeyValue& container); | |
public: | |
ValveKeyValue() { } | |
~ValveKeyValue() { } | |
void Read(std::string& str) | |
{ | |
m_source = str; | |
m_lexPos = 0; | |
Parse(); | |
} | |
private: | |
std::string m_source; | |
size_t m_lexPos; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment