mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-04-02 01:41:02 +02:00
Merge pull request #163 from cdunn2001/master
Reimplement the new Builders. Issue #131.
This commit is contained in:
commit
04a607d95b
@ -53,23 +53,26 @@ preserved.
|
||||
Json::Value root; // 'root' will contain the root value after parsing.
|
||||
std::cin >> root;
|
||||
|
||||
// You can also read into a particular sub-value.
|
||||
std::cin >> root["subtree"];
|
||||
|
||||
// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
|
||||
// such member.
|
||||
std::string encoding = root.get("encoding", "UTF-8" ).asString();
|
||||
// Get the value of the member of root named 'encoding', return a 'null' value if
|
||||
// Get the value of the member of root named 'encoding'; return a 'null' value if
|
||||
// there is no such member.
|
||||
const Json::Value plugins = root["plug-ins"];
|
||||
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
|
||||
loadPlugIn( plugins[index].asString() );
|
||||
|
||||
setIndentLength( root["indent"].get("length", 3).asInt() );
|
||||
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
||||
foo::setIndentLength( root["indent"].get("length", 3).asInt() );
|
||||
foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
|
||||
|
||||
// Since Json::Value has implicit constructor for all value types, it is not
|
||||
// necessary to explicitly construct the Json::Value object:
|
||||
root["encoding"] = getCurrentEncoding();
|
||||
root["indent"]["length"] = getCurrentIndentLength();
|
||||
root["indent"]["use_space"] = getCurrentIndentUseSpace();
|
||||
root["encoding"] = foo::getCurrentEncoding();
|
||||
root["indent"]["length"] = foo::getCurrentIndentLength();
|
||||
root["indent"]["use_space"] = foo::getCurrentIndentUseSpace();
|
||||
|
||||
// If you like the defaults, you can insert directly into a stream.
|
||||
std::cout << root;
|
||||
@ -80,27 +83,40 @@ std::cout << std::endl;
|
||||
\endcode
|
||||
|
||||
\section _advanced Advanced usage
|
||||
We are finalizing the new *Builder* API, which will be in versions
|
||||
`1.4.0` and `0.8.0` when released. Until then, you may continue to
|
||||
use the old API, include `Writer`, `Reader`, and `Feature`.
|
||||
|
||||
Configure *builders* to create *readers* and *writers*. For
|
||||
configuration, we use our own `Json::Value` (rather than
|
||||
standard setters/getters) so that we can add
|
||||
features without losing binary-compatibility.
|
||||
|
||||
\code
|
||||
|
||||
// EXPERIMENTAL
|
||||
// Or use `writeString()` for convenience, with a specialized builder.
|
||||
// For convenience, use `writeString()` with a specialized builder.
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
builder.indentation_ = "\t";
|
||||
std::string document = Json::writeString(root, wbuilder);
|
||||
wbuilder.settings_["indentation"] = "\t"; // simple Json::Value
|
||||
std::string document = Json::writeString(wbuilder, root);
|
||||
|
||||
// You can also read into a particular sub-value.
|
||||
std::cin >> root["subtree"];
|
||||
|
||||
// EXPERIMENTAL
|
||||
// Here we use a specialized Builder, discard comments, and
|
||||
// record errors.
|
||||
// Here, using a specialized Builder, we discard comments and
|
||||
// record errors as we parse.
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
rbuilder.collectComments_ = false;
|
||||
rbuilder.settings_["collectComments"] = false; // simple Json::Value
|
||||
std::string errs;
|
||||
Json::parseFromStream(rbuilder, std::cin, &root["subtree"], &errs);
|
||||
bool ok = Json::parseFromStream(rbuilder, std::cin, &root, &errs);
|
||||
\endcode
|
||||
|
||||
Yes, compile-time configuration-checking would be helpful,
|
||||
but `Json::Value` lets you
|
||||
write and read the builder configuration, which is better! In other words,
|
||||
you can configure your JSON parser using JSON.
|
||||
|
||||
CharReaders and StreamWriters are not thread-safe, but they are re-usable.
|
||||
\code
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
cfg >> rbuilder.settings_;
|
||||
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
|
||||
reader->parse(start, stop, &value1, &errs);
|
||||
// ...
|
||||
reader->parse(start, stop, &value2, &errs);
|
||||
// etc.
|
||||
\endcode
|
||||
|
||||
\section _pbuild Build instructions
|
||||
@ -137,5 +153,7 @@ and recognized in your jurisdiction.
|
||||
|
||||
\author Baptiste Lepilleur <blep@users.sourceforge.net> (originator)
|
||||
\version \include version
|
||||
We make strong guarantees about binary-compatibility, consistent with
|
||||
<a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>.
|
||||
\sa version.h
|
||||
*/
|
||||
|
@ -270,7 +270,9 @@ public:
|
||||
|
||||
class Factory {
|
||||
public:
|
||||
/// \brief Allocate a CharReader via operator new().
|
||||
/** \brief Allocate a CharReader via operator new().
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
virtual CharReader* newCharReader() const = 0;
|
||||
}; // Factory
|
||||
}; // CharReader
|
||||
@ -283,29 +285,53 @@ Usage:
|
||||
\code
|
||||
using namespace Json;
|
||||
CharReaderBuilder builder;
|
||||
builder.collectComments_ = false;
|
||||
builder.settings_["collectComments"] = false;
|
||||
Value value;
|
||||
std::string errs;
|
||||
bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||
\endcode
|
||||
*/
|
||||
class CharReaderBuilder : public CharReader::Factory {
|
||||
class JSON_API CharReaderBuilder : public CharReader::Factory {
|
||||
public:
|
||||
/** default: true
|
||||
*
|
||||
* It is possible to "allow" comments but still not "collect" them.
|
||||
*/
|
||||
bool collectComments_;
|
||||
/** default: all()
|
||||
*
|
||||
* For historical reasons, Features is a separate structure.
|
||||
*/
|
||||
Features features_;
|
||||
// Note: We use a Json::Value so that we can add data-members to this class
|
||||
// without a major version bump.
|
||||
/** Configuration of this builder.
|
||||
These are case-sensitive.
|
||||
Available settings (case-sensitive):
|
||||
- "collectComments": false or true
|
||||
- "allowComments"
|
||||
- "strictRoot"
|
||||
- "allowDroppedNullPlaceholders"
|
||||
- "allowNumericKeys"
|
||||
|
||||
You can examine 'settings_` yourself
|
||||
to see the defaults. You can also write and read them just like any
|
||||
JSON Value.
|
||||
\sa setDefaults()
|
||||
*/
|
||||
Json::Value settings_;
|
||||
|
||||
CharReaderBuilder();
|
||||
virtual ~CharReaderBuilder();
|
||||
|
||||
virtual CharReader* newCharReader() const;
|
||||
|
||||
/** \return true if 'settings' are legal and consistent;
|
||||
* otherwise, indicate bad settings via 'invalid'.
|
||||
*/
|
||||
bool validate(Json::Value* invalid) const;
|
||||
/** Called by ctor, but you can use this to reset settings_.
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||
*/
|
||||
static void setDefaults(Json::Value* settings);
|
||||
/** Same as old Features::strictMode().
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||
*/
|
||||
static void strictMode(Json::Value* settings);
|
||||
};
|
||||
|
||||
/** Consume entire stream and use its begin/end.
|
||||
|
@ -31,85 +31,93 @@ Usage:
|
||||
using namespace Json;
|
||||
void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
|
||||
std::unique_ptr<StreamWriter> const writer(
|
||||
factory.newStreamWriter(&std::cout));
|
||||
writer->write(value);
|
||||
factory.newStreamWriter());
|
||||
writer->write(value, &std::cout);
|
||||
std::cout << std::endl; // add lf and flush
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
class JSON_API StreamWriter {
|
||||
protected:
|
||||
std::ostream& sout_; // not owned; will not delete
|
||||
std::ostream* sout_; // not owned; will not delete
|
||||
public:
|
||||
/// Scoped enums are not available until C++11.
|
||||
struct CommentStyle {
|
||||
/// Decide whether to write comments.
|
||||
enum Enum {
|
||||
None, ///< Drop all comments.
|
||||
Most, ///< Recover odd behavior of previous versions (not implemented yet).
|
||||
All ///< Keep all comments.
|
||||
};
|
||||
};
|
||||
|
||||
/// Keep a reference, but do not take ownership of `sout`.
|
||||
StreamWriter(std::ostream* sout);
|
||||
StreamWriter();
|
||||
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;
|
||||
/** Write Value into document as configured in sub-class.
|
||||
Do not take ownership of sout, but maintain a reference during function.
|
||||
\pre sout != NULL
|
||||
\return zero on success
|
||||
\throw std::exception possibly, depending on configuration
|
||||
*/
|
||||
virtual int write(Value const& root, std::ostream* sout) = 0;
|
||||
|
||||
/** \brief A simple abstract factory.
|
||||
*/
|
||||
class JSON_API Factory {
|
||||
public:
|
||||
virtual ~Factory();
|
||||
/// Do not take ownership of sout, but maintain a reference.
|
||||
virtual StreamWriter* newStreamWriter(std::ostream* sout) const = 0;
|
||||
/** \brief Allocate a CharReader via operator new().
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
virtual StreamWriter* newStreamWriter() const = 0;
|
||||
}; // Factory
|
||||
}; // StreamWriter
|
||||
|
||||
/// \brief Write into stringstream, then return string, for convenience.
|
||||
std::string writeString(Value const& root, StreamWriter::Factory const& factory);
|
||||
/** \brief Write into stringstream, then return string, for convenience.
|
||||
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||
*/
|
||||
std::string writeString(StreamWriter::Factory const& factory, Value const& root);
|
||||
|
||||
|
||||
/** \brief Build a StreamWriter implementation.
|
||||
|
||||
\deprecated This is experimental and will be altered before the next release.
|
||||
|
||||
Usage:
|
||||
\code
|
||||
using namespace Json;
|
||||
Value value = ...;
|
||||
StreamWriterBuilder builder;
|
||||
builder.cs_ = StreamWriter::CommentStyle::None;
|
||||
builder.indentation_ = " "; // or whatever you like
|
||||
writer->write(value);
|
||||
builder.settings_["commentStyle"] = "None";
|
||||
builder.settings_["indentation"] = " "; // or whatever you like
|
||||
std::unique_ptr<Json::StreamWriter> writer(
|
||||
builder.newStreamWriter());
|
||||
writer->write(value, &std::cout);
|
||||
std::cout << std::endl; // add lf and flush
|
||||
\endcode
|
||||
*/
|
||||
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
|
||||
public:
|
||||
// Note: We cannot add data-members to this class without a major version bump.
|
||||
// So these might as well be completely exposed.
|
||||
// Note: We use a Json::Value so that we can add data-members to this class
|
||||
// without a major version bump.
|
||||
/** Configuration of this builder.
|
||||
Available settings (case-sensitive):
|
||||
- "commentStyle": "None", "Some", or "All"
|
||||
- "indentation": "<anything>"
|
||||
|
||||
/** \brief How to write comments.
|
||||
* Default: All
|
||||
*/
|
||||
StreamWriter::CommentStyle::Enum cs_;
|
||||
/** \brief Write in human-friendly style.
|
||||
|
||||
If "", then skip all indentation and newlines.
|
||||
In that case, you probably want CommentStyle::None also.
|
||||
Default: "\t"
|
||||
*/
|
||||
std::string indentation_;
|
||||
You can examine 'settings_` yourself
|
||||
to see the defaults. You can also write and read them just like any
|
||||
JSON Value.
|
||||
\sa setDefaults()
|
||||
*/
|
||||
Json::Value settings_;
|
||||
|
||||
StreamWriterBuilder();
|
||||
virtual ~StreamWriterBuilder();
|
||||
|
||||
/// Do not take ownership of sout, but maintain a reference.
|
||||
virtual StreamWriter* newStreamWriter(std::ostream* sout) const;
|
||||
/**
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
virtual StreamWriter* newStreamWriter() const;
|
||||
|
||||
/** \return true if 'settings' are legal and consistent;
|
||||
* otherwise, indicate bad settings via 'invalid'.
|
||||
*/
|
||||
bool validate(Json::Value* invalid) const;
|
||||
/** Called by ctor, but you can use this to reset settings_.
|
||||
* \pre 'settings' != NULL (but Json::null is fine)
|
||||
* \remark Defaults:
|
||||
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
|
||||
*/
|
||||
static void setDefaults(Json::Value* settings);
|
||||
};
|
||||
|
||||
/** \brief Build a StreamWriter implementation.
|
||||
@ -120,10 +128,12 @@ public:
|
||||
* \code
|
||||
* OldCompressingStreamWriterBuilder b;
|
||||
* b.dropNullPlaceHolders_ = true; // etc.
|
||||
* StreamWriter* w = b.newStreamWriter(&std::cout);
|
||||
* w->write(value);
|
||||
* StreamWriter* w = b.newStreamWriter();
|
||||
* w->write(value, &std::cout);
|
||||
* delete w;
|
||||
* \endcode
|
||||
*
|
||||
* \deprecated Use StreamWriterBuilder
|
||||
*/
|
||||
class JSON_API OldCompressingStreamWriterBuilder : public StreamWriter::Factory
|
||||
{
|
||||
@ -155,7 +165,7 @@ public:
|
||||
, omitEndingLineFeed_(false)
|
||||
, enableYAMLCompatibility_(false)
|
||||
{}
|
||||
virtual StreamWriter* newStreamWriter(std::ostream*) const;
|
||||
virtual StreamWriter* newStreamWriter() const;
|
||||
};
|
||||
|
||||
/** \brief Abstract class for writers.
|
||||
|
@ -185,7 +185,7 @@ static std::string useBuiltStyledStreamWriter(
|
||||
Json::Value const& root)
|
||||
{
|
||||
Json::StreamWriterBuilder builder;
|
||||
return writeString(root, builder);
|
||||
return Json::writeString(builder, root);
|
||||
}
|
||||
static int rewriteValueTree(
|
||||
const std::string& rewritePath,
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include <istream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
||||
#define snprintf _snprintf
|
||||
@ -912,14 +914,71 @@ public:
|
||||
};
|
||||
|
||||
CharReaderBuilder::CharReaderBuilder()
|
||||
: collectComments_(true)
|
||||
, features_(Features::all())
|
||||
{}
|
||||
{
|
||||
setDefaults(&settings_);
|
||||
}
|
||||
CharReaderBuilder::~CharReaderBuilder()
|
||||
{}
|
||||
CharReader* CharReaderBuilder::newCharReader() const
|
||||
{
|
||||
return new OldReader(collectComments_, features_);
|
||||
if (!validate(NULL)) throw std::runtime_error("invalid settings");
|
||||
// TODO: Maybe serialize the invalid settings into the exception.
|
||||
|
||||
bool collectComments = settings_["collectComments"].asBool();
|
||||
Features features = Features::all();
|
||||
features.allowComments_ = settings_["allowComments"].asBool();
|
||||
features.strictRoot_ = settings_["strictRoot"].asBool();
|
||||
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
|
||||
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
|
||||
return new OldReader(collectComments, features);
|
||||
}
|
||||
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
||||
{
|
||||
valid_keys->clear();
|
||||
valid_keys->insert("collectComments");
|
||||
valid_keys->insert("allowComments");
|
||||
valid_keys->insert("strictRoot");
|
||||
valid_keys->insert("allowDroppedNullPlaceholders");
|
||||
valid_keys->insert("allowNumericKeys");
|
||||
}
|
||||
bool CharReaderBuilder::validate(Json::Value* invalid) const
|
||||
{
|
||||
Json::Value my_invalid;
|
||||
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
||||
Json::Value& inv = *invalid;
|
||||
bool valid = true;
|
||||
std::set<std::string> valid_keys;
|
||||
getValidReaderKeys(&valid_keys);
|
||||
Value::Members keys = settings_.getMemberNames();
|
||||
size_t n = keys.size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
std::string const& key = keys[i];
|
||||
if (valid_keys.find(key) == valid_keys.end()) {
|
||||
inv[key] = settings_[key];
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
// static
|
||||
void CharReaderBuilder::strictMode(Json::Value* settings)
|
||||
{
|
||||
//! [CharReaderBuilderStrictMode]
|
||||
(*settings)["allowComments"] = false;
|
||||
(*settings)["strictRoot"] = true;
|
||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||
(*settings)["allowNumericKeys"] = false;
|
||||
//! [CharReaderBuilderStrictMode]
|
||||
}
|
||||
// static
|
||||
void CharReaderBuilder::setDefaults(Json::Value* settings)
|
||||
{
|
||||
//! [CharReaderBuilderDefaults]
|
||||
(*settings)["collectComments"] = true;
|
||||
(*settings)["allowComments"] = true;
|
||||
(*settings)["strictRoot"] = false;
|
||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||
(*settings)["allowNumericKeys"] = false;
|
||||
//! [CharReaderBuilderDefaults]
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
@ -674,16 +676,25 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
|
||||
//////////////////////////
|
||||
// BuiltStyledStreamWriter
|
||||
|
||||
/// Scoped enums are not available until C++11.
|
||||
struct CommentStyle {
|
||||
/// Decide whether to write comments.
|
||||
enum Enum {
|
||||
None, ///< Drop all comments.
|
||||
Most, ///< Recover odd behavior of previous versions (not implemented yet).
|
||||
All ///< Keep all comments.
|
||||
};
|
||||
};
|
||||
|
||||
struct BuiltStyledStreamWriter : public StreamWriter
|
||||
{
|
||||
BuiltStyledStreamWriter(
|
||||
std::ostream* sout,
|
||||
std::string const& indentation,
|
||||
StreamWriter::CommentStyle::Enum cs,
|
||||
CommentStyle::Enum cs,
|
||||
std::string const& colonSymbol,
|
||||
std::string const& nullSymbol,
|
||||
std::string const& endingLineFeedSymbol);
|
||||
virtual int write(Value const& root);
|
||||
virtual int write(Value const& root, std::ostream* sout);
|
||||
private:
|
||||
void writeValue(Value const& value);
|
||||
void writeArrayValue(Value const& value);
|
||||
@ -711,14 +722,12 @@ private:
|
||||
bool indented_ : 1;
|
||||
};
|
||||
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
||||
std::ostream* sout,
|
||||
std::string const& indentation,
|
||||
StreamWriter::CommentStyle::Enum cs,
|
||||
CommentStyle::Enum cs,
|
||||
std::string const& colonSymbol,
|
||||
std::string const& nullSymbol,
|
||||
std::string const& endingLineFeedSymbol)
|
||||
: StreamWriter(sout)
|
||||
, rightMargin_(74)
|
||||
: rightMargin_(74)
|
||||
, indentation_(indentation)
|
||||
, cs_(cs)
|
||||
, colonSymbol_(colonSymbol)
|
||||
@ -728,8 +737,9 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
||||
, indented_(false)
|
||||
{
|
||||
}
|
||||
int BuiltStyledStreamWriter::write(Value const& root)
|
||||
int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
|
||||
{
|
||||
sout_ = sout;
|
||||
addChildValues_ = false;
|
||||
indented_ = true;
|
||||
indentString_ = "";
|
||||
@ -738,7 +748,8 @@ int BuiltStyledStreamWriter::write(Value const& root)
|
||||
indented_ = true;
|
||||
writeValue(root);
|
||||
writeCommentAfterValueOnSameLine(root);
|
||||
sout_ << endingLineFeedSymbol_;
|
||||
*sout_ << endingLineFeedSymbol_;
|
||||
sout_ = NULL;
|
||||
return 0;
|
||||
}
|
||||
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
@ -777,13 +788,13 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
Value const& childValue = value[name];
|
||||
writeCommentBeforeValue(childValue);
|
||||
writeWithIndent(valueToQuotedString(name.c_str()));
|
||||
sout_ << colonSymbol_;
|
||||
*sout_ << colonSymbol_;
|
||||
writeValue(childValue);
|
||||
if (++it == members.end()) {
|
||||
writeCommentAfterValueOnSameLine(childValue);
|
||||
break;
|
||||
}
|
||||
sout_ << ",";
|
||||
*sout_ << ",";
|
||||
writeCommentAfterValueOnSameLine(childValue);
|
||||
}
|
||||
unindent();
|
||||
@ -819,7 +830,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
|
||||
writeCommentAfterValueOnSameLine(childValue);
|
||||
break;
|
||||
}
|
||||
sout_ << ",";
|
||||
*sout_ << ",";
|
||||
writeCommentAfterValueOnSameLine(childValue);
|
||||
}
|
||||
unindent();
|
||||
@ -827,15 +838,15 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
|
||||
} else // output on a single line
|
||||
{
|
||||
assert(childValues_.size() == size);
|
||||
sout_ << "[";
|
||||
if (!indentation_.empty()) sout_ << " ";
|
||||
*sout_ << "[";
|
||||
if (!indentation_.empty()) *sout_ << " ";
|
||||
for (unsigned index = 0; index < size; ++index) {
|
||||
if (index > 0)
|
||||
sout_ << ", ";
|
||||
sout_ << childValues_[index];
|
||||
*sout_ << ", ";
|
||||
*sout_ << childValues_[index];
|
||||
}
|
||||
if (!indentation_.empty()) sout_ << " ";
|
||||
sout_ << "]";
|
||||
if (!indentation_.empty()) *sout_ << " ";
|
||||
*sout_ << "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -872,7 +883,7 @@ void BuiltStyledStreamWriter::pushValue(std::string const& value) {
|
||||
if (addChildValues_)
|
||||
childValues_.push_back(value);
|
||||
else
|
||||
sout_ << value;
|
||||
*sout_ << value;
|
||||
}
|
||||
|
||||
void BuiltStyledStreamWriter::writeIndent() {
|
||||
@ -883,13 +894,13 @@ void BuiltStyledStreamWriter::writeIndent() {
|
||||
|
||||
if (!indentation_.empty()) {
|
||||
// In this case, drop newlines too.
|
||||
sout_ << '\n' << indentString_;
|
||||
*sout_ << '\n' << indentString_;
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
|
||||
if (!indented_) writeIndent();
|
||||
sout_ << value;
|
||||
*sout_ << value;
|
||||
indented_ = false;
|
||||
}
|
||||
|
||||
@ -909,11 +920,11 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
|
||||
const std::string& comment = root.getComment(commentBefore);
|
||||
std::string::const_iterator iter = comment.begin();
|
||||
while (iter != comment.end()) {
|
||||
sout_ << *iter;
|
||||
*sout_ << *iter;
|
||||
if (*iter == '\n' &&
|
||||
(iter != comment.end() && *(iter + 1) == '/'))
|
||||
// writeIndent(); // would write extra newline
|
||||
sout_ << indentString_;
|
||||
*sout_ << indentString_;
|
||||
++iter;
|
||||
}
|
||||
indented_ = false;
|
||||
@ -922,11 +933,11 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
|
||||
void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
|
||||
if (cs_ == CommentStyle::None) return;
|
||||
if (root.hasComment(commentAfterOnSameLine))
|
||||
sout_ << " " + root.getComment(commentAfterOnSameLine);
|
||||
*sout_ << " " + root.getComment(commentAfterOnSameLine);
|
||||
|
||||
if (root.hasComment(commentAfter)) {
|
||||
writeIndent();
|
||||
sout_ << root.getComment(commentAfter);
|
||||
*sout_ << root.getComment(commentAfter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,8 +951,8 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
|
||||
///////////////
|
||||
// StreamWriter
|
||||
|
||||
StreamWriter::StreamWriter(std::ostream* sout)
|
||||
: sout_(*sout)
|
||||
StreamWriter::StreamWriter()
|
||||
: sout_(NULL)
|
||||
{
|
||||
}
|
||||
StreamWriter::~StreamWriter()
|
||||
@ -950,41 +961,70 @@ StreamWriter::~StreamWriter()
|
||||
StreamWriter::Factory::~Factory()
|
||||
{}
|
||||
StreamWriterBuilder::StreamWriterBuilder()
|
||||
: cs_(StreamWriter::CommentStyle::All)
|
||||
, indentation_("\t")
|
||||
{}
|
||||
{
|
||||
setDefaults(&settings_);
|
||||
}
|
||||
StreamWriterBuilder::~StreamWriterBuilder()
|
||||
{}
|
||||
StreamWriter* StreamWriterBuilder::newStreamWriter(std::ostream* stream) const
|
||||
StreamWriter* StreamWriterBuilder::newStreamWriter() const
|
||||
{
|
||||
if (!validate(NULL)) throw std::runtime_error("invalid settings");
|
||||
// TODO: Maybe serialize the invalid settings into the exception.
|
||||
|
||||
std::string indentation = settings_["indentation"].asString();
|
||||
std::string cs_str = settings_["commentStyle"].asString();
|
||||
CommentStyle::Enum cs = CommentStyle::All;
|
||||
if (cs_str == "All") {
|
||||
cs = CommentStyle::All;
|
||||
} else if (cs_str == "None") {
|
||||
cs = CommentStyle::None;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
std::string colonSymbol = " : ";
|
||||
if (indentation_.empty()) {
|
||||
if (indentation.empty()) {
|
||||
colonSymbol = ":";
|
||||
}
|
||||
std::string nullSymbol = "null";
|
||||
std::string endingLineFeedSymbol = "";
|
||||
return new BuiltStyledStreamWriter(stream,
|
||||
indentation_, cs_,
|
||||
return new BuiltStyledStreamWriter(
|
||||
indentation, cs,
|
||||
colonSymbol, nullSymbol, endingLineFeedSymbol);
|
||||
}
|
||||
/*
|
||||
// This might become public someday.
|
||||
class StreamWriterBuilderFactory {
|
||||
public:
|
||||
virtual ~StreamWriterBuilderFactory();
|
||||
virtual StreamWriterBuilder* newStreamWriterBuilder() const;
|
||||
};
|
||||
StreamWriterBuilderFactory::~StreamWriterBuilderFactory()
|
||||
static void getValidWriterKeys(std::set<std::string>* valid_keys)
|
||||
{
|
||||
valid_keys->clear();
|
||||
valid_keys->insert("indentation");
|
||||
valid_keys->insert("commentStyle");
|
||||
}
|
||||
StreamWriterBuilder* StreamWriterBuilderFactory::newStreamWriterBuilder() const
|
||||
bool StreamWriterBuilder::validate(Json::Value* invalid) const
|
||||
{
|
||||
return new StreamWriterBuilder;
|
||||
Json::Value my_invalid;
|
||||
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
||||
Json::Value& inv = *invalid;
|
||||
bool valid = true;
|
||||
std::set<std::string> valid_keys;
|
||||
getValidWriterKeys(&valid_keys);
|
||||
Value::Members keys = settings_.getMemberNames();
|
||||
size_t n = keys.size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
std::string const& key = keys[i];
|
||||
if (valid_keys.find(key) == valid_keys.end()) {
|
||||
inv[key] = settings_[key];
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
// static
|
||||
void StreamWriterBuilder::setDefaults(Json::Value* settings)
|
||||
{
|
||||
//! [StreamWriterBuilderDefaults]
|
||||
(*settings)["commentStyle"] = "All";
|
||||
(*settings)["indentation"] = "\t";
|
||||
//! [StreamWriterBuilderDefaults]
|
||||
}
|
||||
*/
|
||||
|
||||
StreamWriter* OldCompressingStreamWriterBuilder::newStreamWriter(
|
||||
std::ostream* stream) const
|
||||
StreamWriter* OldCompressingStreamWriterBuilder::newStreamWriter() const
|
||||
{
|
||||
std::string colonSymbol = " : ";
|
||||
if (enableYAMLCompatibility_) {
|
||||
@ -1000,22 +1040,22 @@ StreamWriter* OldCompressingStreamWriterBuilder::newStreamWriter(
|
||||
if (omitEndingLineFeed_) {
|
||||
endingLineFeedSymbol = "";
|
||||
}
|
||||
return new BuiltStyledStreamWriter(stream,
|
||||
"", StreamWriter::CommentStyle::None,
|
||||
return new BuiltStyledStreamWriter(
|
||||
"", CommentStyle::None,
|
||||
colonSymbol, nullSymbol, endingLineFeedSymbol);
|
||||
}
|
||||
|
||||
std::string writeString(Value const& root, StreamWriter::Factory const& builder) {
|
||||
std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
|
||||
std::ostringstream sout;
|
||||
StreamWriterPtr const sw(builder.newStreamWriter(&sout));
|
||||
sw->write(root);
|
||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||
writer->write(root, &sout);
|
||||
return sout.str();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& sout, Value const& root) {
|
||||
StreamWriterBuilder builder;
|
||||
StreamWriterPtr const writer(builder.newStreamWriter(&sout));
|
||||
writer->write(root);
|
||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||
writer->write(root, &sout);
|
||||
return sout;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user