Compare commits

..
7 Commits
Author SHA1 Message Date
Riyyi 11fdc64447 Util: Add pause() and resume() to Timer 2022-07-18 17:37:04 +02:00
Riyyi a92ac29d19 Util: Add parse(std::ifstream) function 2022-07-18 16:03:11 +02:00
Riyyi 07df4054da Util: Massively speedup serialization, remove all ifs from loop 2022-07-18 15:53:42 +02:00
Riyyi 2915c1c1ec Util: Reorder Array/Object functions, add empty() 2022-07-18 15:10:11 +02:00
Riyyi 161be80fd6 Util: Make second to last element detection more compatible
std::prev doesn't work on std::unordered_map, this patch makes it work.
2022-07-18 12:50:09 +02:00
Riyyi c3f5df7a29 Util: Optimize away returning strings 2022-07-18 12:42:08 +02:00
Riyyi 93eb2f4f6a Util: Optimize Value member away 2022-07-18 12:18:56 +02:00
8 changed files with 172 additions and 89 deletions
+11 -3
View File
@@ -30,18 +30,26 @@ public:
{
}
void clear() { m_elements.clear(); }
void emplace_back(Value element);
// Capacity
bool empty() const { return m_elements.empty(); }
size_t size() const { return m_elements.size(); }
void reserve(size_t size) { m_elements.reserve(size); }
// Element access
Value& operator[](size_t index);
Value& at(size_t index) { return m_elements.at(index); }
const Value& at(size_t index) const { return m_elements.at(index); }
size_t size() const { return m_elements.size(); }
const std::vector<Value>& elements() const { return m_elements; }
// Modifiers
void clear() { m_elements.clear(); }
void emplace_back(Value element);
private:
std::vector<Value> m_elements;
};
+11 -3
View File
@@ -27,17 +27,25 @@ public:
{
}
void clear() { m_members.clear(); }
void emplace(const std::string& name, Value value);
// Capacity
bool empty() const { return m_members.empty(); }
size_t size() const { return m_members.size(); }
// Member access
Value& operator[](const std::string& name);
Value& at(const std::string& name) { return m_members.at(name); }
const Value& at(const std::string& name) const { return m_members.at(name); }
size_t size() const { return m_members.size(); }
const std::map<std::string, Value>& members() const { return m_members; }
// Modifiers
void clear() { m_members.clear(); }
void emplace(const std::string& name, Value value);
private:
std::map<std::string, Value> m_members;
};
+79 -65
View File
@@ -5,7 +5,7 @@
*/
#include <cstdint> // uint32_t
#include <iterator> // prev
#include <iterator> // next
#include <sstream> // ostringstream
#include <string>
@@ -16,9 +16,8 @@
namespace Json {
Serializer::Serializer(const Value& value, const uint32_t indent, const char indentCharacter)
: m_value(value)
, m_indent(indent)
Serializer::Serializer(const uint32_t indent, const char indentCharacter)
: m_indent(indent)
, m_indentCharacter(indentCharacter)
{
}
@@ -29,112 +28,127 @@ Serializer::~Serializer()
// ------------------------------------------
std::string Serializer::dump()
std::string Serializer::dump(const Value& value)
{
return dumpHelper(m_value);
dumpHelper(value);
return m_output;
}
// ------------------------------------------
std::string Serializer::dumpHelper(const Value& value, const uint32_t indentLevel)
void Serializer::dumpHelper(const Value& value, const uint32_t indentLevel)
{
switch (value.m_type) {
case Value::Type::Null:
return "null";
m_output += "null";
break;
case Value::Type::Bool:
return value.m_value.boolean ? "true" : "false";
m_output += value.m_value.boolean ? "true" : "false";
break;
case Value::Type::Number: {
std::ostringstream os;
os << value.m_value.number;
return os.str();
m_output += os.str();
break;
}
case Value::Type::String:
return "\"" + *value.m_value.string + "\"";
m_output += "\"" + *value.m_value.string + "\"";
break;
case Value::Type::Array:
return dumpArray(value, indentLevel);
dumpArray(value, indentLevel);
break;
case Value::Type::Object:
return dumpObject(value, indentLevel);
dumpObject(value, indentLevel);
break;
default:
break;
}
return "";
}
std::string Serializer::dumpArray(const Value& value, const uint32_t indentLevel)
void Serializer::dumpArray(const Value& value, const uint32_t indentLevel)
{
std::string result;
// Append [
result += "[";
if (m_indent > 0) {
result += '\n';
m_output += '[';
m_output += '\n';
}
auto values = value.m_value.array->elements();
for (auto it = values.begin(); it != values.end(); ++it) {
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter);
result += dumpHelper(*it, indentLevel + 1);
// Add comma, except after the last element
if (it != std::prev(values.end(), 1)) {
result += ",";
}
if (m_indent > 0) {
result += '\n';
}
// Empty Array early return
if (value.m_value.array->empty()) {
m_output += ']';
return;
}
// Append indentation
result += std::string(m_indent * indentLevel, m_indentCharacter);
size_t i = 0;
auto it = value.m_value.array->elements().cbegin();
if (!m_indent) {
for (; i < value.m_value.array->size() - 1; ++i, ++it) {
dumpHelper(*it, indentLevel + 1);
m_output += ',';
}
dumpHelper(*it, indentLevel + 1);
}
else {
std::string indentation = std::string(m_indent * (indentLevel + 1), m_indentCharacter);
// Append ]
result += "]";
for (; i < value.m_value.array->size() - 1; ++i, ++it) {
m_output += indentation;
dumpHelper(*it, indentLevel + 1);
m_output += ",\n";
}
m_output += indentation;
dumpHelper(*it, indentLevel + 1);
m_output += '\n';
return result;
// Append indentation
m_output += std::string(m_indent * indentLevel, m_indentCharacter);
}
m_output += "]";
}
std::string Serializer::dumpObject(const Value& value, const uint32_t indentLevel)
void Serializer::dumpObject(const Value& value, const uint32_t indentLevel)
{
std::string result;
// Append {
result += "{";
if (m_indent > 0) {
result += '\n';
m_output += '{';
m_output += '\n';
}
auto members = value.m_value.object->members();
for (auto it = members.begin(); it != members.end(); ++it) {
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter);
result += "\"" + it->first + "\":";
if (m_indent > 0) {
result += ' ';
}
result += dumpHelper(it->second, indentLevel + 1);
// Add comma, except after the last element
if (it != std::prev(members.end(), 1)) {
result += ",";
}
if (m_indent > 0) {
result += '\n';
}
// Empty Object early return
if (value.m_value.object->empty()) {
m_output += '}';
return;
}
// Append indentation
result += std::string(m_indent * indentLevel, m_indentCharacter);
size_t i = 0;
auto it = value.m_value.object->members().cbegin();
if (!m_indent) {
for (; i < value.m_value.object->size() - 1; ++i, ++it) {
m_output += '"' + it->first + "\":";
dumpHelper(it->second, indentLevel + 1);
m_output += ',';
}
m_output += '"' + it->first + "\":";
dumpHelper(it->second, indentLevel + 1);
}
else {
std::string indentation = std::string(m_indent * (indentLevel + 1), m_indentCharacter);
// Append }
result += "}";
for (; i < value.m_value.object->size() - 1; ++i, ++it) {
m_output += indentation;
m_output += '"' + it->first + "\": ";
dumpHelper(it->second, indentLevel + 1);
m_output += ",\n";
}
m_output += indentation;
m_output += '"' + it->first + "\": ";
dumpHelper(it->second, indentLevel + 1);
m_output += '\n';
return result;
// Append indentation
m_output += std::string(m_indent * indentLevel, m_indentCharacter);
}
m_output += '}';
}
} // namespace Json
+6 -6
View File
@@ -16,17 +16,17 @@ namespace Json {
class Serializer {
public:
Serializer(const Value& value, const uint32_t indent = 0, const char indentCharacter = ' ');
Serializer(const uint32_t indent = 0, const char indentCharacter = ' ');
virtual ~Serializer();
std::string dump();
std::string dump(const Value& value);
private:
std::string dumpHelper(const Value& value, const uint32_t indentLevel = 0);
std::string dumpArray(const Value& value, const uint32_t indentLevel = 0);
std::string dumpObject(const Value& value, const uint32_t indentLevel = 0);
void dumpHelper(const Value& value, const uint32_t indentLevel = 0);
void dumpArray(const Value& value, const uint32_t indentLevel = 0);
void dumpObject(const Value& value, const uint32_t indentLevel = 0);
Value m_value;
std::string m_output;
uint32_t m_indent { 0 };
char m_indentCharacter { ' ' };
+10 -4
View File
@@ -157,10 +157,17 @@ Value Value::parse(const std::string& input)
return Job(input).fire();
}
Value Value::parse(std::ifstream& file)
{
Value value;
file >> value;
return value;
}
std::string Value::dump(const uint32_t indent, const char indentCharacter) const
{
Serializer serializer(*this, indent, indentCharacter);
return serializer.dump();
Serializer serializer(indent, indentCharacter);
return serializer.dump(*this);
}
void Value::emplace_back(Value value)
@@ -313,8 +320,7 @@ std::istream& operator>>(std::istream& input, Value& value)
}
inputString.append(buffer, input.gcount());
Job job(inputString);
value = job.fire();
value = Job(inputString).fire();
return input;
}
+1
View File
@@ -66,6 +66,7 @@ public:
// --------------------------------------
static Value parse(const std::string& input);
static Value parse(std::ifstream& file);
std::string dump(const uint32_t indent = 0, const char indentCharacter = ' ') const;
void clear();
+47 -4
View File
@@ -1,21 +1,57 @@
#include <chrono> // high_resolution_clock, seconds, milliseconds, microseconds, nanoseconds
#include <cstdint> // uint64_t
#include <cstdio> // printf
#include <cstdio> // printf
#include "util/timer.h"
namespace Util {
Timer::Timer()
: m_start(std::chrono::high_resolution_clock::now())
: m_running(true)
, m_accumulated(TimePoint::min())
, m_start(now())
{
}
Timer::Timer(const TimePoint& timePoint)
: m_running(true)
, m_accumulated(TimePoint::min())
, m_start(timePoint)
{
}
// -----------------------------------------
Timer Timer::operator-(const Timer& timer)
{
return Timer(TimePoint { m_start - timer.start() });
}
TimePoint Timer::now()
{
return std::chrono::high_resolution_clock::now();
}
void Timer::pause()
{
if (!m_running) {
return;
}
m_accumulated += now() - m_start;
m_running = false;
}
void Timer::resume()
{
if (m_running) {
return;
}
m_running = true;
m_start = now();
}
template<typename To, typename From>
To Timer::to(From from)
{
@@ -45,8 +81,15 @@ uint64_t Timer::toNanoseconds()
template<typename T>
uint64_t Timer::elapsed()
{
auto now = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<T>(now - m_start).count();
uint64_t elapsed = 0;
if (m_running) {
elapsed += std::chrono::duration_cast<T>(now() - m_start).count();
}
elapsed += std::chrono::duration_cast<T>(m_accumulated - TimePoint::min()).count();
return elapsed;
}
uint64_t Timer::elapsedSeconds()
+7 -4
View File
@@ -11,13 +11,14 @@ using TimePoint = std::chrono::high_resolution_clock::time_point;
class Timer {
public:
Timer();
Timer(const TimePoint& timePoint)
: m_start(timePoint)
{
}
Timer(const TimePoint& timePoint);
Timer operator-(const Timer& timer);
static TimePoint now();
void pause();
void resume();
template<typename To, typename From>
To to(From from);
uint64_t toSeconds();
@@ -37,6 +38,8 @@ public:
const TimePoint& start() const { return m_start; }
private:
bool m_running { true };
TimePoint m_accumulated;
TimePoint m_start;
};