forked from mia/Aegisub
07da6f6f1b
Trying to decide whether an option should be an int or double after discarding the differences between "1.0" and "1" simply isn't possible, and even if an option was initialized correctly, if it was changed to a round number it could get written as an int and break later. Also convert cajun to tabs because three spaces to indent is terrible. Originally committed to SVN as r6018.
131 lines
2.8 KiB
C++
131 lines
2.8 KiB
C++
/**********************************************
|
|
|
|
License: BSD
|
|
Project Webpage: http://cajun-jsonapi.sourceforge.net/
|
|
Author: Terry Caton
|
|
|
|
***********************************************/
|
|
|
|
#include "libaegisub/cajun/writer.h"
|
|
|
|
#ifndef LAGI_PRE
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#endif
|
|
|
|
/*
|
|
|
|
TODO:
|
|
* better documentation
|
|
* unicode character encoding
|
|
|
|
*/
|
|
|
|
namespace json
|
|
{
|
|
|
|
Writer::Writer(std::ostream& ostr)
|
|
: m_ostr(ostr)
|
|
, tab_depth(0)
|
|
{
|
|
}
|
|
|
|
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') << ']';
|
|
}
|
|
}
|
|
|
|
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') << '"' << it->first << "\" : ";
|
|
Write(it->second);
|
|
|
|
if (++it != itend)
|
|
m_ostr << ',';
|
|
m_ostr << std::endl;
|
|
}
|
|
|
|
--tab_depth;
|
|
m_ostr << std::string(tab_depth, '\t') << '}';
|
|
}
|
|
}
|
|
|
|
void Writer::Write(Double const& numberElement) {
|
|
m_ostr << std::setprecision(20) << numberElement;
|
|
|
|
double unused;
|
|
if (!std::modf(numberElement, &unused))
|
|
m_ostr << ".0";
|
|
}
|
|
|
|
void Writer::Write(Integer const& numberElement) {
|
|
m_ostr << numberElement;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
m_ostr << '"';
|
|
}
|
|
|
|
void Writer::Write(Null const&) {
|
|
m_ostr << "null";
|
|
}
|
|
|
|
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
|