mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-03-03 21:06:24 +01:00
Merge pull request #132 from cdunn2001/builder
StreamWriter::Builder Deprecate old Writers, but include them in tests. This should still be binary-compatible with 1.3.0.
This commit is contained in:
commit
54b8e6939a
@ -73,24 +73,31 @@ for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the seq
|
|||||||
setIndentLength( root["indent"].get("length", 3).asInt() );
|
setIndentLength( root["indent"].get("length", 3).asInt() );
|
||||||
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
||||||
|
|
||||||
// ...
|
|
||||||
// At application shutdown to make the new configuration document:
|
|
||||||
// Since Json::Value has implicit constructor for all value types, it is not
|
// Since Json::Value has implicit constructor for all value types, it is not
|
||||||
// necessary to explicitly construct the Json::Value object:
|
// necessary to explicitly construct the Json::Value object:
|
||||||
root["encoding"] = getCurrentEncoding();
|
root["encoding"] = getCurrentEncoding();
|
||||||
root["indent"]["length"] = getCurrentIndentLength();
|
root["indent"]["length"] = getCurrentIndentLength();
|
||||||
root["indent"]["use_space"] = getCurrentIndentUseSpace();
|
root["indent"]["use_space"] = getCurrentIndentUseSpace();
|
||||||
|
|
||||||
Json::StyledWriter writer;
|
// To write into a steam with minimal memory overhead,
|
||||||
// Make a new JSON document for the configuration. Preserve original comments.
|
// create a Builder for a StreamWriter.
|
||||||
std::string outputConfig = writer.write( root );
|
Json::StreamWriter::Builder builder;
|
||||||
|
builder.withIndentation(" "); // or whatever you like
|
||||||
|
|
||||||
// You can also use streams. This will put the contents of any JSON
|
// Then build a StreamWriter.
|
||||||
|
// (Of course, you can write to std::ostringstream if you prefer.)
|
||||||
|
std::shared_ptr<Json::StreamWriter> writer(
|
||||||
|
builder.newStreamWriter( &std::cout );
|
||||||
|
|
||||||
|
// Make a new JSON document for the configuration. Preserve original comments.
|
||||||
|
writer->write( root );
|
||||||
|
|
||||||
|
// If you like the defaults, you can insert directly into a stream.
|
||||||
|
std::cout << root;
|
||||||
|
|
||||||
|
// You can also read from a stream. This will put the contents of any JSON
|
||||||
// stream at a particular sub-value, if you'd like.
|
// stream at a particular sub-value, if you'd like.
|
||||||
std::cin >> root["subtree"];
|
std::cin >> root["subtree"];
|
||||||
|
|
||||||
// And you can write to a stream, using the StyledWriter automatically.
|
|
||||||
std::cout << root;
|
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\section _pbuild Build instructions
|
\section _pbuild Build instructions
|
||||||
|
@ -22,8 +22,88 @@
|
|||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
|
class StreamWriterBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
using namespace Json;
|
||||||
|
Value value;
|
||||||
|
StreamWriter::Builder builder;
|
||||||
|
builder.withCommentStyle(StreamWriter::CommentStyle::None);
|
||||||
|
std::shared_ptr<StreamWriter> writer(
|
||||||
|
builder.newStreamWriter(&std::cout));
|
||||||
|
writer->write(value);
|
||||||
|
std::cout.flush();
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriter {
|
||||||
|
protected:
|
||||||
|
std::ostream& sout_; // not owned; will not delete
|
||||||
|
public:
|
||||||
|
/// `All`: Keep all comments.
|
||||||
|
/// `None`: Drop all comments.
|
||||||
|
/// Use `Most` to recover the odd behavior of previous versions.
|
||||||
|
/// Only `All` is currently implemented.
|
||||||
|
enum class CommentStyle {None, Most, All};
|
||||||
|
|
||||||
|
/// Keep a reference, but do not take ownership of `sout`.
|
||||||
|
StreamWriter(std::ostream* sout);
|
||||||
|
virtual ~StreamWriter();
|
||||||
|
/// Write Value into document as configured in sub-class.
|
||||||
|
/// \return zero on success
|
||||||
|
/// \throw std::exception possibly, depending on configuration
|
||||||
|
virtual int write(Value const& root) = 0;
|
||||||
|
|
||||||
|
/// Because this Builder is non-virtual, we can safely add
|
||||||
|
/// methods without a major version bump.
|
||||||
|
/// \see http://stackoverflow.com/questions/14875052/pure-virtual-functions-and-binary-compatibility
|
||||||
|
class Builder {
|
||||||
|
StreamWriterBuilder* own_;
|
||||||
|
Builder(Builder const&); // noncopyable
|
||||||
|
void operator=(Builder const&); // noncopyable
|
||||||
|
public:
|
||||||
|
Builder();
|
||||||
|
~Builder(); // delete underlying StreamWriterBuilder
|
||||||
|
|
||||||
|
Builder& withCommentStyle(CommentStyle cs); /// default: All
|
||||||
|
/** \brief Write in human-friendly style.
|
||||||
|
|
||||||
|
If "", then skip all indentation, newlines, and comments,
|
||||||
|
which implies CommentStyle::None.
|
||||||
|
Default: "\t"
|
||||||
|
*/
|
||||||
|
Builder& withIndentation(std::string indentation);
|
||||||
|
/** \brief Drop the "null" string from the writer's output for nullValues.
|
||||||
|
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
|
* fed to a browser's Javascript, it makes for smaller output and the
|
||||||
|
* browser can handle the output just fine.
|
||||||
|
*/
|
||||||
|
Builder& withDropNullPlaceholders(bool v);
|
||||||
|
/** \brief Do not add \n at end of document.
|
||||||
|
* Normally, we add an extra newline, just because.
|
||||||
|
*/
|
||||||
|
Builder& withOmitEndingLineFeed(bool v);
|
||||||
|
/** \brief Add a space after ':'.
|
||||||
|
* If indentation is non-empty, we surround colon with whitespace,
|
||||||
|
* e.g. " : "
|
||||||
|
* This will add back the trailing space when there is no indentation.
|
||||||
|
* This seems dubious when the entire document is on a single line,
|
||||||
|
* but we leave this here to repduce the behavior of the old `FastWriter`.
|
||||||
|
*/
|
||||||
|
Builder& withEnableYAMLCompatibility(bool v);
|
||||||
|
|
||||||
|
/// Do not take ownership of sout, but maintain a reference.
|
||||||
|
StreamWriter* newStreamWriter(std::ostream* sout) const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Write into stringstream, then return string, for convenience.
|
||||||
|
std::string writeString(Value const& root, StreamWriter::Builder const& builder);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Abstract class for writers.
|
/** \brief Abstract class for writers.
|
||||||
|
* \deprecated Use StreamWriter::Builder.
|
||||||
*/
|
*/
|
||||||
class JSON_API Writer {
|
class JSON_API Writer {
|
||||||
public:
|
public:
|
||||||
@ -39,6 +119,7 @@ public:
|
|||||||
*consumption,
|
*consumption,
|
||||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||||
* \sa Reader, Value
|
* \sa Reader, Value
|
||||||
|
* \deprecated Use StreamWriter::Builder.
|
||||||
*/
|
*/
|
||||||
class JSON_API FastWriter : public Writer {
|
class JSON_API FastWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
@ -90,6 +171,7 @@ private:
|
|||||||
*#CommentPlacement.
|
*#CommentPlacement.
|
||||||
*
|
*
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriter::Builder.
|
||||||
*/
|
*/
|
||||||
class JSON_API StyledWriter : public Writer {
|
class JSON_API StyledWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
@ -151,6 +233,7 @@ private:
|
|||||||
*
|
*
|
||||||
* \param indentation Each level will be indented by this amount extra.
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriter::Builder.
|
||||||
*/
|
*/
|
||||||
class JSON_API StyledStreamWriter {
|
class JSON_API StyledStreamWriter {
|
||||||
public:
|
public:
|
||||||
|
@ -151,7 +151,6 @@ static int parseAndSaveValueTree(const std::string& input,
|
|||||||
reader.getFormattedErrorMessages().c_str());
|
reader.getFormattedErrorMessages().c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parseOnly) {
|
if (!parseOnly) {
|
||||||
FILE* factual = fopen(actual.c_str(), "wt");
|
FILE* factual = fopen(actual.c_str(), "wt");
|
||||||
if (!factual) {
|
if (!factual) {
|
||||||
@ -182,6 +181,13 @@ static std::string useStyledStreamWriter(
|
|||||||
writer.write(sout, root);
|
writer.write(sout, root);
|
||||||
return sout.str();
|
return sout.str();
|
||||||
}
|
}
|
||||||
|
static std::string useBuiltStyledStreamWriter(
|
||||||
|
Json::Value const& root)
|
||||||
|
{
|
||||||
|
Json::StreamWriter::Builder builder;
|
||||||
|
builder.withCommentStyle(Json::StreamWriter::CommentStyle::All);
|
||||||
|
return writeString(root, builder);
|
||||||
|
}
|
||||||
static int rewriteValueTree(
|
static int rewriteValueTree(
|
||||||
const std::string& rewritePath,
|
const std::string& rewritePath,
|
||||||
const Json::Value& root,
|
const Json::Value& root,
|
||||||
@ -248,6 +254,8 @@ static int parseCommandLine(
|
|||||||
opts->write = &useStyledWriter;
|
opts->write = &useStyledWriter;
|
||||||
} else if (writerName == "StyledStreamWriter") {
|
} else if (writerName == "StyledStreamWriter") {
|
||||||
opts->write = &useStyledStreamWriter;
|
opts->write = &useStyledStreamWriter;
|
||||||
|
} else if (writerName == "BuiltStyledStreamWriter") {
|
||||||
|
opts->write = &useBuiltStyledStreamWriter;
|
||||||
} else {
|
} else {
|
||||||
printf("Unknown '--json-writer %s'\n", writerName.c_str());
|
printf("Unknown '--json-writer %s'\n", writerName.c_str());
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
#include <json/writer.h>
|
#include <json/writer.h>
|
||||||
#include "json_tool.h"
|
#include "json_tool.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <iomanip>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
@ -664,9 +665,442 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
|
|||||||
value.hasComment(commentAfter);
|
value.hasComment(commentAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& sout, const Value& root) {
|
//////////////////////////
|
||||||
Json::StyledStreamWriter writer;
|
// BuiltStyledStreamWriter
|
||||||
writer.write(sout, root);
|
|
||||||
|
struct BuiltStyledStreamWriter : public StreamWriter
|
||||||
|
{
|
||||||
|
BuiltStyledStreamWriter(
|
||||||
|
std::ostream* sout,
|
||||||
|
std::string const& indentation,
|
||||||
|
StreamWriter::CommentStyle cs,
|
||||||
|
std::string const& colonSymbol,
|
||||||
|
std::string const& nullSymbol,
|
||||||
|
std::string const& endingLineFeedSymbol);
|
||||||
|
virtual int write(Value const& root);
|
||||||
|
private:
|
||||||
|
void writeValue(Value const& value);
|
||||||
|
void writeArrayValue(Value const& value);
|
||||||
|
bool isMultineArray(Value const& value);
|
||||||
|
void pushValue(std::string const& value);
|
||||||
|
void writeIndent();
|
||||||
|
void writeWithIndent(std::string const& value);
|
||||||
|
void indent();
|
||||||
|
void unindent();
|
||||||
|
void writeCommentBeforeValue(Value const& root);
|
||||||
|
void writeCommentAfterValueOnSameLine(Value const& root);
|
||||||
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
|
||||||
|
typedef std::vector<std::string> ChildValues;
|
||||||
|
|
||||||
|
ChildValues childValues_;
|
||||||
|
std::string indentString_;
|
||||||
|
int rightMargin_;
|
||||||
|
std::string indentation_;
|
||||||
|
CommentStyle cs_;
|
||||||
|
std::string colonSymbol_;
|
||||||
|
std::string nullSymbol_;
|
||||||
|
std::string endingLineFeedSymbol_;
|
||||||
|
bool addChildValues_ : 1;
|
||||||
|
bool indented_ : 1;
|
||||||
|
};
|
||||||
|
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
||||||
|
std::ostream* sout,
|
||||||
|
std::string const& indentation,
|
||||||
|
StreamWriter::CommentStyle cs,
|
||||||
|
std::string const& colonSymbol,
|
||||||
|
std::string const& nullSymbol,
|
||||||
|
std::string const& endingLineFeedSymbol)
|
||||||
|
: StreamWriter(sout)
|
||||||
|
, rightMargin_(74)
|
||||||
|
, indentation_(indentation)
|
||||||
|
, cs_(cs)
|
||||||
|
, colonSymbol_(colonSymbol)
|
||||||
|
, nullSymbol_(nullSymbol)
|
||||||
|
, endingLineFeedSymbol_(endingLineFeedSymbol)
|
||||||
|
, addChildValues_(false)
|
||||||
|
, indented_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
int BuiltStyledStreamWriter::write(Value const& root)
|
||||||
|
{
|
||||||
|
addChildValues_ = false;
|
||||||
|
indented_ = true;
|
||||||
|
indentString_ = "";
|
||||||
|
writeCommentBeforeValue(root);
|
||||||
|
if (!indented_) writeIndent();
|
||||||
|
indented_ = true;
|
||||||
|
writeValue(root);
|
||||||
|
writeCommentAfterValueOnSameLine(root);
|
||||||
|
sout_ << endingLineFeedSymbol_;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||||
|
switch (value.type()) {
|
||||||
|
case nullValue:
|
||||||
|
pushValue(nullSymbol_);
|
||||||
|
break;
|
||||||
|
case intValue:
|
||||||
|
pushValue(valueToString(value.asLargestInt()));
|
||||||
|
break;
|
||||||
|
case uintValue:
|
||||||
|
pushValue(valueToString(value.asLargestUInt()));
|
||||||
|
break;
|
||||||
|
case realValue:
|
||||||
|
pushValue(valueToString(value.asDouble()));
|
||||||
|
break;
|
||||||
|
case stringValue:
|
||||||
|
pushValue(valueToQuotedString(value.asCString()));
|
||||||
|
break;
|
||||||
|
case booleanValue:
|
||||||
|
pushValue(valueToString(value.asBool()));
|
||||||
|
break;
|
||||||
|
case arrayValue:
|
||||||
|
writeArrayValue(value);
|
||||||
|
break;
|
||||||
|
case objectValue: {
|
||||||
|
Value::Members members(value.getMemberNames());
|
||||||
|
if (members.empty())
|
||||||
|
pushValue("{}");
|
||||||
|
else {
|
||||||
|
writeWithIndent("{");
|
||||||
|
indent();
|
||||||
|
Value::Members::iterator it = members.begin();
|
||||||
|
for (;;) {
|
||||||
|
std::string const& name = *it;
|
||||||
|
Value const& childValue = value[name];
|
||||||
|
writeCommentBeforeValue(childValue);
|
||||||
|
writeWithIndent(valueToQuotedString(name.c_str()));
|
||||||
|
sout_ << colonSymbol_;
|
||||||
|
writeValue(childValue);
|
||||||
|
if (++it == members.end()) {
|
||||||
|
writeCommentAfterValueOnSameLine(childValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sout_ << ",";
|
||||||
|
writeCommentAfterValueOnSameLine(childValue);
|
||||||
|
}
|
||||||
|
unindent();
|
||||||
|
writeWithIndent("}");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
|
||||||
|
unsigned size = value.size();
|
||||||
|
if (size == 0)
|
||||||
|
pushValue("[]");
|
||||||
|
else {
|
||||||
|
bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
|
||||||
|
if (isMultiLine) {
|
||||||
|
writeWithIndent("[");
|
||||||
|
indent();
|
||||||
|
bool hasChildValue = !childValues_.empty();
|
||||||
|
unsigned index = 0;
|
||||||
|
for (;;) {
|
||||||
|
Value const& childValue = value[index];
|
||||||
|
writeCommentBeforeValue(childValue);
|
||||||
|
if (hasChildValue)
|
||||||
|
writeWithIndent(childValues_[index]);
|
||||||
|
else {
|
||||||
|
if (!indented_) writeIndent();
|
||||||
|
indented_ = true;
|
||||||
|
writeValue(childValue);
|
||||||
|
indented_ = false;
|
||||||
|
}
|
||||||
|
if (++index == size) {
|
||||||
|
writeCommentAfterValueOnSameLine(childValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sout_ << ",";
|
||||||
|
writeCommentAfterValueOnSameLine(childValue);
|
||||||
|
}
|
||||||
|
unindent();
|
||||||
|
writeWithIndent("]");
|
||||||
|
} else // output on a single line
|
||||||
|
{
|
||||||
|
assert(childValues_.size() == size);
|
||||||
|
sout_ << "[";
|
||||||
|
if (!indentation_.empty()) sout_ << " ";
|
||||||
|
for (unsigned index = 0; index < size; ++index) {
|
||||||
|
if (index > 0)
|
||||||
|
sout_ << ", ";
|
||||||
|
sout_ << childValues_[index];
|
||||||
|
}
|
||||||
|
if (!indentation_.empty()) sout_ << " ";
|
||||||
|
sout_ << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
|
||||||
|
int size = value.size();
|
||||||
|
bool isMultiLine = size * 3 >= rightMargin_;
|
||||||
|
childValues_.clear();
|
||||||
|
for (int index = 0; index < size && !isMultiLine; ++index) {
|
||||||
|
Value const& childValue = value[index];
|
||||||
|
isMultiLine =
|
||||||
|
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
|
||||||
|
childValue.size() > 0);
|
||||||
|
}
|
||||||
|
if (!isMultiLine) // check if line length > max line length
|
||||||
|
{
|
||||||
|
childValues_.reserve(size);
|
||||||
|
addChildValues_ = true;
|
||||||
|
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
||||||
|
for (int index = 0; index < size; ++index) {
|
||||||
|
if (hasCommentForValue(value[index])) {
|
||||||
|
isMultiLine = true;
|
||||||
|
}
|
||||||
|
writeValue(value[index]);
|
||||||
|
lineLength += int(childValues_[index].length());
|
||||||
|
}
|
||||||
|
addChildValues_ = false;
|
||||||
|
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
||||||
|
}
|
||||||
|
return isMultiLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::pushValue(std::string const& value) {
|
||||||
|
if (addChildValues_)
|
||||||
|
childValues_.push_back(value);
|
||||||
|
else
|
||||||
|
sout_ << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::writeIndent() {
|
||||||
|
// blep intended this to look at the so-far-written string
|
||||||
|
// to determine whether we are already indented, but
|
||||||
|
// with a stream we cannot do that. So we rely on some saved state.
|
||||||
|
// The caller checks indented_.
|
||||||
|
|
||||||
|
if (!indentation_.empty()) {
|
||||||
|
// In this case, drop newlines too.
|
||||||
|
sout_ << '\n' << indentString_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
|
||||||
|
if (!indented_) writeIndent();
|
||||||
|
sout_ << value;
|
||||||
|
indented_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::unindent() {
|
||||||
|
assert(indentString_.size() >= indentation_.size());
|
||||||
|
indentString_.resize(indentString_.size() - indentation_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
|
||||||
|
if (cs_ == CommentStyle::None) return;
|
||||||
|
if (!root.hasComment(commentBefore))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!indented_) writeIndent();
|
||||||
|
const std::string& comment = root.getComment(commentBefore);
|
||||||
|
std::string::const_iterator iter = comment.begin();
|
||||||
|
while (iter != comment.end()) {
|
||||||
|
sout_ << *iter;
|
||||||
|
if (*iter == '\n' &&
|
||||||
|
(iter != comment.end() && *(iter + 1) == '/'))
|
||||||
|
// writeIndent(); // would write extra newline
|
||||||
|
sout_ << indentString_;
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
indented_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
|
||||||
|
if (cs_ == CommentStyle::None) return;
|
||||||
|
if (root.hasComment(commentAfterOnSameLine))
|
||||||
|
sout_ << " " + root.getComment(commentAfterOnSameLine);
|
||||||
|
|
||||||
|
if (root.hasComment(commentAfter)) {
|
||||||
|
writeIndent();
|
||||||
|
sout_ << root.getComment(commentAfter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
|
||||||
|
return value.hasComment(commentBefore) ||
|
||||||
|
value.hasComment(commentAfterOnSameLine) ||
|
||||||
|
value.hasComment(commentAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////
|
||||||
|
// StreamWriter
|
||||||
|
|
||||||
|
StreamWriter::StreamWriter(std::ostream* sout)
|
||||||
|
: sout_(*sout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StreamWriter::~StreamWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
struct MyStreamWriter : public StreamWriter {
|
||||||
|
public:
|
||||||
|
MyStreamWriter(std::ostream* sout);
|
||||||
|
virtual ~MyStreamWriter();
|
||||||
|
virtual int write(Value const& root) = 0;
|
||||||
|
};
|
||||||
|
MyStreamWriter::MyStreamWriter(std::ostream* sout)
|
||||||
|
: StreamWriter(sout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
MyStreamWriter::~MyStreamWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
int MyStreamWriter::write(Value const& root)
|
||||||
|
{
|
||||||
|
sout_ << root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
class StreamWriterBuilder {
|
||||||
|
typedef StreamWriter::CommentStyle CommentStyle;
|
||||||
|
CommentStyle cs_;
|
||||||
|
std::string indentation_;
|
||||||
|
bool dropNullPlaceholders_;
|
||||||
|
bool omitEndingLineFeed_;
|
||||||
|
bool enableYAMLCompatibility_;
|
||||||
|
public:
|
||||||
|
StreamWriterBuilder();
|
||||||
|
virtual ~StreamWriterBuilder();
|
||||||
|
virtual void setCommentStyle(CommentStyle cs);
|
||||||
|
virtual void setIndentation(std::string indentation);
|
||||||
|
virtual void setDropNullPlaceholders(bool v);
|
||||||
|
virtual void setOmitEndingLineFeed(bool v);
|
||||||
|
virtual void setEnableYAMLCompatibility(bool v);
|
||||||
|
virtual StreamWriter* newStreamWriter(std::ostream* sout) const;
|
||||||
|
};
|
||||||
|
StreamWriterBuilder::StreamWriterBuilder()
|
||||||
|
: cs_(CommentStyle::All)
|
||||||
|
, indentation_("\t")
|
||||||
|
, dropNullPlaceholders_(false)
|
||||||
|
, omitEndingLineFeed_(false)
|
||||||
|
, enableYAMLCompatibility_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StreamWriterBuilder::~StreamWriterBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void StreamWriterBuilder::setCommentStyle(CommentStyle v)
|
||||||
|
{
|
||||||
|
cs_ = v;
|
||||||
|
}
|
||||||
|
void StreamWriterBuilder::setIndentation(std::string v)
|
||||||
|
{
|
||||||
|
indentation_ = v;
|
||||||
|
if (indentation_.empty()) cs_ = CommentStyle::None;
|
||||||
|
}
|
||||||
|
void StreamWriterBuilder::setDropNullPlaceholders(bool v)
|
||||||
|
{
|
||||||
|
dropNullPlaceholders_ = v;
|
||||||
|
}
|
||||||
|
void StreamWriterBuilder::setOmitEndingLineFeed(bool v)
|
||||||
|
{
|
||||||
|
omitEndingLineFeed_ = v;
|
||||||
|
}
|
||||||
|
void StreamWriterBuilder::setEnableYAMLCompatibility(bool v)
|
||||||
|
{
|
||||||
|
enableYAMLCompatibility_ = v;
|
||||||
|
}
|
||||||
|
StreamWriter* StreamWriterBuilder::newStreamWriter(std::ostream* stream) const
|
||||||
|
{
|
||||||
|
std::string colonSymbol = " : ";
|
||||||
|
if (indentation_.empty()) {
|
||||||
|
if (enableYAMLCompatibility_) {
|
||||||
|
colonSymbol = ": ";
|
||||||
|
} else {
|
||||||
|
colonSymbol = ":";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string nullSymbol = "null";
|
||||||
|
if (dropNullPlaceholders_) {
|
||||||
|
nullSymbol = "";
|
||||||
|
}
|
||||||
|
std::string endingLineFeedSymbol = "\n";
|
||||||
|
if (omitEndingLineFeed_) {
|
||||||
|
endingLineFeedSymbol = "";
|
||||||
|
}
|
||||||
|
return new BuiltStyledStreamWriter(stream,
|
||||||
|
indentation_, cs_,
|
||||||
|
colonSymbol, nullSymbol, endingLineFeedSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This might become public someday.
|
||||||
|
class StreamWriterBuilderFactory {
|
||||||
|
public:
|
||||||
|
virtual ~StreamWriterBuilderFactory();
|
||||||
|
virtual StreamWriterBuilder* newStreamWriterBuilder() const;
|
||||||
|
};
|
||||||
|
StreamWriterBuilderFactory::~StreamWriterBuilderFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StreamWriterBuilder* StreamWriterBuilderFactory::newStreamWriterBuilder() const
|
||||||
|
{
|
||||||
|
return new StreamWriterBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamWriter::Builder::Builder()
|
||||||
|
: own_(StreamWriterBuilderFactory().newStreamWriterBuilder())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StreamWriter::Builder::~Builder()
|
||||||
|
{
|
||||||
|
delete own_;
|
||||||
|
}
|
||||||
|
StreamWriter::Builder::Builder(Builder const&)
|
||||||
|
: own_(nullptr)
|
||||||
|
{abort();}
|
||||||
|
void StreamWriter::Builder::operator=(Builder const&)
|
||||||
|
{abort();}
|
||||||
|
StreamWriter::Builder& StreamWriter::Builder::withCommentStyle(CommentStyle v)
|
||||||
|
{
|
||||||
|
own_->setCommentStyle(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
StreamWriter::Builder& StreamWriter::Builder::withIndentation(std::string v)
|
||||||
|
{
|
||||||
|
own_->setIndentation(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
StreamWriter::Builder& StreamWriter::Builder::withDropNullPlaceholders(bool v)
|
||||||
|
{
|
||||||
|
own_->setDropNullPlaceholders(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
StreamWriter::Builder& StreamWriter::Builder::withOmitEndingLineFeed(bool v)
|
||||||
|
{
|
||||||
|
own_->setOmitEndingLineFeed(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
StreamWriter::Builder& StreamWriter::Builder::withEnableYAMLCompatibility(bool v)
|
||||||
|
{
|
||||||
|
own_->setEnableYAMLCompatibility(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
StreamWriter* StreamWriter::Builder::newStreamWriter(std::ostream* sout) const
|
||||||
|
{
|
||||||
|
return own_->newStreamWriter(sout);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string writeString(Value const& root, StreamWriter::Builder const& builder) {
|
||||||
|
std::ostringstream sout;
|
||||||
|
std::unique_ptr<StreamWriter> const sw(builder.newStreamWriter(&sout));
|
||||||
|
sw->write(root);
|
||||||
|
return sout.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& sout, Value const& root) {
|
||||||
|
StreamWriter::Builder builder;
|
||||||
|
builder.withCommentStyle(StreamWriter::CommentStyle::All);
|
||||||
|
builder.withIndentation("\t");
|
||||||
|
std::shared_ptr<StreamWriter> writer(builder.newStreamWriter(&sout));
|
||||||
|
writer->write(root);
|
||||||
return sout;
|
return sout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,16 +147,23 @@ def main():
|
|||||||
else:
|
else:
|
||||||
input_path = None
|
input_path = None
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
status = runAllTests(jsontest_executable_path, input_path,
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledWriter')
|
writerClass='StyledWriter')
|
||||||
if status:
|
if status:
|
||||||
sys.exit(status)
|
sys.exit(status)
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
status = runAllTests(jsontest_executable_path, input_path,
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledStreamWriter')
|
writerClass='StyledStreamWriter')
|
||||||
sys.exit(status)
|
if status:
|
||||||
|
sys.exit(status)
|
||||||
|
status = runAllTests(jsontest_executable_path, input_path,
|
||||||
|
use_valgrind=options.valgrind,
|
||||||
|
with_json_checker=options.with_json_checker,
|
||||||
|
writerClass='BuiltStyledStreamWriter')
|
||||||
|
if status:
|
||||||
|
sys.exit(status)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user