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(Array const&) { }
|
||||
void Visit(Object const&) { }
|
||||
void Visit(Integer const&) { }
|
||||
void Visit(Double const&) { }
|
||||
void Visit(Integer) { }
|
||||
void Visit(Double) { }
|
||||
void Visit(String const&) { }
|
||||
void Visit(Boolean const&) { }
|
||||
void Visit(Boolean) { }
|
||||
void Visit(Null const&) { is_null = true; }
|
||||
public:
|
||||
bool is_null = false;
|
||||
|
|
|
@ -1,125 +1,100 @@
|
|||
/**********************************************
|
||||
|
||||
License: BSD
|
||||
Project Webpage: http://cajun-jsonapi.sourceforge.net/
|
||||
Author: Terry Caton
|
||||
|
||||
***********************************************/
|
||||
// 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/
|
||||
|
||||
#include "libaegisub/cajun/writer.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
|
||||
/*
|
||||
|
||||
TODO:
|
||||
* better documentation
|
||||
* unicode character encoding
|
||||
|
||||
*/
|
||||
|
||||
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') << ']';
|
||||
namespace agi {
|
||||
void JsonWriter::Visit(json::Array const& array) {
|
||||
if (array.empty()) {
|
||||
ostr << "[]";
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (object.empty())
|
||||
m_ostr << "{}";
|
||||
else {
|
||||
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') << '}';
|
||||
void JsonWriter::Visit(json::Object const& object) {
|
||||
if (object.empty()) {
|
||||
ostr << "{}";
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
m_ostr << std::setprecision(20) << numberElement;
|
||||
void JsonWriter::Visit(double d) {
|
||||
ostr << std::setprecision(20) << d;
|
||||
|
||||
double unused;
|
||||
if (!std::modf(numberElement, &unused))
|
||||
m_ostr << ".0";
|
||||
if (!std::modf(d, &unused))
|
||||
ostr << ".0";
|
||||
}
|
||||
|
||||
void Writer::Write(Integer const& numberElement) {
|
||||
m_ostr << numberElement;
|
||||
}
|
||||
void JsonWriter::Visit(std::string const& str) {
|
||||
ostr << '"';
|
||||
|
||||
void Writer::Write(Boolean const& booleanElement) {
|
||||
m_ostr << (booleanElement ? "true" : "false");
|
||||
}
|
||||
|
||||
void Writer::Write(String const& stringElement) {
|
||||
m_ostr << '"';
|
||||
|
||||
std::string::const_iterator it(stringElement.begin()), itend(stringElement.end());
|
||||
for (; it != itend; ++it) {
|
||||
switch (*it) {
|
||||
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;
|
||||
for (auto c : str) {
|
||||
switch (c) {
|
||||
case '"': ostr << "\\\""; break;
|
||||
case '\\': ostr << "\\\\"; break;
|
||||
case '\b': ostr << "\\b"; break;
|
||||
case '\f': ostr << "\\f"; break;
|
||||
case '\n': ostr << "\\n"; break;
|
||||
case '\r': ostr << "\\r"; break;
|
||||
case '\t': ostr << "\\t"; break;
|
||||
default: ostr << c; break;
|
||||
}
|
||||
}
|
||||
|
||||
m_ostr << '"';
|
||||
ostr << '"';
|
||||
}
|
||||
|
||||
void Writer::Write(Null const&) {
|
||||
m_ostr << "null";
|
||||
void JsonWriter::Visit(int64_t i) { ostr << i; }
|
||||
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);
|
||||
json::Writer::Write(root, file.Get());
|
||||
agi::JsonWriter::Write(root, file.Get());
|
||||
}
|
||||
|
||||
void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
||||
|
|
|
@ -113,7 +113,7 @@ void JsonEmitter::log(SinkMessage const& sm) {
|
|||
entry["func"] = sm.func;
|
||||
entry["line"] = sm.line;
|
||||
entry["message"] = sm.message;
|
||||
json::Writer::Write(entry, *fp);
|
||||
agi::JsonWriter::Write(entry, *fp);
|
||||
fp->flush();
|
||||
}
|
||||
|
||||
|
|
|
@ -89,11 +89,11 @@ void MRUManager::Flush() {
|
|||
|
||||
for (auto const& mru_map : mru) {
|
||||
json::Array &array = out[mru_map.first];
|
||||
transform(begin(mru_map.second), end(mru_map.second),
|
||||
back_inserter(array), [](agi::fs::path const& p) { return p.string(); });
|
||||
for (auto const& p : mru_map.second)
|
||||
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 {
|
||||
|
|
|
@ -106,11 +106,11 @@ class ConfigVisitor final : public json::ConstVisitor {
|
|||
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));
|
||||
}
|
||||
|
||||
void Visit(const json::Double& number) {
|
||||
void Visit(double 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));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -30,10 +30,10 @@ struct ConstVisitor {
|
|||
|
||||
virtual void Visit(const Array& array) = 0;
|
||||
virtual void Visit(const Object& object) = 0;
|
||||
virtual void Visit(const Integer& number) = 0;
|
||||
virtual void Visit(const Double& number) = 0;
|
||||
virtual void Visit(int64_t number) = 0;
|
||||
virtual void Visit(double number) = 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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace json {
|
||||
namespace agi {
|
||||
|
||||
class Writer final : private ConstVisitor {
|
||||
Writer(std::ostream& ostr);
|
||||
void Write(const Object& object);
|
||||
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);
|
||||
class JsonWriter final : json::ConstVisitor {
|
||||
std::ostream &ostr;
|
||||
std::string indent;
|
||||
|
||||
void Visit(const Array& array) override;
|
||||
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;
|
||||
JsonWriter(std::ostream &ostr) : ostr(ostr) { }
|
||||
|
||||
std::ostream& m_ostr;
|
||||
int tab_depth = 0;
|
||||
void Visit(json::Array const& array) override;
|
||||
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:
|
||||
template <typename ElementTypeT>
|
||||
static void Write(const ElementTypeT& element, std::ostream& ostr) {
|
||||
Writer writer(ostr);
|
||||
writer.Write(element);
|
||||
ostr.flush(); // all done
|
||||
template <typename T>
|
||||
static void Write(T const& value, std::ostream& ostr) {
|
||||
JsonWriter(ostr).Visit(value);
|
||||
ostr.flush();
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetMessage();
|
||||
|
@ -333,9 +333,8 @@ void DialogShiftTimes::LoadHistory() {
|
|||
history_box->Freeze();
|
||||
|
||||
try {
|
||||
std::unique_ptr<std::istream> file(agi::io::Open(history_filename));
|
||||
json::UnknownElement root;
|
||||
json::Reader::Read(root, *file);
|
||||
json::Reader::Read(root, *agi::io::Open(history_filename));
|
||||
history = root;
|
||||
|
||||
for (auto& history_entry : history)
|
||||
|
|
|
@ -281,27 +281,27 @@ TEST_F(lagi_cajun, Write) {
|
|||
obj["String"] = "This \"is\" \\a \t test";
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ std::string roundtrip_test(const char *in) {
|
|||
json::Reader::Read(ele, iss);
|
||||
|
||||
std::stringstream oss;
|
||||
json::Writer::Write(ele, oss);
|
||||
agi::JsonWriter::Write(ele, oss);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue