GH #119: JSON::Object holds values in ordered map

- fixed GH #119: JSON::Object holds values in ordered map
- added PrintHandler
- renamed DefaultHandler to ParseHandler
- redefined DefaultHandler as typedef to ParseHandler
This commit is contained in:
aleks-f
2013-03-16 11:33:27 -05:00
parent fe6715890c
commit 42ff341cb9
34 changed files with 1249 additions and 328 deletions

View File

@@ -137,9 +137,9 @@ public:
void add(const Dynamic::Var& value);
/// Add the given value to the array
void stringify(std::ostream& out, unsigned int indent) const;
/// Prints the array to out. When indent is 0, the array
/// will be printed on one line without indentation.
void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const;
/// Prints the array to out. When indent has zero value,
/// the array will be printed without newline breaks and spaces between elements.
void remove(unsigned int index);
/// Removes the element on the given index.

View File

@@ -40,137 +40,15 @@
#define JSON_DefaultHandler_INCLUDED
#include "Poco/JSON/Handler.h"
#include <stack>
#include "Poco/JSON/ParseHandler.h"
namespace Poco {
namespace JSON {
class JSON_API DefaultHandler : public Handler
/// Provides a default handler for the JSON parser.
/// This handler will build up an object or array based
/// on the handlers called by the parser.
{
public:
DefaultHandler();
/// Default Constructor
virtual ~DefaultHandler();
/// Destructor
void startObject();
/// Handles a {, meaning a new object will be read
void endObject();
/// Handles a }, meaning the object is read
void startArray();
/// Handles a [, meaning a new array will be read
void endArray();
/// Handles a ], meaning the array is read
void key(const std::string& k);
/// A key is read
Dynamic::Var result() const;
/// Returns the result of the parser. Which is an object or an array.
virtual void value(int v);
/// An integer value is read
virtual void value(unsigned v);
/// An unsigned value is read. This will only be triggered if the
/// value cannot fit into a signed int.
#if defined(POCO_HAVE_INT64)
virtual void value(Int64 v);
/// A 64-bit integer value is read
virtual void value(UInt64 v);
/// An unsigned 64-bit integer value is read. This will only be
/// triggered if the value cannot fit into a signed 64-bit integer.
#endif
virtual void value(const std::string& s);
/// A string value is read.
virtual void value(double d);
/// A double value is read
virtual void value(bool b);
/// A boolean value is read
virtual void null();
/// A null value is read
private:
void setValue(const Poco::Dynamic::Var& value);
std::stack<Dynamic::Var> _stack;
std::string _key;
Dynamic::Var _result;
};
inline Dynamic::Var DefaultHandler::result() const
{
return _result;
}
inline void DefaultHandler::value(int v)
{
setValue(v);
}
inline void DefaultHandler::value(unsigned v)
{
setValue(v);
}
#if defined(POCO_HAVE_INT64)
inline void DefaultHandler::value(Int64 v)
{
setValue(v);
}
inline void DefaultHandler::value(UInt64 v)
{
setValue(v);
}
#endif
inline void DefaultHandler::value(const std::string& s)
{
setValue(s);
}
inline void DefaultHandler::value(double d)
{
setValue(d);
}
inline void DefaultHandler::value(bool b)
{
setValue(b);
}
inline void DefaultHandler::null()
{
Poco::Dynamic::Var empty;
setValue(empty);
}
//@deprecated
typedef ParseHandler DefaultHandler;
}} // namespace Poco::JSON

View File

@@ -51,6 +51,9 @@ namespace JSON {
class JSON_API Handler
{
public:
Handler();
/// Constructor;
virtual void startObject() = 0;
/// The parser has read a {, meaning a new object will be read
@@ -74,7 +77,7 @@ public:
virtual void value(unsigned v) = 0;
/// An unsigned value is read. This will only be triggered if the
/// value cannot fit into a signed int.
/// value cannot fit into a signed int.
#if defined(POCO_HAVE_INT64)
virtual void value(Int64 v) = 0;
@@ -82,7 +85,7 @@ public:
virtual void value(UInt64 v) = 0;
/// An unsigned 64-bit integer value is read. This will only be
/// triggered if the value cannot fit into a signed 64-bit integer.
/// triggered if the value cannot fit into a signed 64-bit integer.
#endif
virtual void value(const std::string& value) = 0;
@@ -94,6 +97,9 @@ public:
virtual void value(bool b) = 0;
/// A boolean value is read
virtual void comma();
/// A comma is read
protected:
virtual ~Handler();

View File

@@ -46,6 +46,7 @@
#include "Poco/Dynamic/Var.h"
#include <map>
#include <vector>
#include <deque>
#include <iostream>
#include <sstream>
@@ -60,8 +61,10 @@ class JSON_API Object
public:
typedef SharedPtr<Object> Ptr;
Object();
/// Default constructor
Object(bool preserveInsertionOrder = false);
/// Default constructor. If preserveInsertionOrder, object
/// will preserve the items insertion order. Otherwise, items
/// will be sorted by keys.
Object(const Object& copy);
/// Copy constructor
@@ -138,17 +141,55 @@ public:
void set(const std::string& key, const Dynamic::Var& value);
/// Sets a new value
void stringify(std::ostream& out, unsigned int indent = 0) const;
void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const;
/// Prints the object to out. When indent is 0, the object
/// will be printed on one line without indentation.
/// will be printed on a single line without indentation.
void remove(const std::string& key);
/// Removes the property with the given key
private:
//TODO: unordered map
template <typename C>
void doStringify(const C& container, std::ostream& out, unsigned int indent, int step) const
{
out << '{';
if (indent > 0) out << std::endl;
for (C::const_iterator it = container.begin(); it != container.end();)
{
for(int i = 0; i < indent; i++) out << ' ';
out << '"' << getKey(it) << '"';
out << ((indent > 0) ? " : " : ":");
Stringifier::stringify(getValue(it), out, indent + step, step);
if ( ++it != container.end() ) out << ',';
if (step > 0) out << '\n';
}
if (indent >= step) indent -= step;
for (int i = 0; i < indent; i++)
out << ' ';
out << '}';
}
typedef std::map<std::string, Dynamic::Var> ValueMap;
ValueMap _values;
typedef std::deque<Dynamic::Var*> KeyPtrList;
const std::string& getKey(ValueMap::const_iterator& it) const;
const Dynamic::Var& getValue(ValueMap::const_iterator& it) const;
const std::string& getKey(KeyPtrList::const_iterator& it) const;
const Dynamic::Var& getValue(KeyPtrList::const_iterator& it) const;
ValueMap _values;
KeyPtrList _keys;
bool _preserveInsOrder;
};
@@ -180,12 +221,6 @@ inline bool Object::isObject(const std::string& key) const
}
inline void Object::set(const std::string& key, const Dynamic::Var& value)
{
_values[key] = value;
}
inline std::size_t Object::size() const
{
return static_cast<std::size_t>(_values.size());
@@ -198,6 +233,24 @@ inline void Object::remove(const std::string& key)
}
inline const std::string& Object::getKey(ValueMap::const_iterator& it) const
{
return it->first;
}
inline const Dynamic::Var& Object::getValue(ValueMap::const_iterator& it) const
{
return it->second;
}
inline const Dynamic::Var& Object::getValue(KeyPtrList::const_iterator& it) const
{
return **it;
}
}} // Namespace Poco::JSON

View File

@@ -0,0 +1,181 @@
//
// ParseHandler.h
//
// $Id$
//
// Library: JSON
// Package: JSON
// Module: ParseHandler
//
// Definition of the ParseHandler class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef JSON_ParseHandler_INCLUDED
#define JSON_ParseHandler_INCLUDED
#include "Poco/JSON/Handler.h"
#include <stack>
namespace Poco {
namespace JSON {
class JSON_API ParseHandler : public Handler
/// Provides a default handler for the JSON parser.
/// This handler will build up an object or array based
/// on the handlers called by the parser.
{
public:
ParseHandler(bool preserveObjectOrder = false);
/// Creates the ParseHandler.
virtual ~ParseHandler();
/// Destroys the ParseHandler.
void startObject();
/// Handles a '{'; a new object is started.
void endObject();
/// Handles a '}'; the object is closed.
void startArray();
/// Handles a '['; a new array is started.
void endArray();
/// Handles a ']'; the array is closed.
void key(const std::string& k);
/// A key is read
Dynamic::Var result() const;
/// Returns the result of the parser (an object or an array).
virtual void value(int v);
/// An integer value is read
virtual void value(unsigned v);
/// An unsigned value is read. This will only be triggered if the
/// value cannot fit into a signed int.
#if defined(POCO_HAVE_INT64)
virtual void value(Int64 v);
/// A 64-bit integer value is read
virtual void value(UInt64 v);
/// An unsigned 64-bit integer value is read. This will only be
/// triggered if the value cannot fit into a signed 64-bit integer.
#endif
virtual void value(const std::string& s);
/// A string value is read.
virtual void value(double d);
/// A double value is read.
virtual void value(bool b);
/// A boolean value is read.
virtual void null();
/// A null value is read.
private:
void setValue(const Poco::Dynamic::Var& value);
typedef std::stack<Dynamic::Var> Stack;
Stack _stack;
std::string _key;
Dynamic::Var _result;
bool _preserveObjectOrder;
};
inline Dynamic::Var ParseHandler::result() const
{
return _result;
}
inline void ParseHandler::value(int v)
{
setValue(v);
}
inline void ParseHandler::value(unsigned v)
{
setValue(v);
}
#if defined(POCO_HAVE_INT64)
inline void ParseHandler::value(Int64 v)
{
setValue(v);
}
inline void ParseHandler::value(UInt64 v)
{
setValue(v);
}
#endif
inline void ParseHandler::value(const std::string& s)
{
setValue(s);
}
inline void ParseHandler::value(double d)
{
setValue(d);
}
inline void ParseHandler::value(bool b)
{
setValue(b);
}
inline void ParseHandler::null()
{
Poco::Dynamic::Var empty;
setValue(empty);
}
}} // namespace Poco::JSON
#endif // JSON_ParseHandler_INCLUDED

View File

@@ -0,0 +1,139 @@
//
// PrintHandler.h
//
// $Id$
//
// Library: JSON
// Package: JSON
// Module: PrintHandler
//
// Definition of the PrintHandler class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef JSON_PrintHandler_INCLUDED
#define JSON_PrintHandler_INCLUDED
#include "Poco/JSON/JSON.h"
#include "Poco/JSON/Handler.h"
namespace Poco {
namespace JSON {
class JSON_API PrintHandler : public Handler
/// PrintHandler formats and prints the JSON object
/// to either user-provided std::ostream or standard out.
/// If indent i zero, the output is condensed JSON string,
/// otherwise, the proper indentation is applied to elements.
{
public:
static const unsigned JSON_PRINT_FLAT = 0;
PrintHandler(unsigned indent = 0);
/// Creates the PrintHandler.
PrintHandler(std::ostream& out, unsigned indent = 0);
/// Creates the PrintHandler.
~PrintHandler();
/// Destroys the PrintHandler.
void startObject();
/// The parser has read a '{'; a new object is started.
/// If indent is greater than zero, a newline will be apended.
void endObject();
/// The parser has read a '}'; the object is closed.
void startArray();
/// The parser has read a [; a new array will be started.
/// If indent is greater than zero, a newline will be apended.
void endArray();
/// The parser has read a ]; the array is closed.
void key(const std::string& k);
/// A key of an object is read; it will be written to the output,
/// followed by a ':'. If indent is greater than zero, the colon
/// is padded by a space before and after.
void null();
/// A null value is read; "null" will be written to the output.
void value(int v);
/// An integer value is read.
void value(unsigned v);
/// An unsigned value is read. This will only be triggered if the
/// value cannot fit into a signed int.
#if defined(POCO_HAVE_INT64)
void value(Int64 v);
/// A 64-bit integer value is read; it will be written to the output.
void value(UInt64 v);
/// An unsigned 64-bit integer value is read; it will be written to the output.
#endif
void value(const std::string& value);
/// A string value is read; it will be fromatted and written to the output.
void value(double d);
/// A double value is read; it will be written to the output.
void value(bool b);
/// A boolean value is read; it will be written to the output.
void comma();
/// A comma is read; it will be written to the output as "true" or "false".
void setIndent(unsigned indent)
{
_indent = indent;
}
private:
const char* endLine() const;
unsigned indent();
bool printFlat() const;
std::ostream& _out;
unsigned _indent;
std::string _tab;
bool _array;
};
}} // namespace Poco::JSON
#endif // JSON_PrintHandler_INCLUDED

View File

@@ -53,12 +53,39 @@ class JSON_API Stringifier
/// Helper class for creating a String from a JSON object or array
{
public:
static void stringify(const Dynamic::Var& any, std::ostream& out, unsigned int indent = 0);
static void condense(const Dynamic::Var& any, std::ostream& out);
/// Writes a condensed string representation of the value to the output stream while preserving the insertion order.
/// This is just a "shortcut" to stringify(any, out) with name indicating the function effect.
static void stringify(const Dynamic::Var& any, bool preserveInsertionOrder, std::ostream& out, unsigned int indent = 0);
/// Writes a String representation of the value to the output stream while preserving the insertion order.
/// When indent is 0, the generated string will be created as small as possible (condensed).
/// When preserveInsertionOrder is true, the original string object members order will be preserved.
/// This is a "shortcut" to stringify(any, out, indent, -1, preserveInsertionOrder).
static void stringify(const Dynamic::Var& any, std::ostream& out, unsigned int indent = 0, int step = -1, bool preserveInsertionOrder = false);
/// Writes a String representation of the value to the output stream.
/// When indent is 0, the String will be created as small as possible.
/// When preserveInsertionOrder is true, the original string object members order will be preserved;
/// otherwise, object members are sorted by their names.
static void formatString(const std::string& value, std::ostream& out);
/// Formats the JSON string and streams it into ostream.
};
inline void Stringifier::condense(const Dynamic::Var& any, std::ostream& out)
{
stringify(any, out, 0, -1, true);
}
inline void Stringifier::stringify(const Dynamic::Var& any, bool preserveInsertionOrder, std::ostream& out, unsigned int indent)
{
stringify(any, out, indent, -1, preserveInsertionOrder);
}
}} // namespace Poco::JSON