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(); } // Capacity
void emplace_back(Value element);
bool empty() const { return m_elements.empty(); }
size_t size() const { return m_elements.size(); }
void reserve(size_t size) { m_elements.reserve(size); } void reserve(size_t size) { m_elements.reserve(size); }
// Element access
Value& operator[](size_t index); Value& operator[](size_t index);
Value& at(size_t index) { return m_elements.at(index); } Value& at(size_t index) { return m_elements.at(index); }
const Value& at(size_t index) const { 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; } const std::vector<Value>& elements() const { return m_elements; }
// Modifiers
void clear() { m_elements.clear(); }
void emplace_back(Value element);
private: private:
std::vector<Value> m_elements; std::vector<Value> m_elements;
}; };
+11 -3
View File
@@ -27,17 +27,25 @@ public:
{ {
} }
void clear() { m_members.clear(); } // Capacity
void emplace(const std::string& name, Value value);
bool empty() const { return m_members.empty(); }
size_t size() const { return m_members.size(); }
// Member access
Value& operator[](const std::string& name); Value& operator[](const std::string& name);
Value& at(const std::string& name) { return m_members.at(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); } 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; } 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: private:
std::map<std::string, Value> m_members; std::map<std::string, Value> m_members;
}; };
+73 -59
View File
@@ -5,7 +5,7 @@
*/ */
#include <cstdint> // uint32_t #include <cstdint> // uint32_t
#include <iterator> // prev #include <iterator> // next
#include <sstream> // ostringstream #include <sstream> // ostringstream
#include <string> #include <string>
@@ -16,9 +16,8 @@
namespace Json { namespace Json {
Serializer::Serializer(const Value& value, const uint32_t indent, const char indentCharacter) Serializer::Serializer(const uint32_t indent, const char indentCharacter)
: m_value(value) : m_indent(indent)
, m_indent(indent)
, m_indentCharacter(indentCharacter) , 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) { switch (value.m_type) {
case Value::Type::Null: case Value::Type::Null:
return "null"; m_output += "null";
break; break;
case Value::Type::Bool: case Value::Type::Bool:
return value.m_value.boolean ? "true" : "false"; m_output += value.m_value.boolean ? "true" : "false";
break; break;
case Value::Type::Number: { case Value::Type::Number: {
std::ostringstream os; std::ostringstream os;
os << value.m_value.number; os << value.m_value.number;
return os.str(); m_output += os.str();
break; break;
} }
case Value::Type::String: case Value::Type::String:
return "\"" + *value.m_value.string + "\""; m_output += "\"" + *value.m_value.string + "\"";
break; break;
case Value::Type::Array: case Value::Type::Array:
return dumpArray(value, indentLevel); dumpArray(value, indentLevel);
break; break;
case Value::Type::Object: case Value::Type::Object:
return dumpObject(value, indentLevel); dumpObject(value, indentLevel);
break; break;
default: default:
break; 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) { if (m_indent > 0) {
result += '\n'; m_output += '[';
m_output += '\n';
} }
auto values = value.m_value.array->elements(); // Empty Array early return
for (auto it = values.begin(); it != values.end(); ++it) { if (value.m_value.array->empty()) {
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter); m_output += ']';
result += dumpHelper(*it, indentLevel + 1); return;
}
// Add comma, except after the last element size_t i = 0;
if (it != std::prev(values.end(), 1)) { auto it = value.m_value.array->elements().cbegin();
result += ","; if (!m_indent) {
for (; i < value.m_value.array->size() - 1; ++i, ++it) {
dumpHelper(*it, indentLevel + 1);
m_output += ',';
} }
if (m_indent > 0) { dumpHelper(*it, indentLevel + 1);
result += '\n';
} }
else {
std::string indentation = std::string(m_indent * (indentLevel + 1), m_indentCharacter);
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';
// Append indentation // Append indentation
result += std::string(m_indent * indentLevel, m_indentCharacter); m_output += std::string(m_indent * indentLevel, m_indentCharacter);
// Append ]
result += "]";
return result;
} }
std::string Serializer::dumpObject(const Value& value, const uint32_t indentLevel) m_output += "]";
}
void Serializer::dumpObject(const Value& value, const uint32_t indentLevel)
{ {
std::string result;
// Append {
result += "{";
if (m_indent > 0) { if (m_indent > 0) {
result += '\n'; m_output += '{';
m_output += '\n';
} }
auto members = value.m_value.object->members(); // Empty Object early return
for (auto it = members.begin(); it != members.end(); ++it) { if (value.m_value.object->empty()) {
result += std::string(m_indent * (indentLevel + 1), m_indentCharacter); m_output += '}';
result += "\"" + it->first + "\":"; return;
if (m_indent > 0) {
result += ' ';
} }
result += dumpHelper(it->second, indentLevel + 1);
// Add comma, except after the last element size_t i = 0;
if (it != std::prev(members.end(), 1)) { auto it = value.m_value.object->members().cbegin();
result += ","; if (!m_indent) {
for (; i < value.m_value.object->size() - 1; ++i, ++it) {
m_output += '"' + it->first + "\":";
dumpHelper(it->second, indentLevel + 1);
m_output += ',';
} }
if (m_indent > 0) { m_output += '"' + it->first + "\":";
result += '\n'; dumpHelper(it->second, indentLevel + 1);
} }
else {
std::string indentation = std::string(m_indent * (indentLevel + 1), m_indentCharacter);
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';
// Append indentation // Append indentation
result += std::string(m_indent * indentLevel, m_indentCharacter); m_output += std::string(m_indent * indentLevel, m_indentCharacter);
}
// Append } m_output += '}';
result += "}";
return result;
} }
} // namespace Json } // namespace Json
+6 -6
View File
@@ -16,17 +16,17 @@ namespace Json {
class Serializer { class Serializer {
public: public:
Serializer(const Value& value, const uint32_t indent = 0, const char indentCharacter = ' '); Serializer(const uint32_t indent = 0, const char indentCharacter = ' ');
virtual ~Serializer(); virtual ~Serializer();
std::string dump(); std::string dump(const Value& value);
private: private:
std::string dumpHelper(const Value& value, const uint32_t indentLevel = 0); void dumpHelper(const Value& value, const uint32_t indentLevel = 0);
std::string dumpArray(const Value& value, const uint32_t indentLevel = 0); void dumpArray(const Value& value, const uint32_t indentLevel = 0);
std::string dumpObject(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 }; uint32_t m_indent { 0 };
char m_indentCharacter { ' ' }; char m_indentCharacter { ' ' };
+10 -4
View File
@@ -157,10 +157,17 @@ Value Value::parse(const std::string& input)
return Job(input).fire(); 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 std::string Value::dump(const uint32_t indent, const char indentCharacter) const
{ {
Serializer serializer(*this, indent, indentCharacter); Serializer serializer(indent, indentCharacter);
return serializer.dump(); return serializer.dump(*this);
} }
void Value::emplace_back(Value value) void Value::emplace_back(Value value)
@@ -313,8 +320,7 @@ std::istream& operator>>(std::istream& input, Value& value)
} }
inputString.append(buffer, input.gcount()); inputString.append(buffer, input.gcount());
Job job(inputString); value = Job(inputString).fire();
value = job.fire();
return input; return input;
} }
+1
View File
@@ -66,6 +66,7 @@ public:
// -------------------------------------- // --------------------------------------
static Value parse(const std::string& input); 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; std::string dump(const uint32_t indent = 0, const char indentCharacter = ' ') const;
void clear(); void clear();
+46 -3
View File
@@ -7,15 +7,51 @@
namespace Util { namespace Util {
Timer::Timer() 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) Timer Timer::operator-(const Timer& timer)
{ {
return Timer(TimePoint { m_start - timer.start() }); 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> template<typename To, typename From>
To Timer::to(From from) To Timer::to(From from)
{ {
@@ -45,8 +81,15 @@ uint64_t Timer::toNanoseconds()
template<typename T> template<typename T>
uint64_t Timer::elapsed() uint64_t Timer::elapsed()
{ {
auto now = std::chrono::high_resolution_clock::now(); uint64_t elapsed = 0;
return std::chrono::duration_cast<T>(now - m_start).count();
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() uint64_t Timer::elapsedSeconds()
+7 -4
View File
@@ -11,13 +11,14 @@ using TimePoint = std::chrono::high_resolution_clock::time_point;
class Timer { class Timer {
public: public:
Timer(); Timer();
Timer(const TimePoint& timePoint) Timer(const TimePoint& timePoint);
: m_start(timePoint)
{
}
Timer operator-(const Timer& timer); Timer operator-(const Timer& timer);
static TimePoint now();
void pause();
void resume();
template<typename To, typename From> template<typename To, typename From>
To to(From from); To to(From from);
uint64_t toSeconds(); uint64_t toSeconds();
@@ -37,6 +38,8 @@ public:
const TimePoint& start() const { return m_start; } const TimePoint& start() const { return m_start; }
private: private:
bool m_running { true };
TimePoint m_accumulated;
TimePoint m_start; TimePoint m_start;
}; };