mirror of https://github.com/odrling/Aegisub
Rewrite the remaining bits of json::Writer
This commit is contained in:
parent
bc410a99f6
commit
4c0e578eda
|
@ -24,10 +24,10 @@ namespace {
|
||||||
void Visit(Null&) { is_null = true; }
|
void Visit(Null&) { is_null = true; }
|
||||||
void Visit(Array const&) { }
|
void Visit(Array const&) { }
|
||||||
void Visit(Object const&) { }
|
void Visit(Object const&) { }
|
||||||
void Visit(Integer const&) { }
|
void Visit(Integer) { }
|
||||||
void Visit(Double const&) { }
|
void Visit(Double) { }
|
||||||
void Visit(String const&) { }
|
void Visit(String const&) { }
|
||||||
void Visit(Boolean const&) { }
|
void Visit(Boolean) { }
|
||||||
void Visit(Null const&) { is_null = true; }
|
void Visit(Null const&) { is_null = true; }
|
||||||
public:
|
public:
|
||||||
bool is_null = false;
|
bool is_null = false;
|
||||||
|
|
|
@ -1,125 +1,100 @@
|
||||||
/**********************************************
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
License: BSD
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
Project Webpage: http://cajun-jsonapi.sourceforge.net/
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
Author: Terry Caton
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
***********************************************/
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
#include "libaegisub/cajun/writer.h"
|
#include "libaegisub/cajun/writer.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
/*
|
namespace agi {
|
||||||
|
void JsonWriter::Visit(json::Array const& array) {
|
||||||
TODO:
|
if (array.empty()) {
|
||||||
* better documentation
|
ostr << "[]";
|
||||||
* unicode character encoding
|
return;
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace json {
|
|
||||||
|
|
||||||
Writer::Writer(std::ostream& ostr) : m_ostr(ostr) { }
|
|
||||||
|
|
||||||
void Writer::Write(Array const& array) {
|
|
||||||
if (array.empty())
|
|
||||||
m_ostr << "[]";
|
|
||||||
else {
|
|
||||||
m_ostr << '[' << std::endl;
|
|
||||||
++tab_depth;
|
|
||||||
|
|
||||||
Array::const_iterator it(array.begin()), itend(array.end());
|
|
||||||
while (it != itend) {
|
|
||||||
m_ostr << std::string(tab_depth, '\t');
|
|
||||||
|
|
||||||
Write(*it);
|
|
||||||
|
|
||||||
if (++it != itend)
|
|
||||||
m_ostr << ',';
|
|
||||||
m_ostr << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
--tab_depth;
|
|
||||||
m_ostr << std::string(tab_depth, '\t') << ']';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indent += '\t';
|
||||||
|
ostr << "[\n";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& entry : array) {
|
||||||
|
if (!first) ostr << ",\n";
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
ostr << indent;
|
||||||
|
Visit(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
indent.pop_back();
|
||||||
|
ostr << '\n' << indent << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::Write(Object const& object) {
|
void JsonWriter::Visit(json::Object const& object) {
|
||||||
if (object.empty())
|
if (object.empty()) {
|
||||||
m_ostr << "{}";
|
ostr << "{}";
|
||||||
else {
|
return;
|
||||||
m_ostr << '{' << std::endl;
|
|
||||||
++tab_depth;
|
|
||||||
|
|
||||||
Object::const_iterator it(object.begin()), itend(object.end());
|
|
||||||
while (it != itend) {
|
|
||||||
m_ostr << std::string(tab_depth, '\t');
|
|
||||||
Write(it->first);
|
|
||||||
m_ostr << " : ";
|
|
||||||
Write(it->second);
|
|
||||||
|
|
||||||
if (++it != itend)
|
|
||||||
m_ostr << ',';
|
|
||||||
m_ostr << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
--tab_depth;
|
|
||||||
m_ostr << std::string(tab_depth, '\t') << '}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indent += '\t';
|
||||||
|
ostr << "{\n";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for (auto const& entry : object) {
|
||||||
|
if (!first) ostr << ",\n";
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
ostr << indent;
|
||||||
|
Visit(entry.first);
|
||||||
|
ostr << " : ";
|
||||||
|
Visit(entry.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
indent.pop_back();
|
||||||
|
ostr << '\n' << indent << '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::Write(Double const& numberElement) {
|
void JsonWriter::Visit(double d) {
|
||||||
m_ostr << std::setprecision(20) << numberElement;
|
ostr << std::setprecision(20) << d;
|
||||||
|
|
||||||
double unused;
|
double unused;
|
||||||
if (!std::modf(numberElement, &unused))
|
if (!std::modf(d, &unused))
|
||||||
m_ostr << ".0";
|
ostr << ".0";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::Write(Integer const& numberElement) {
|
void JsonWriter::Visit(std::string const& str) {
|
||||||
m_ostr << numberElement;
|
ostr << '"';
|
||||||
}
|
|
||||||
|
|
||||||
void Writer::Write(Boolean const& booleanElement) {
|
for (auto c : str) {
|
||||||
m_ostr << (booleanElement ? "true" : "false");
|
switch (c) {
|
||||||
}
|
case '"': ostr << "\\\""; break;
|
||||||
|
case '\\': ostr << "\\\\"; break;
|
||||||
void Writer::Write(String const& stringElement) {
|
case '\b': ostr << "\\b"; break;
|
||||||
m_ostr << '"';
|
case '\f': ostr << "\\f"; break;
|
||||||
|
case '\n': ostr << "\\n"; break;
|
||||||
std::string::const_iterator it(stringElement.begin()), itend(stringElement.end());
|
case '\r': ostr << "\\r"; break;
|
||||||
for (; it != itend; ++it) {
|
case '\t': ostr << "\\t"; break;
|
||||||
switch (*it) {
|
default: ostr << c; break;
|
||||||
case '"': m_ostr << "\\\""; break;
|
|
||||||
case '\\': m_ostr << "\\\\"; break;
|
|
||||||
case '\b': m_ostr << "\\b"; break;
|
|
||||||
case '\f': m_ostr << "\\f"; break;
|
|
||||||
case '\n': m_ostr << "\\n"; break;
|
|
||||||
case '\r': m_ostr << "\\r"; break;
|
|
||||||
case '\t': m_ostr << "\\t"; break;
|
|
||||||
default: m_ostr << *it; break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ostr << '"';
|
ostr << '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::Write(Null const&) {
|
void JsonWriter::Visit(int64_t i) { ostr << i; }
|
||||||
m_ostr << "null";
|
void JsonWriter::Visit(bool b) { ostr << (b ? "true" : "false"); }
|
||||||
|
void JsonWriter::Visit(json::Null const&) { ostr << "null"; }
|
||||||
|
void JsonWriter::Visit(json::UnknownElement const& unknown) { unknown.Accept(*this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::Write(UnknownElement const& unknown) {
|
|
||||||
unknown.Accept(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Writer::Visit(Array const& array) { Write(array); }
|
|
||||||
void Writer::Visit(Object const& object) { Write(object); }
|
|
||||||
void Writer::Visit(Integer const& integer) { Write(integer); }
|
|
||||||
void Writer::Visit(Double const& dbl) { Write(dbl); }
|
|
||||||
void Writer::Visit(String const& string) { Write(string); }
|
|
||||||
void Writer::Visit(Boolean const& boolean) { Write(boolean); }
|
|
||||||
void Writer::Visit(Null const& null) { Write(null); }
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ void Hotkey::Flush() {
|
||||||
}
|
}
|
||||||
|
|
||||||
io::Save file(config_file);
|
io::Save file(config_file);
|
||||||
json::Writer::Write(root, file.Get());
|
agi::JsonWriter::Write(root, file.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
||||||
|
|
|
@ -113,7 +113,7 @@ void JsonEmitter::log(SinkMessage const& sm) {
|
||||||
entry["func"] = sm.func;
|
entry["func"] = sm.func;
|
||||||
entry["line"] = sm.line;
|
entry["line"] = sm.line;
|
||||||
entry["message"] = sm.message;
|
entry["message"] = sm.message;
|
||||||
json::Writer::Write(entry, *fp);
|
agi::JsonWriter::Write(entry, *fp);
|
||||||
fp->flush();
|
fp->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,11 +89,11 @@ void MRUManager::Flush() {
|
||||||
|
|
||||||
for (auto const& mru_map : mru) {
|
for (auto const& mru_map : mru) {
|
||||||
json::Array &array = out[mru_map.first];
|
json::Array &array = out[mru_map.first];
|
||||||
transform(begin(mru_map.second), end(mru_map.second),
|
for (auto const& p : mru_map.second)
|
||||||
back_inserter(array), [](agi::fs::path const& p) { return p.string(); });
|
array.push_back(p.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
json::Writer::Write(out, io::Save(config_name).Get());
|
agi::JsonWriter::Write(out, io::Save(config_name).Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MRUManager::Prune(std::string const& key, MRUListMap& map) const {
|
void MRUManager::Prune(std::string const& key, MRUListMap& map) const {
|
||||||
|
|
|
@ -106,11 +106,11 @@ class ConfigVisitor final : public json::ConstVisitor {
|
||||||
Error("Array type not handled");
|
Error("Array type not handled");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visit(const json::Integer& number) {
|
void Visit(int64_t number) {
|
||||||
values.push_back(agi::make_unique<OptionValueInt>(name, number));
|
values.push_back(agi::make_unique<OptionValueInt>(name, number));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visit(const json::Double& number) {
|
void Visit(double number) {
|
||||||
values.push_back(agi::make_unique<OptionValueDouble>(name, number));
|
values.push_back(agi::make_unique<OptionValueDouble>(name, number));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ class ConfigVisitor final : public json::ConstVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visit(const json::Boolean& boolean) {
|
void Visit(bool boolean) {
|
||||||
values.push_back(agi::make_unique<OptionValueBool>(name, boolean));
|
values.push_back(agi::make_unique<OptionValueBool>(name, boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ void Options::Flush() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json::Writer::Write(obj_out, io::Save(config_file).Get());
|
agi::JsonWriter::Write(obj_out, io::Save(config_file).Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace agi
|
} // namespace agi
|
||||||
|
|
|
@ -30,10 +30,10 @@ struct ConstVisitor {
|
||||||
|
|
||||||
virtual void Visit(const Array& array) = 0;
|
virtual void Visit(const Array& array) = 0;
|
||||||
virtual void Visit(const Object& object) = 0;
|
virtual void Visit(const Object& object) = 0;
|
||||||
virtual void Visit(const Integer& number) = 0;
|
virtual void Visit(int64_t number) = 0;
|
||||||
virtual void Visit(const Double& number) = 0;
|
virtual void Visit(double number) = 0;
|
||||||
virtual void Visit(const String& string) = 0;
|
virtual void Visit(const String& string) = 0;
|
||||||
virtual void Visit(const Boolean& boolean) = 0;
|
virtual void Visit(bool boolean) = 0;
|
||||||
virtual void Visit(const Null& null) = 0;
|
virtual void Visit(const Null& null) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,54 +1,47 @@
|
||||||
/**********************************************
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
License: BSD
|
|
||||||
Project Webpage: http://cajun-jsonapi.sourceforge.net/
|
|
||||||
Author: Terry Caton
|
|
||||||
|
|
||||||
***********************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "elements.h"
|
|
||||||
#include "visitor.h"
|
#include "visitor.h"
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace json {
|
namespace agi {
|
||||||
|
|
||||||
class Writer final : private ConstVisitor {
|
class JsonWriter final : json::ConstVisitor {
|
||||||
Writer(std::ostream& ostr);
|
std::ostream &ostr;
|
||||||
void Write(const Object& object);
|
std::string indent;
|
||||||
void Write(const Array& array);
|
|
||||||
void Write(const String& string);
|
|
||||||
void Write(const Integer& number);
|
|
||||||
void Write(const Double& number);
|
|
||||||
void Write(const Boolean& boolean);
|
|
||||||
void Write(const Null& null);
|
|
||||||
void Write(const UnknownElement& unknown);
|
|
||||||
|
|
||||||
void Visit(const Array& array) override;
|
JsonWriter(std::ostream &ostr) : ostr(ostr) { }
|
||||||
void Visit(const Object& object) override;
|
|
||||||
void Visit(const Integer& number) override;
|
|
||||||
void Visit(const Double& number) override;
|
|
||||||
void Visit(const String& string) override;
|
|
||||||
void Visit(const Boolean& boolean) override;
|
|
||||||
void Visit(const Null& null) override;
|
|
||||||
|
|
||||||
std::ostream& m_ostr;
|
void Visit(json::Array const& array) override;
|
||||||
int tab_depth = 0;
|
void Visit(bool boolean) override;
|
||||||
|
void Visit(double number) override;
|
||||||
|
void Visit(int64_t number) override;
|
||||||
|
void Visit(json::Null const& null) override;
|
||||||
|
void Visit(json::Object const& object) override;
|
||||||
|
void Visit(std::string const& string) override;
|
||||||
|
void Visit(json::UnknownElement const& unknown);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename ElementTypeT>
|
template <typename T>
|
||||||
static void Write(const ElementTypeT& element, std::ostream& ostr) {
|
static void Write(T const& value, std::ostream& ostr) {
|
||||||
Writer writer(ostr);
|
JsonWriter(ostr).Visit(value);
|
||||||
writer.Write(element);
|
ostr.flush();
|
||||||
ostr.flush(); // all done
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator <<(std::ostream& ostr, UnknownElement const& elementRoot) {
|
|
||||||
Writer::Write(elementRoot, ostr);
|
|
||||||
return ostr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End namespace
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ void DialogShiftTimes::SaveHistory(json::Array const& shifted_blocks) {
|
||||||
history.resize(50);
|
history.resize(50);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
json::Writer::Write(history, agi::io::Save(history_filename).Get());
|
agi::JsonWriter::Write(history, agi::io::Save(history_filename).Get());
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetMessage();
|
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetMessage();
|
||||||
|
@ -333,9 +333,8 @@ void DialogShiftTimes::LoadHistory() {
|
||||||
history_box->Freeze();
|
history_box->Freeze();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::unique_ptr<std::istream> file(agi::io::Open(history_filename));
|
|
||||||
json::UnknownElement root;
|
json::UnknownElement root;
|
||||||
json::Reader::Read(root, *file);
|
json::Reader::Read(root, *agi::io::Open(history_filename));
|
||||||
history = root;
|
history = root;
|
||||||
|
|
||||||
for (auto& history_entry : history)
|
for (auto& history_entry : history)
|
||||||
|
|
|
@ -281,27 +281,27 @@ TEST_F(lagi_cajun, Write) {
|
||||||
obj["String"] = "This \"is\" \\a \t test";
|
obj["String"] = "This \"is\" \\a \t test";
|
||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
EXPECT_NO_THROW(json::Writer::Write(obj, stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(obj, stream));
|
||||||
EXPECT_STREQ("{\n\t\"Boolean\" : true,\n\t\"String\" : \"This \\\"is\\\" \\\\a \\t test\"\n}", stream.str().c_str());
|
EXPECT_STREQ("{\n\t\"Boolean\" : true,\n\t\"String\" : \"This \\\"is\\\" \\\\a \\t test\"\n}", stream.str().c_str());
|
||||||
|
|
||||||
stream.str("");
|
stream.str("");
|
||||||
EXPECT_NO_THROW(json::Writer::Write(json::Array(), stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(json::Array(), stream));
|
||||||
EXPECT_STREQ("[]", stream.str().c_str());
|
EXPECT_STREQ("[]", stream.str().c_str());
|
||||||
|
|
||||||
stream.str("");
|
stream.str("");
|
||||||
EXPECT_NO_THROW(json::Writer::Write(json::Object(), stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(json::Object(), stream));
|
||||||
EXPECT_STREQ("{}", stream.str().c_str());
|
EXPECT_STREQ("{}", stream.str().c_str());
|
||||||
|
|
||||||
stream.str("");
|
stream.str("");
|
||||||
EXPECT_NO_THROW(json::Writer::Write(true, stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(true, stream));
|
||||||
EXPECT_STREQ("true", stream.str().c_str());
|
EXPECT_STREQ("true", stream.str().c_str());
|
||||||
|
|
||||||
stream.str("");
|
stream.str("");
|
||||||
EXPECT_NO_THROW(json::Writer::Write(false, stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(false, stream));
|
||||||
EXPECT_STREQ("false", stream.str().c_str());
|
EXPECT_STREQ("false", stream.str().c_str());
|
||||||
|
|
||||||
stream.str("");
|
stream.str("");
|
||||||
EXPECT_NO_THROW(json::Writer::Write(json::Null(), stream));
|
EXPECT_NO_THROW(agi::JsonWriter::Write(json::Null(), stream));
|
||||||
EXPECT_STREQ("null", stream.str().c_str());
|
EXPECT_STREQ("null", stream.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ std::string roundtrip_test(const char *in) {
|
||||||
json::Reader::Read(ele, iss);
|
json::Reader::Read(ele, iss);
|
||||||
|
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
json::Writer::Write(ele, oss);
|
agi::JsonWriter::Write(ele, oss);
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue