Skip to content

Commit 3b5f2b8

Browse files
committed
Merge pull request open-source-parsers#145 from cdunn2001/simplify-builder
Simplify builder
2 parents 9da9f84 + 7eca3b4 commit 3b5f2b8

File tree

4 files changed

+131
-155
lines changed

4 files changed

+131
-155
lines changed

doc/jsoncpp.dox

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ root["indent"]["use_space"] = getCurrentIndentUseSpace();
8181

8282
// To write into a steam with minimal memory overhead,
8383
// create a Builder for a StreamWriter.
84-
Json::StreamWriter::Builder builder;
85-
builder.withIndentation(" "); // or whatever you like
84+
Json::StreamWriterBuilder builder;
85+
builder.indentation_ = " "; // or whatever you like
8686

8787
// Then build a StreamWriter.
8888
std::shared_ptr<Json::StreamWriter> writer(
@@ -94,6 +94,9 @@ writer->write( root );
9494
// If you like the defaults, you can insert directly into a stream.
9595
std::cout << root;
9696

97+
// If desired, remember to add a linefeed and flush.
98+
std::cout << std::endl;
99+
97100
// Of course, you can write to `std::ostringstream` if you prefer. Or
98101
// use `writeString()` for convenience.
99102
std::string document = Json::writeString( root, builder );

include/json/writer.h

Lines changed: 96 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#endif // if !defined(JSON_IS_AMALGAMATION)
1212
#include <vector>
1313
#include <string>
14+
#include <ostream>
1415

1516
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
1617
// be used by...
@@ -22,20 +23,18 @@
2223
namespace Json {
2324

2425
class Value;
25-
class StreamWriterBuilder;
2626

2727
/**
2828
2929
Usage:
3030
\code
3131
using namespace Json;
32-
Value value;
33-
StreamWriter::Builder builder;
34-
builder.withCommentStyle(StreamWriter::CommentStyle::None);
35-
std::shared_ptr<StreamWriter> writer(
36-
builder.newStreamWriter(&std::cout));
37-
writer->write(value);
38-
std::cout.flush();
32+
void writeToStdout(StreamWriter::Builder const& builder, Value const& value) {
33+
std::unique_ptr<StreamWriter> const writer(
34+
builder.newStreamWriter(&std::cout));
35+
writer->write(value);
36+
std::cout << std::endl; // add lf and flush
37+
}
3938
\endcode
4039
*/
4140
class JSON_API StreamWriter {
@@ -57,52 +56,102 @@ class JSON_API StreamWriter {
5756
/// \throw std::exception possibly, depending on configuration
5857
virtual int write(Value const& root) = 0;
5958

60-
/// Because this Builder is non-virtual, we can safely add
61-
/// methods without a major version bump.
62-
/// \see http://stackoverflow.com/questions/14875052/pure-virtual-functions-and-binary-compatibility
63-
class Builder {
64-
StreamWriterBuilder* own_;
65-
Builder(Builder const&); // noncopyable
66-
void operator=(Builder const&); // noncopyable
59+
/** \brief A simple abstract factory.
60+
*/
61+
class JSON_API Factory {
6762
public:
68-
Builder();
69-
~Builder(); // delete underlying StreamWriterBuilder
63+
virtual ~Factory();
64+
/// Do not take ownership of sout, but maintain a reference.
65+
virtual StreamWriter* newStreamWriter(std::ostream* sout) const = 0;
66+
}; // Factory
67+
}; // StreamWriter
7068

71-
Builder& withCommentStyle(CommentStyle cs); /// default: All
72-
/** \brief Write in human-friendly style.
69+
/// \brief Write into stringstream, then return string, for convenience.
70+
std::string writeString(Value const& root, StreamWriter::Factory const& factory);
7371

74-
If "", then skip all indentation, newlines, and comments,
75-
which implies CommentStyle::None.
76-
Default: "\t"
77-
*/
78-
Builder& withIndentation(std::string indentation);
79-
/** \brief Drop the "null" string from the writer's output for nullValues.
80-
* Strictly speaking, this is not valid JSON. But when the output is being
81-
* fed to a browser's Javascript, it makes for smaller output and the
82-
* browser can handle the output just fine.
83-
*/
84-
Builder& withDropNullPlaceholders(bool v);
85-
/** \brief Do not add \n at end of document.
86-
* Normally, we add an extra newline, just because.
87-
*/
88-
Builder& withOmitEndingLineFeed(bool v);
89-
/** \brief Add a space after ':'.
90-
* If indentation is non-empty, we surround colon with whitespace,
91-
* e.g. " : "
92-
* This will add back the trailing space when there is no indentation.
93-
* This seems dubious when the entire document is on a single line,
94-
* but we leave this here to repduce the behavior of the old `FastWriter`.
95-
*/
96-
Builder& withEnableYAMLCompatibility(bool v);
9772

98-
/// Do not take ownership of sout, but maintain a reference.
99-
StreamWriter* newStreamWriter(std::ostream* sout) const;
100-
};
73+
/** \brief Build a StreamWriter implementation.
74+
75+
Usage:
76+
\code
77+
using namespace Json;
78+
Value value = ...;
79+
StreamWriter::Builder builder;
80+
builder.cs_ = StreamWriter::CommentStyle::None;
81+
std::shared_ptr<StreamWriter> writer(
82+
builder.newStreamWriter(&std::cout));
83+
writer->write(value);
84+
std::cout << std::endl; // add lf and flush
85+
\endcode
86+
*/
87+
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
88+
public:
89+
// Note: We cannot add data-members to this class without a major version bump.
90+
// So these might as well be completely exposed.
91+
92+
/** \brief How to write comments.
93+
* Default: All
94+
*/
95+
StreamWriter::CommentStyle cs_;
96+
/** \brief Write in human-friendly style.
97+
98+
If "", then skip all indentation and newlines.
99+
In that case, you probably want CommentStyle::None also.
100+
Default: "\t"
101+
*/
102+
std::string indentation_;
103+
104+
StreamWriterBuilder();
105+
106+
/// Do not take ownership of sout, but maintain a reference.
107+
StreamWriter* newStreamWriter(std::ostream* sout) const;
101108
};
102109

103-
/// \brief Write into stringstream, then return string, for convenience.
104-
std::string writeString(Value const& root, StreamWriter::Builder const& builder);
110+
/** \brief Build a StreamWriter implementation.
111+
* Comments are not written, and most whitespace is omitted.
112+
* In addition, there are some special settings to allow compatibility
113+
* with the old FastWriter.
114+
* Usage:
115+
* \code
116+
* OldCompressingStreamWriterBuilder b;
117+
* b.dropNullPlaceHolders_ = true; // etc.
118+
* StreamWriter* w = b.newStreamWriter(&std::cout);
119+
* w.write(value);
120+
* delete w;
121+
* \endcode
122+
*/
123+
class JSON_API OldCompressingStreamWriterBuilder : public StreamWriter::Factory
124+
{
125+
public:
126+
// Note: We cannot add data-members to this class without a major version bump.
127+
// So these might as well be completely exposed.
105128

129+
/** \brief Drop the "null" string from the writer's output for nullValues.
130+
* Strictly speaking, this is not valid JSON. But when the output is being
131+
* fed to a browser's Javascript, it makes for smaller output and the
132+
* browser can handle the output just fine.
133+
*/
134+
bool dropNullPlaceholders_;
135+
/** \brief Do not add \n at end of document.
136+
* Normally, we add an extra newline, just because.
137+
*/
138+
bool omitEndingLineFeed_;
139+
/** \brief Add a space after ':'.
140+
* If indentation is non-empty, we surround colon with whitespace,
141+
* e.g. " : "
142+
* This will add back the trailing space when there is no indentation.
143+
* This seems dubious when the entire document is on a single line,
144+
* but we leave this here to repduce the behavior of the old `FastWriter`.
145+
*/
146+
bool enableYAMLCompatibility_;
147+
148+
OldCompressingStreamWriterBuilder()
149+
: dropNullPlaceholders_(false)
150+
, omitEndingLineFeed_(false)
151+
, enableYAMLCompatibility_(false)
152+
{}
153+
virtual StreamWriter* newStreamWriter(std::ostream*) const;
154+
};
106155

107156
/** \brief Abstract class for writers.
108157
* \deprecated Use StreamWriter::Builder.

src/jsontestrunner/main.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ static std::string useStyledStreamWriter(
184184
static std::string useBuiltStyledStreamWriter(
185185
Json::Value const& root)
186186
{
187-
Json::StreamWriter::Builder builder;
188-
builder.withCommentStyle(Json::StreamWriter::CommentStyle::All);
187+
Json::StreamWriterBuilder builder;
189188
return writeString(root, builder);
190189
}
191190
static int rewriteValueTree(

src/lib_json/json_writer.cpp

Lines changed: 29 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -959,78 +959,25 @@ int MyStreamWriter::write(Value const& root)
959959
sout_ << root;
960960
return 0;
961961
}
962-
class StreamWriterBuilder {
963-
typedef StreamWriter::CommentStyle CommentStyle;
964-
CommentStyle cs_;
965-
std::string indentation_;
966-
bool dropNullPlaceholders_;
967-
bool omitEndingLineFeed_;
968-
bool enableYAMLCompatibility_;
969-
public:
970-
StreamWriterBuilder();
971-
virtual ~StreamWriterBuilder();
972-
virtual void setCommentStyle(CommentStyle cs);
973-
virtual void setIndentation(std::string indentation);
974-
virtual void setDropNullPlaceholders(bool v);
975-
virtual void setOmitEndingLineFeed(bool v);
976-
virtual void setEnableYAMLCompatibility(bool v);
977-
virtual StreamWriter* newStreamWriter(std::ostream* sout) const;
978-
};
962+
StreamWriter::Factory::~Factory()
963+
{}
979964
StreamWriterBuilder::StreamWriterBuilder()
980-
: cs_(CommentStyle::All)
965+
: cs_(StreamWriter::CommentStyle::All)
981966
, indentation_("\t")
982-
, dropNullPlaceholders_(false)
983-
, omitEndingLineFeed_(false)
984-
, enableYAMLCompatibility_(false)
985-
{
986-
}
987-
StreamWriterBuilder::~StreamWriterBuilder()
988-
{
989-
}
990-
void StreamWriterBuilder::setCommentStyle(CommentStyle v)
991-
{
992-
cs_ = v;
993-
}
994-
void StreamWriterBuilder::setIndentation(std::string v)
995-
{
996-
indentation_ = v;
997-
if (indentation_.empty()) cs_ = CommentStyle::None;
998-
}
999-
void StreamWriterBuilder::setDropNullPlaceholders(bool v)
1000-
{
1001-
dropNullPlaceholders_ = v;
1002-
}
1003-
void StreamWriterBuilder::setOmitEndingLineFeed(bool v)
1004-
{
1005-
omitEndingLineFeed_ = v;
1006-
}
1007-
void StreamWriterBuilder::setEnableYAMLCompatibility(bool v)
1008-
{
1009-
enableYAMLCompatibility_ = v;
1010-
}
967+
{}
1011968
StreamWriter* StreamWriterBuilder::newStreamWriter(std::ostream* stream) const
1012969
{
1013970
std::string colonSymbol = " : ";
1014971
if (indentation_.empty()) {
1015-
if (enableYAMLCompatibility_) {
1016-
colonSymbol = ": ";
1017-
} else {
1018-
colonSymbol = ":";
1019-
}
972+
colonSymbol = ":";
1020973
}
1021974
std::string nullSymbol = "null";
1022-
if (dropNullPlaceholders_) {
1023-
nullSymbol = "";
1024-
}
1025-
std::string endingLineFeedSymbol = "\n";
1026-
if (omitEndingLineFeed_) {
1027-
endingLineFeedSymbol = "";
1028-
}
975+
std::string endingLineFeedSymbol = "";
1029976
return new BuiltStyledStreamWriter(stream,
1030977
indentation_, cs_,
1031978
colonSymbol, nullSymbol, endingLineFeedSymbol);
1032979
}
1033-
980+
/*
1034981
// This might become public someday.
1035982
class StreamWriterBuilderFactory {
1036983
public:
@@ -1044,61 +991,39 @@ StreamWriterBuilder* StreamWriterBuilderFactory::newStreamWriterBuilder() const
1044991
{
1045992
return new StreamWriterBuilder;
1046993
}
994+
*/
1047995

1048-
StreamWriter::Builder::Builder()
1049-
: own_(StreamWriterBuilderFactory().newStreamWriterBuilder())
996+
StreamWriter* OldCompressingStreamWriterBuilder::newStreamWriter(
997+
std::ostream* stream) const
1050998
{
1051-
}
1052-
StreamWriter::Builder::~Builder()
1053-
{
1054-
delete own_;
1055-
}
1056-
StreamWriter::Builder::Builder(Builder const&)
1057-
: own_(nullptr)
1058-
{abort();}
1059-
void StreamWriter::Builder::operator=(Builder const&)
1060-
{abort();}
1061-
StreamWriter::Builder& StreamWriter::Builder::withCommentStyle(CommentStyle v)
1062-
{
1063-
own_->setCommentStyle(v);
1064-
return *this;
1065-
}
1066-
StreamWriter::Builder& StreamWriter::Builder::withIndentation(std::string v)
1067-
{
1068-
own_->setIndentation(v);
1069-
return *this;
1070-
}
1071-
StreamWriter::Builder& StreamWriter::Builder::withDropNullPlaceholders(bool v)
1072-
{
1073-
own_->setDropNullPlaceholders(v);
1074-
return *this;
1075-
}
1076-
StreamWriter::Builder& StreamWriter::Builder::withOmitEndingLineFeed(bool v)
1077-
{
1078-
own_->setOmitEndingLineFeed(v);
1079-
return *this;
1080-
}
1081-
StreamWriter::Builder& StreamWriter::Builder::withEnableYAMLCompatibility(bool v)
1082-
{
1083-
own_->setEnableYAMLCompatibility(v);
1084-
return *this;
1085-
}
1086-
StreamWriter* StreamWriter::Builder::newStreamWriter(std::ostream* sout) const
1087-
{
1088-
return own_->newStreamWriter(sout);
999+
std::string colonSymbol = " : ";
1000+
if (enableYAMLCompatibility_) {
1001+
colonSymbol = ": ";
1002+
} else {
1003+
colonSymbol = ":";
1004+
}
1005+
std::string nullSymbol = "null";
1006+
if (dropNullPlaceholders_) {
1007+
nullSymbol = "";
1008+
}
1009+
std::string endingLineFeedSymbol = "\n";
1010+
if (omitEndingLineFeed_) {
1011+
endingLineFeedSymbol = "";
1012+
}
1013+
return new BuiltStyledStreamWriter(stream,
1014+
"", StreamWriter::CommentStyle::None,
1015+
colonSymbol, nullSymbol, endingLineFeedSymbol);
10891016
}
10901017

1091-
std::string writeString(Value const& root, StreamWriter::Builder const& builder) {
1018+
std::string writeString(Value const& root, StreamWriter::Factory const& builder) {
10921019
std::ostringstream sout;
10931020
std::unique_ptr<StreamWriter> const sw(builder.newStreamWriter(&sout));
10941021
sw->write(root);
10951022
return sout.str();
10961023
}
10971024

10981025
std::ostream& operator<<(std::ostream& sout, Value const& root) {
1099-
StreamWriter::Builder builder;
1100-
builder.withCommentStyle(StreamWriter::CommentStyle::All);
1101-
builder.withIndentation("\t");
1026+
StreamWriterBuilder builder;
11021027
std::shared_ptr<StreamWriter> writer(builder.newStreamWriter(&sout));
11031028
writer->write(root);
11041029
return sout;

0 commit comments

Comments
 (0)