add util/json to repo

This commit is contained in:
Patrick Brosi 2018-08-09 19:33:20 +02:00
parent dfce1a44fc
commit 18c00718f6
2 changed files with 281 additions and 0 deletions

173
src/util/json/Writer.cpp Normal file
View file

@ -0,0 +1,173 @@
// Copyright 2018, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
#include <iomanip>
#include "Writer.h"
#include "util/String.h"
using namespace util;
using namespace json;
using std::ostream;
using std::string;
using std::map;
// _____________________________________________________________________________
Writer::Writer(std::ostream* out)
: _out(out), _pretty(false), _indent(2), _floatPrec(10) {}
// _____________________________________________________________________________
Writer::Writer(std::ostream* out, size_t prec)
: _out(out), _pretty(false), _indent(2), _floatPrec(prec) {}
// _____________________________________________________________________________
Writer::Writer(std::ostream* out, size_t prec, bool pret)
: _out(out), _pretty(pret), _indent(2), _floatPrec(prec) {}
// _____________________________________________________________________________
Writer::Writer(std::ostream* out, size_t prec, bool pret, size_t indent)
: _out(out), _pretty(pret), _indent(indent), _floatPrec(prec) {}
// _____________________________________________________________________________
void Writer::obj() {
if (!_stack.empty() && _stack.top().type == OBJ)
throw WriterException("Object not allowed as key");
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
if (!_stack.empty() && _stack.top().type == ARR) valCheck();
if (_stack.size() && _stack.top().type == ARR) prettor();
*_out << "{";
_stack.push({OBJ, 1});
}
// _____________________________________________________________________________
void Writer::key(const std::string& k) {
if (_stack.empty() || _stack.top().type != OBJ)
throw WriterException("Keys only allowed in objects.");
if (!_stack.top().empty) (*_out) << "," << (_pretty ? " " : "");
_stack.top().empty = 0;
prettor();
*_out << "\"" << k << "\""
<< ":" << (_pretty ? " " : "");
_stack.push({KEY, 1});
}
// _____________________________________________________________________________
void Writer::valCheck() {
if (_stack.empty() || (_stack.top().type != KEY && _stack.top().type != ARR))
throw WriterException("Value not allowed here.");
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
if (!_stack.empty() && _stack.top().type == ARR) {
if (!_stack.top().empty) (*_out) << "," << (_pretty ? " " : "");
_stack.top().empty = 0;
}
}
// _____________________________________________________________________________
void Writer::val(const std::string& v) {
valCheck();
*_out << "\"" << util::jsonStringEscape(v) << "\"";
}
// _____________________________________________________________________________
void Writer::val(const char* v) {
valCheck();
*_out << "\"" << util::jsonStringEscape(v) << "\"";
}
// _____________________________________________________________________________
void Writer::val(bool v) {
valCheck();
*_out << (v ? "true" : "false");
}
// _____________________________________________________________________________
void Writer::val(int v) {
valCheck();
*_out << v;
}
// _____________________________________________________________________________
void Writer::val(double v) {
valCheck();
*_out << std::fixed << std::setprecision(_floatPrec) << v;
}
// _____________________________________________________________________________
void Writer::val(Null) {
valCheck();
*_out << "null";
}
// _____________________________________________________________________________
void Writer::val(const Val& v) {
switch (v.type) {
case Val::JSNULL:
val(Null());
return;
case Val::INT:
val(v.i);
return;
case Val::FLOAT:
val(v.f);
return;
case Val::BOOL:
val((bool)v.i);
return;
case Val::STRING:
val(v.str);
return;
case Val::ARRAY:
arr();
for (const Val& varr : v.arr) val(varr);
close();
return;
case Val::DICT:
obj();
for (const auto& vdic : v.dict) {
keyVal(vdic.first, vdic.second);
};
close();
return;
}
}
// _____________________________________________________________________________
void Writer::arr() {
if (!_stack.empty() && _stack.top().type == OBJ)
throw WriterException("Array not allowed as key");
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
if (!_stack.empty() && _stack.top().type == ARR) valCheck();
*_out << "[";
_stack.push({ARR, 1});
}
// _____________________________________________________________________________
void Writer::prettor() {
if (_pretty) {
*_out << "\n";
for (size_t i = 0; i < _indent * _stack.size(); i++) (*_out) << " ";
}
}
// _____________________________________________________________________________
void Writer::closeAll() {
while (!_stack.empty()) close();
}
// _____________________________________________________________________________
void Writer::close() {
if (_stack.empty()) return;
switch (_stack.top().type) {
case OBJ:
_stack.pop();
prettor();
(*_out) << "}";
break;
case ARR:
_stack.pop();
(*_out) << "]";
break;
case KEY:
throw WriterException("Missing value.");
}
}

108
src/util/json/Writer.h Normal file
View file

@ -0,0 +1,108 @@
// Copyright 2018, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
#ifndef UTIL_JSON_WRITER_H_
#define UTIL_JSON_WRITER_H_
#include <map>
#include <ostream>
#include <stack>
#include <string>
#include <vector>
namespace util {
namespace json {
class WriterException : public std::exception {
public:
WriterException(std::string msg) : _msg(msg) {}
~WriterException() throw() {}
virtual const char* what() const throw() { return _msg.c_str(); };
private:
std::string _msg;
};
struct Null {};
struct Val {
enum VAL_T { INT, FLOAT, STRING, ARRAY, DICT, BOOL, JSNULL };
VAL_T type;
int i;
double f;
std::string str;
std::vector<Val> arr;
std::map<std::string, Val> dict;
Val() { type = DICT; }
Val(Null) { type = JSNULL; }
Val(const std::vector<Val>& arrC) { arr = arrC, type = ARRAY; }
Val(const std::map<std::string, Val>& dC) { dict = dC, type = DICT; }
Val(const std::string& strC) { str = strC, type = STRING; }
Val(const char* strC) { str = strC, type = STRING; }
Val(double fC) { f = fC, type = FLOAT; }
Val(int iC) { i = iC, type = INT; }
Val(bool fC) { i = fC, type = BOOL; }
};
typedef int Int;
typedef double Float;
typedef bool Bool;
typedef std::string String;
typedef std::vector<Val> Array;
typedef std::map<std::string, Val> Dict;
// simple JSON writer class without much overhead
class Writer {
public:
explicit Writer(std::ostream* out);
Writer(std::ostream* out, size_t prec);
Writer(std::ostream* out, size_t prec, bool pretty);
Writer(std::ostream* out, size_t prec, bool pretty, size_t indent);
~Writer(){};
void obj();
void arr();
void key(const std::string& k);
void val(const std::string& v);
void val(const char* v);
void val(double v);
void val(int v);
void val(bool v);
void val(Null);
void val(const Val& v);
template <typename V>
void keyVal(const std::string& k, const V& v) {
key(k);
val(v);
}
void close();
void closeAll();
private:
std::ostream* _out;
enum NODE_T { OBJ, ARR, KEY };
struct Node {
NODE_T type;
bool empty;
};
std::stack<Node> _stack;
bool _pretty;
size_t _indent;
size_t _floatPrec;
void valCheck();
void prettor();
};
} // namespace json
} // namespace util
#endif // UTIL_JSON_WRITER_H_