toml::Wrapper removed

This commit is contained in:
MihailRis
2024-04-28 17:23:52 +03:00
parent 184ecd88ba
commit c3b5576c02
22 changed files with 795 additions and 965 deletions
+323 -320
View File
@@ -1,320 +1,323 @@
#include "commons.h"
#include "../util/stringutil.h"
#include <sstream>
#include <stdexcept>
#include <math.h>
inline double power(double base, int64_t power) {
double result = 1.0;
for (int64_t i = 0; i < power; i++) {
result *= base;
}
return result;
}
parsing_error::parsing_error(
std::string message,
std::string filename,
std::string source,
uint pos,
uint line,
uint linestart)
: std::runtime_error(message), filename(filename), source(source),
pos(pos), line(line), linestart(linestart) {
}
std::string parsing_error::errorLog() const {
std::stringstream ss;
uint linepos = pos - linestart;
ss << "parsing error in file '" << filename;
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
size_t end = source.find("\n", linestart);
if (end == std::string::npos) {
end = source.length();
}
ss << source.substr(linestart, end-linestart) << "\n";
for (uint i = 0; i < linepos; i++) {
ss << " ";
}
ss << "^";
return ss.str();
}
BasicParser::BasicParser(std::string file, std::string source) : filename(file), source(source) {
}
void BasicParser::skipWhitespace() {
while (hasNext()) {
char next = source[pos];
if (next == '\n') {
line++;
linestart = ++pos;
continue;
}
if (is_whitespace(next)) {
pos++;
} else {
break;
}
}
}
void BasicParser::skip(size_t n) {
n = std::min(n, source.length()-pos);
for (size_t i = 0; i < n; i++) {
char next = source[pos++];
if (next == '\n') {
line++;
linestart = pos;
}
}
}
void BasicParser::skipLine() {
while (hasNext()) {
if (source[pos] == '\n') {
pos++;
linestart = pos;
line++;
break;
}
pos++;
}
}
bool BasicParser::skipTo(const std::string& substring) {
size_t idx = source.find(substring, pos);
if (idx == std::string::npos) {
skip(source.length()-pos);
return false;
} else {
skip(idx-pos);
return true;
}
}
bool BasicParser::hasNext() {
return pos < source.length();
}
bool BasicParser::isNext(const std::string& substring) {
if (source.length() - pos < substring.length()) {
return false;
}
return source.substr(pos, substring.length()) == substring;
}
char BasicParser::nextChar() {
if (!hasNext()) {
throw error("unexpected end");
}
return source[pos++];
}
void BasicParser::expect(char expected) {
char c = peek();
if (c != expected) {
throw error("'"+std::string({expected})+"' expected");
}
pos++;
}
void BasicParser::expect(const std::string& substring) {
if (substring.empty())
return;
for (uint i = 0; i < substring.length(); i++) {
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
throw error(util::quote(substring)+" expected");
}
}
pos += substring.length();
}
void BasicParser::expectNewLine() {
while (hasNext()) {
char next = source[pos];
if (next == '\n') {
line++;
linestart = ++pos;
return;
}
if (is_whitespace(next)) {
pos++;
} else {
throw error("line separator expected");
}
}
}
void BasicParser::goBack() {
if (pos) pos--;
}
char BasicParser::peek() {
skipWhitespace();
if (pos >= source.length()) {
throw error("unexpected end");
}
return source[pos];
}
std::string BasicParser::parseName() {
char c = peek();
if (!is_identifier_start(c)) {
if (c == '"') {
pos++;
return parseString(c);
}
throw error("identifier expected");
}
int start = pos;
while (hasNext() && is_identifier_part(source[pos])) {
pos++;
}
return source.substr(start, pos-start);
}
int64_t BasicParser::parseSimpleInt(int base) {
char c = peek();
int index = hexchar2int(c);
if (index == -1 || index >= base) {
throw error("invalid number literal");
}
int64_t value = index;
pos++;
while (hasNext()) {
c = source[pos];
while (c == '_') {
c = source[++pos];
}
index = hexchar2int(c);
if (index == -1 || index >= base) {
return value;
}
value *= base;
value += index;
pos++;
}
return value;
}
bool BasicParser::parseNumber(int sign, number_u& out) {
char c = peek();
int base = 10;
if (c == '0' && pos + 1 < source.length() &&
(base = is_box(source[pos+1])) != 10) {
pos += 2;
out = parseSimpleInt(base);
return true;
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
pos += 3;
out = INFINITY * sign;
return false;
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
pos += 3;
out = NAN * sign;
return false;
}
int64_t value = parseSimpleInt(base);
if (!hasNext()) {
out = value * sign;
return true;
}
c = source[pos];
if (c == 'e' || c == 'E') {
pos++;
int s = 1;
if (peek() == '-') {
s = -1;
pos++;
} else if (peek() == '+'){
pos++;
}
out = sign * value * power(10.0, s * parseSimpleInt(10));
return false;
}
if (c == '.') {
pos++;
int64_t expo = 1;
while (hasNext() && source[pos] == '0') {
expo *= 10;
pos++;
}
int64_t afterdot = 0;
if (hasNext() && is_digit(source[pos])) {
afterdot = parseSimpleInt(10);
}
expo *= power(10, fmax(0, log10(afterdot) + 1));
c = source[pos];
double dvalue = (value + (afterdot / (double)expo));
if (c == 'e' || c == 'E') {
pos++;
int s = 1;
if (peek() == '-') {
s = -1;
pos++;
} else if (peek() == '+'){
pos++;
}
out = sign * dvalue * power(10.0, s * parseSimpleInt(10));
return false;
}
out = sign * dvalue;
return false;
}
out = sign * value;
return true;
}
std::string BasicParser::parseString(char quote, bool closeRequired) {
std::stringstream ss;
while (hasNext()) {
char c = source[pos];
if (c == quote) {
pos++;
return ss.str();
}
if (c == '\\') {
pos++;
c = nextChar();
if (c >= '0' && c <= '7') {
pos--;
ss << (char)parseSimpleInt(8);
continue;
}
switch (c) {
case 'n': ss << '\n'; break;
case 'r': ss << '\r'; break;
case 'b': ss << '\b'; break;
case 't': ss << '\t'; break;
case 'f': ss << '\f'; break;
case '\'': ss << '\\'; break;
case '"': ss << '"'; break;
case '\\': ss << '\\'; break;
case '/': ss << '/'; break;
case '\n': pos++; continue;
default:
throw error("'\\" + std::string({c}) +
"' is an illegal escape");
}
continue;
}
if (c == '\n' && closeRequired) {
throw error("non-closed string literal");
}
ss << c;
pos++;
}
if (closeRequired) {
throw error("unexpected end");
}
return ss.str();
}
parsing_error BasicParser::error(std::string message) {
return parsing_error(message, filename, source, pos, line, linestart);
}
#include "commons.h"
#include "../util/stringutil.h"
#include <sstream>
#include <stdexcept>
#include <math.h>
inline double power(double base, int64_t power) {
double result = 1.0;
for (int64_t i = 0; i < power; i++) {
result *= base;
}
return result;
}
parsing_error::parsing_error(
std::string message,
std::string filename,
std::string source,
uint pos,
uint line,
uint linestart)
: std::runtime_error(message), filename(filename), source(source),
pos(pos), line(line), linestart(linestart) {
}
std::string parsing_error::errorLog() const {
std::stringstream ss;
uint linepos = pos - linestart;
ss << "parsing error in file '" << filename;
ss << "' at " << (line+1) << ":" << linepos << ": " << this->what() << "\n";
size_t end = source.find("\n", linestart);
if (end == std::string::npos) {
end = source.length();
}
ss << source.substr(linestart, end-linestart) << "\n";
for (uint i = 0; i < linepos; i++) {
ss << " ";
}
ss << "^";
return ss.str();
}
BasicParser::BasicParser(
const std::string& file,
const std::string& source
) : filename(file), source(source) {
}
void BasicParser::skipWhitespace() {
while (hasNext()) {
char next = source[pos];
if (next == '\n') {
line++;
linestart = ++pos;
continue;
}
if (is_whitespace(next)) {
pos++;
} else {
break;
}
}
}
void BasicParser::skip(size_t n) {
n = std::min(n, source.length()-pos);
for (size_t i = 0; i < n; i++) {
char next = source[pos++];
if (next == '\n') {
line++;
linestart = pos;
}
}
}
void BasicParser::skipLine() {
while (hasNext()) {
if (source[pos] == '\n') {
pos++;
linestart = pos;
line++;
break;
}
pos++;
}
}
bool BasicParser::skipTo(const std::string& substring) {
size_t idx = source.find(substring, pos);
if (idx == std::string::npos) {
skip(source.length()-pos);
return false;
} else {
skip(idx-pos);
return true;
}
}
bool BasicParser::hasNext() {
return pos < source.length();
}
bool BasicParser::isNext(const std::string& substring) {
if (source.length() - pos < substring.length()) {
return false;
}
return source.substr(pos, substring.length()) == substring;
}
char BasicParser::nextChar() {
if (!hasNext()) {
throw error("unexpected end");
}
return source[pos++];
}
void BasicParser::expect(char expected) {
char c = peek();
if (c != expected) {
throw error("'"+std::string({expected})+"' expected");
}
pos++;
}
void BasicParser::expect(const std::string& substring) {
if (substring.empty())
return;
for (uint i = 0; i < substring.length(); i++) {
if (source.length() <= pos + i || source[pos+i] != substring[i]) {
throw error(util::quote(substring)+" expected");
}
}
pos += substring.length();
}
void BasicParser::expectNewLine() {
while (hasNext()) {
char next = source[pos];
if (next == '\n') {
line++;
linestart = ++pos;
return;
}
if (is_whitespace(next)) {
pos++;
} else {
throw error("line separator expected");
}
}
}
void BasicParser::goBack() {
if (pos) pos--;
}
char BasicParser::peek() {
skipWhitespace();
if (pos >= source.length()) {
throw error("unexpected end");
}
return source[pos];
}
std::string BasicParser::parseName() {
char c = peek();
if (!is_identifier_start(c)) {
if (c == '"') {
pos++;
return parseString(c);
}
throw error("identifier expected");
}
int start = pos;
while (hasNext() && is_identifier_part(source[pos])) {
pos++;
}
return source.substr(start, pos-start);
}
int64_t BasicParser::parseSimpleInt(int base) {
char c = peek();
int index = hexchar2int(c);
if (index == -1 || index >= base) {
throw error("invalid number literal");
}
int64_t value = index;
pos++;
while (hasNext()) {
c = source[pos];
while (c == '_') {
c = source[++pos];
}
index = hexchar2int(c);
if (index == -1 || index >= base) {
return value;
}
value *= base;
value += index;
pos++;
}
return value;
}
bool BasicParser::parseNumber(int sign, number_u& out) {
char c = peek();
int base = 10;
if (c == '0' && pos + 1 < source.length() &&
(base = is_box(source[pos+1])) != 10) {
pos += 2;
out = parseSimpleInt(base);
return true;
} else if (c == 'i' && pos + 2 < source.length() && source[pos+1] == 'n' && source[pos+2] == 'f') {
pos += 3;
out = INFINITY * sign;
return false;
} else if (c == 'n' && pos + 2 < source.length() && source[pos+1] == 'a' && source[pos+2] == 'n') {
pos += 3;
out = NAN * sign;
return false;
}
int64_t value = parseSimpleInt(base);
if (!hasNext()) {
out = value * sign;
return true;
}
c = source[pos];
if (c == 'e' || c == 'E') {
pos++;
int s = 1;
if (peek() == '-') {
s = -1;
pos++;
} else if (peek() == '+'){
pos++;
}
out = sign * value * power(10.0, s * parseSimpleInt(10));
return false;
}
if (c == '.') {
pos++;
int64_t expo = 1;
while (hasNext() && source[pos] == '0') {
expo *= 10;
pos++;
}
int64_t afterdot = 0;
if (hasNext() && is_digit(source[pos])) {
afterdot = parseSimpleInt(10);
}
expo *= power(10, fmax(0, log10(afterdot) + 1));
c = source[pos];
double dvalue = (value + (afterdot / (double)expo));
if (c == 'e' || c == 'E') {
pos++;
int s = 1;
if (peek() == '-') {
s = -1;
pos++;
} else if (peek() == '+'){
pos++;
}
out = sign * dvalue * power(10.0, s * parseSimpleInt(10));
return false;
}
out = sign * dvalue;
return false;
}
out = sign * value;
return true;
}
std::string BasicParser::parseString(char quote, bool closeRequired) {
std::stringstream ss;
while (hasNext()) {
char c = source[pos];
if (c == quote) {
pos++;
return ss.str();
}
if (c == '\\') {
pos++;
c = nextChar();
if (c >= '0' && c <= '7') {
pos--;
ss << (char)parseSimpleInt(8);
continue;
}
switch (c) {
case 'n': ss << '\n'; break;
case 'r': ss << '\r'; break;
case 'b': ss << '\b'; break;
case 't': ss << '\t'; break;
case 'f': ss << '\f'; break;
case '\'': ss << '\\'; break;
case '"': ss << '"'; break;
case '\\': ss << '\\'; break;
case '/': ss << '/'; break;
case '\n': pos++; continue;
default:
throw error("'\\" + std::string({c}) +
"' is an illegal escape");
}
continue;
}
if (c == '\n' && closeRequired) {
throw error("non-closed string literal");
}
ss << c;
pos++;
}
if (closeRequired) {
throw error("unexpected end");
}
return ss.str();
}
parsing_error BasicParser::error(std::string message) {
return parsing_error(message, filename, source, pos, line, linestart);
}
+3 -3
View File
@@ -70,8 +70,8 @@ public:
class BasicParser {
protected:
std::string filename;
std::string source;
const std::string& filename;
const std::string& source;
uint pos = 0;
uint line = 1;
uint linestart = 0;
@@ -96,7 +96,7 @@ protected:
parsing_error error(std::string message);
BasicParser(std::string filename, std::string source);
BasicParser(const std::string& file, const std::string& source);
};
#endif // CODERS_COMMONS_H_
+4 -4
View File
@@ -118,8 +118,8 @@ std::string json::stringify(
return ss.str();
}
Parser::Parser(std::string filename, std::string source)
: BasicParser(filename, source) {
Parser::Parser(const std::string& filename, const std::string& source)
: BasicParser(filename, source) {
}
Map* Parser::parse() {
@@ -244,11 +244,11 @@ Value* Parser::parseValue() {
throw error("unexpected character '"+std::string({next})+"'");
}
std::unique_ptr<Map> json::parse(std::string filename, std::string source) {
std::unique_ptr<Map> json::parse(const std::string& filename, const std::string& source) {
Parser parser(filename, source);
return std::unique_ptr<Map>(parser.parse());
}
std::unique_ptr<Map> json::parse(std::string source) {
std::unique_ptr<Map> json::parse(const std::string& source) {
return parse("<string>", source);
}
+4 -4
View File
@@ -24,13 +24,13 @@ namespace json {
dynamic::Map* parseObject();
dynamic::Value* parseValue();
public:
Parser(std::string filename, std::string source);
Parser(const std::string& filename, const std::string& source);
dynamic::Map* parse();
};
extern std::unique_ptr<dynamic::Map> parse(std::string filename, std::string source);
extern std::unique_ptr<dynamic::Map> parse(std::string source);
extern std::unique_ptr<dynamic::Map> parse(const std::string& filename, const std::string& source);
extern std::unique_ptr<dynamic::Map> parse(const std::string& source);
extern std::string stringify(
const dynamic::Map* obj,
@@ -38,4 +38,4 @@ namespace json {
const std::string& indent);
}
#endif // CODERS_JSON_H_
#endif // CODERS_JSON_H_
+127 -261
View File
@@ -1,261 +1,127 @@
#include "toml.h"
#include "commons.h"
#include "../util/stringutil.h"
#include <math.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <assert.h>
// FIXME: refactor this monster
using namespace toml;
Section::Section(std::string name) : name(name) {
}
void Section::add(std::string name, Field field) {
if (fields.find(name) != fields.end()) {
throw std::runtime_error("field duplication");
}
fields[name] = field;
keyOrder.push_back(name);
}
void Section::add(std::string name, bool* ptr) {
add(name, {fieldtype::ftbool, ptr});
}
void Section::add(std::string name, int* ptr) {
add(name, {fieldtype::ftint, ptr});
}
void Section::add(std::string name, uint* ptr) {
add(name, {fieldtype::ftuint, ptr});
}
void Section::add(std::string name, int64_t* ptr) {
add(name, {fieldtype::ftint64, ptr});
}
void Section::add(std::string name, float* ptr) {
add(name, {fieldtype::ftfloat, ptr});
}
void Section::add(std::string name, double* ptr) {
add(name, {fieldtype::ftdouble, ptr});
}
void Section::add(std::string name, std::string* ptr) {
add(name, {fieldtype::ftstring, ptr});
}
const std::string& Section::getName() const {
return name;
}
const Field* Section::field(const std::string& name) const {
auto found = fields.find(name);
if (found == fields.end()) {
return nullptr;
}
return &found->second;
}
const std::vector<std::string>& Section::keys() const {
return keyOrder;
}
Wrapper::~Wrapper() {
for (auto entry : sections) {
delete entry.second;
}
}
Section& Wrapper::add(std::string name) {
if (sections.find(name) != sections.end()) {
throw std::runtime_error("section duplication");
}
Section* section = new Section(name);
sections[name] = section;
keyOrder.push_back(name);
return *section;
}
Section* Wrapper::section(std::string name) {
auto found = sections.find(name);
if (found == sections.end()) {
return nullptr;
}
return found->second;
}
std::string Wrapper::write() const {
std::stringstream ss;
for (const std::string& key : keyOrder) {
const Section* section = sections.at(key);
ss << "[" << key << "]\n";
for (const std::string& key : section->keys()) {
ss << key << " = ";
const Field* field = section->field(key);
assert(field != nullptr);
switch (field->type) {
case fieldtype::ftbool:
ss << (*((bool*)field->ptr) ? "true" : "false");
break;
case fieldtype::ftint: ss << *((int*)field->ptr); break;
case fieldtype::ftuint: ss << *((uint*)field->ptr); break;
case fieldtype::ftint64: ss << *((int64_t*)field->ptr); break;
case fieldtype::ftfloat: ss << *((float*)field->ptr); break;
case fieldtype::ftdouble: ss << *((double*)field->ptr); break;
case fieldtype::ftstring:
ss << util::escape(*((const std::string*)field->ptr));
break;
}
ss << "\n";
}
ss << "\n";
}
return ss.str();
}
Reader::Reader(Wrapper* wrapper, std::string file, std::string source)
: BasicParser(file, source), wrapper(wrapper) {
}
void Reader::skipWhitespace() {
BasicParser::skipWhitespace();
if (hasNext() && source[pos] == '#') {
skipLine();
if (hasNext() && is_whitespace(peek())) {
skipWhitespace();
}
}
}
void Reader::read() {
skipWhitespace();
if (!hasNext()) {
return;
}
readSection(nullptr);
}
void Section::set(const std::string& name, double value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftbool: *(bool*)(field->ptr) = fabs(value) > 0.0; break;
case fieldtype::ftint: *(int*)(field->ptr) = value; break;
case fieldtype::ftuint: *(uint*)(field->ptr) = value; break;
case fieldtype::ftint64: *(int64_t*)(field->ptr) = value; break;
case fieldtype::ftfloat: *(float*)(field->ptr) = value; break;
case fieldtype::ftdouble: *(double*)(field->ptr) = value; break;
case fieldtype::ftstring: *(std::string*)(field->ptr) = std::to_string(value); break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Section::set(const std::string& name, bool value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftbool: *(bool*)(field->ptr) = value; break;
case fieldtype::ftint: *(int*)(field->ptr) = (int)value; break;
case fieldtype::ftuint: *(uint*)(field->ptr) = (uint)value; break;
case fieldtype::ftint64: *(int64_t*)(field->ptr) = (int64_t)value; break;
case fieldtype::ftfloat: *(float*)(field->ptr) = (float)value; break;
case fieldtype::ftdouble: *(double*)(field->ptr) = (double)value; break;
case fieldtype::ftstring: *(std::string*)(field->ptr) = value ? "true" : "false"; break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Section::set(const std::string& name, std::string value) {
const Field* field = this->field(name);
if (field == nullptr) {
std::cerr << "warning: unknown key '" << name << "'" << std::endl;
} else {
switch (field->type) {
case fieldtype::ftstring: *(std::string*)(field->ptr) = value; break;
default:
std::cerr << "error: type error for key '" << name << "'" << std::endl;
}
}
}
void Reader::readSection(Section* section /*nullable*/) {
while (hasNext()) {
skipWhitespace();
if (!hasNext()) {
break;
}
char c = nextChar();
if (c == '[') {
std::string name = parseName();
Section* section = wrapper->section(name);
pos++;
readSection(section);
return;
}
pos--;
std::string name = parseName();
expect('=');
c = peek();
if (is_digit(c)) {
number_u num;
if (parseNumber(1, num)) {
if (section)
section->set(name, (double)std::get<integer_t>(num));
} else {
if (section)
section->set(name, std::get<number_t>(num));
}
} else if (c == '-' || c == '+') {
int sign = c == '-' ? -1 : 1;
pos++;
number_u num;
if (parseNumber(sign, num)) {
if (section)
section->set(name, (double)std::get<integer_t>(num));
} else {
if (section)
section->set(name, std::get<number_t>(num));
}
} else if (is_identifier_start(c)) {
std::string identifier = parseName();
if (identifier == "true" || identifier == "false") {
bool flag = identifier == "true";
if (section) {
section->set(name, flag);
}
} else if (identifier == "inf") {
if (section) {
section->set(name, INFINITY);
}
} else if (identifier == "nan") {
if (section) {
section->set(name, NAN);
}
}
} else if (c == '"' || c == '\'') {
pos++;
std::string str = parseString(c);
if (section) {
section->set(name, str);
}
} else {
throw error("feature is not supported");
}
expectNewLine();
}
}
#include "toml.h"
#include "commons.h"
#include "../data/dynamic.h"
#include "../util/stringutil.h"
#include "../files/settings_io.hpp"
#include <math.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <assert.h>
// FIXME: refactor this monster
using namespace toml;
class Reader : public BasicParser {
SettingsHandler& handler;
void skipWhitespace() override {
BasicParser::skipWhitespace();
if (hasNext() && source[pos] == '#') {
skipLine();
if (hasNext() && is_whitespace(peek())) {
skipWhitespace();
}
}
}
void readSection(const std::string& section) {
while (hasNext()) {
skipWhitespace();
if (!hasNext()) {
break;
}
char c = nextChar();
if (c == '[') {
std::string name = parseName();
pos++;
readSection(name);
return;
}
pos--;
std::string name = section+"."+parseName();
expect('=');
c = peek();
if (is_digit(c)) {
number_u num;
parseNumber(1, num);
handler.setValue(name, *dynamic::Value::of(num));
} else if (c == '-' || c == '+') {
int sign = c == '-' ? -1 : 1;
pos++;
number_u num;
parseNumber(sign, num);
handler.setValue(name, *dynamic::Value::of(num));
} else if (is_identifier_start(c)) {
std::string identifier = parseName();
if (identifier == "true" || identifier == "false") {
bool flag = identifier == "true";
handler.setValue(name, *dynamic::Value::boolean(flag));
} else if (identifier == "inf") {
handler.setValue(name, *dynamic::Value::of(INFINITY));
} else if (identifier == "nan") {
handler.setValue(name, *dynamic::Value::of(NAN));
}
} else if (c == '"' || c == '\'') {
pos++;
std::string str = parseString(c);
handler.setValue(name, *dynamic::Value::of(str));
} else {
throw error("feature is not supported");
}
expectNewLine();
}
}
public:
Reader(
SettingsHandler& handler,
const std::string& file,
const std::string& source)
: BasicParser(file, source), handler(handler) {
}
void read() {
skipWhitespace();
if (!hasNext()) {
return;
}
readSection("");
}
};
void toml::parse(
SettingsHandler& handler,
const std::string& file,
const std::string& source
) {
Reader reader(handler, file, source);
reader.read();
}
std::string toml::stringify(SettingsHandler& handler) {
auto& sections = handler.getSections();
std::stringstream ss;
for (auto& section : sections) {
ss << "[" << section.name << "]\n";
for (const std::string& key : section.keys) {
ss << key << " = ";
auto setting = handler.getSetting(section.name+"."+key);
assert(setting != nullptr);
if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
ss << integer->get();
} else if (auto number = dynamic_cast<NumberSetting*>(setting)) {
ss << number->get();
} else if (auto flag = dynamic_cast<FlagSetting*>(setting)) {
ss << (flag->get() ? "true" : "false");
} else if (auto string = dynamic_cast<StringSetting*>(setting)) {
ss << util::escape(string->get());
}
ss << "\n";
}
ss << "\n";
}
return ss.str();
}
+22 -72
View File
@@ -1,72 +1,22 @@
#ifndef CODERS_TOML_H_
#define CODERS_TOML_H_
#include <string>
#include <vector>
#include <unordered_map>
#include "commons.h"
namespace toml {
enum class fieldtype {
ftbool,
ftint,
ftuint,
ftint64,
ftfloat,
ftdouble,
ftstring,
};
struct Field {
fieldtype type;
void* ptr;
};
class Section {
std::unordered_map<std::string, Field> fields;
std::vector<std::string> keyOrder;
std::string name;
void add(std::string name, Field field);
public:
Section(std::string name);
void add(std::string name, bool* ptr);
void add(std::string name, int* ptr);
void add(std::string name, int64_t* ptr);
void add(std::string name, uint* ptr);
void add(std::string name, float* ptr);
void add(std::string name, double* ptr);
void add(std::string name, std::string* ptr);
const Field* field(const std::string& name) const;
void set(const std::string& name, double value);
void set(const std::string& name, bool value);
void set(const std::string& name, std::string value);
const std::string& getName() const;
const std::vector<std::string>& keys() const;
};
class Wrapper {
std::unordered_map<std::string, Section*> sections;
std::vector<std::string> keyOrder;
public:
~Wrapper();
Section& add(std::string section);
Section* section(std::string name);
std::string write() const;
};
class Reader : public BasicParser {
Wrapper* wrapper;
void skipWhitespace() override;
void readSection(Section* section);
public:
Reader(Wrapper* wrapper, std::string file, std::string source);
void read();
};
}
#endif // CODERS_TOML_H_
#ifndef CODERS_TOML_H_
#define CODERS_TOML_H_
#include <string>
#include <vector>
#include <unordered_map>
#include "commons.h"
class SettingsHandler;
namespace toml {
std::string stringify(SettingsHandler& handler);
void parse(
SettingsHandler& handler,
const std::string& file,
const std::string& source
);
}
#endif // CODERS_TOML_H_
+1 -1
View File
@@ -176,7 +176,7 @@ const std::string& Document::getEncoding() const {
return encoding;
}
Parser::Parser(std::string filename, std::string source)
Parser::Parser(const std::string& filename, const std::string& source)
: BasicParser(filename, source) {
}
+1 -1
View File
@@ -118,7 +118,7 @@ namespace xml {
std::string parseText();
std::string parseXMLName();
public:
Parser(std::string filename, std::string source);
Parser(const std::string& filename, const std::string& source);
xmldocument parse();
};