handler reference counting

- handler reference counting
- parser returns parsing result
This commit is contained in:
Aleksandar Fabijanic 2013-03-24 17:32:57 -05:00
parent 4668c13af7
commit 579842bce4
7 changed files with 122 additions and 189 deletions

View File

@ -41,6 +41,7 @@
#include "Poco/JSON/JSON.h"
#include "Poco/SharedPtr.h"
#include "Poco/Dynamic/Var.h"
@ -51,8 +52,13 @@ namespace JSON {
class JSON_API Handler
{
public:
typedef SharedPtr<Handler> Ptr;
Handler();
/// Constructor;
virtual ~Handler();
/// Destructor
virtual void startObject() = 0;
/// The parser has read a {, meaning a new object will be read
@ -100,12 +106,9 @@ public:
virtual void comma();
/// A comma is read
protected:
virtual ~Handler();
/// Destructor
private:
virtual Dynamic::Var result() const;
/// Returns the result of the parser (an object, array or string),
/// empty Var if there is no result.
};

View File

@ -54,7 +54,6 @@ class JSON_API ParseHandler : public Handler
/// on the handlers called by the parser.
{
public:
ParseHandler(bool preserveObjectOrder = false);
/// Creates the ParseHandler.

View File

@ -43,7 +43,7 @@
#include "Poco/JSON/JSON.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Array.h"
#include "Poco/JSON/Handler.h"
#include "Poco/JSON/ParseHandler.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/StreamTokenizer.h"
#include <istream>
@ -59,24 +59,27 @@ class JSON_API Parser
{
public:
Parser();
Parser(const Handler::Ptr& pHandler = new ParseHandler);
/// Constructor.
virtual ~Parser();
/// Destructor.
void parse(const std::string& source);
Dynamic::Var parse(const std::string& source);
/// Parses a string.
void parse(std::istream& in);
Dynamic::Var parse(std::istream& in);
/// Parses a JSON from the input stream.
void setHandler(Handler* handler);
void setHandler(const Handler::Ptr& pHandler);
/// Set the handler.
Handler* getHandler();
const Handler::Ptr& getHandler();
/// Returns the handler.
Dynamic::Var result() const;
/// Returns the result of parsing;
private:
const Token* nextToken();
/// Returns the next token.
@ -97,26 +100,32 @@ private:
/// Read all elements of an array.
StreamTokenizer _tokenizer;
Handler* _handler;
Handler::Ptr _pHandler;
};
inline void Parser::parse(const std::string& source)
inline Dynamic::Var Parser::parse(const std::string& source)
{
std::istringstream is(source);
parse(is);
return parse(is);
}
inline void Parser::setHandler(Handler* handler)
inline void Parser::setHandler(const Handler::Ptr& pHandler)
{
_handler = handler;
_pHandler = pHandler;
}
inline Handler* Parser::getHandler()
inline const Handler::Ptr& Parser::getHandler()
{
return _handler;
return _pHandler;
}
inline Dynamic::Var Parser::result() const
{
return _pHandler->result();
}

View File

@ -55,6 +55,8 @@ class JSON_API PrintHandler : public Handler
/// otherwise, the proper indentation is applied to elements.
{
public:
typedef SharedPtr<PrintHandler> Ptr;
static const unsigned JSON_PRINT_FLAT = 0;
PrintHandler(unsigned indent = 0);
@ -115,10 +117,8 @@ public:
void comma();
/// A comma is read; it will be written to the output as "true" or "false".
void setIndent(unsigned indent)
{
_indent = indent;
}
void setIndent(unsigned indent);
/// Sets indentation.
private:
@ -133,6 +133,12 @@ private:
};
inline void PrintHandler::setIndent(unsigned indent)
{
_indent = indent;
}
}} // namespace Poco::JSON

View File

@ -57,4 +57,10 @@ void Handler::comma()
}
Dynamic::Var Handler::result() const
{
return Dynamic::Var();
}
} } // namespace Poco::JSON

View File

@ -484,7 +484,7 @@ private:
};
Parser::Parser() : _tokenizer(), _handler(NULL)
Parser::Parser(const Handler::Ptr& pHandler) : _tokenizer(), _pHandler(pHandler)
{
_tokenizer.addToken(new WhitespaceToken());
_tokenizer.addToken(new InvalidToken());
@ -512,7 +512,7 @@ const Token* Parser::nextToken()
}
void Parser::parse(std::istream& in)
Dynamic::Var Parser::parse(std::istream& in)
{
_tokenizer.attachToStream(in);
const Token* token = nextToken();
@ -542,14 +542,16 @@ void Parser::parse(std::istream& in)
{
throw JSONException(format("Invalid token '%s' found. Expecting { or [", token->asString()));
}
return result();
}
void Parser::readObject()
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->startObject();
_pHandler->startObject();
}
if ( readRow(true) ) // First call is special: check for empty object
@ -557,9 +559,9 @@ void Parser::readObject()
while(readRow());
}
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->endObject();
_pHandler->endObject();
}
}
@ -576,9 +578,9 @@ bool Parser::readRow(bool firstCall)
if (token->tokenClass() == Token::STRING_LITERAL_TOKEN)
{
std::string propertyName = token->tokenString();
if ( _handler != NULL )
if ( !_pHandler.isNull() )
{
_handler->key(propertyName);
_pHandler->key(propertyName);
}
token = nextToken();
@ -594,9 +596,9 @@ bool Parser::readRow(bool firstCall)
{
if (token->asChar() == ',')
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->comma();
_pHandler->comma();
}
return true; // Read next row
}
@ -637,7 +639,7 @@ void Parser::readValue(const Token* token)
break;
case Token::INTEGER_LITERAL_TOKEN:
if (_handler != NULL)
if (!_pHandler.isNull())
{
#if defined(POCO_HAVE_INT64)
try
@ -647,11 +649,11 @@ void Parser::readValue(const Token* token)
if ( value > std::numeric_limits<int>::max()
|| value < std::numeric_limits<int>::min() )
{
_handler->value(value);
_pHandler->value(value);
}
else
{
_handler->value(static_cast<int>(value));
_pHandler->value(static_cast<int>(value));
}
}
// try to handle error as unsigned in case of overflow
@ -661,11 +663,11 @@ void Parser::readValue(const Token* token)
// if number is 32-bit, then handle as such
if ( value > std::numeric_limits<unsigned>::max() )
{
_handler->value(value);
_pHandler->value(value);
}
else
{
_handler->value(static_cast<unsigned>(value));
_pHandler->value(static_cast<unsigned>(value));
}
}
#else
@ -687,23 +689,23 @@ void Parser::readValue(const Token* token)
{
if (token->tokenString().compare("null") == 0)
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->null();
_pHandler->null();
}
}
else if (token->tokenString().compare("true") == 0)
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->value(true);
_pHandler->value(true);
}
}
else if (token->tokenString().compare("false") == 0)
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->value(false);
_pHandler->value(false);
}
}
else
@ -715,15 +717,15 @@ void Parser::readValue(const Token* token)
case Token::FLOAT_LITERAL_TOKEN:
// Fall through
case Token::DOUBLE_LITERAL_TOKEN:
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->value(token->asFloat());
_pHandler->value(token->asFloat());
}
break;
case Token::STRING_LITERAL_TOKEN:
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->value(token->tokenString());
_pHandler->value(token->tokenString());
}
break;
case Token::SEPARATOR_TOKEN:
@ -746,9 +748,9 @@ void Parser::readValue(const Token* token)
void Parser::readArray()
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->startArray();
_pHandler->startArray();
}
if (readElements(true)) // First call is special: check for empty array
@ -756,9 +758,9 @@ void Parser::readArray()
while(readElements());
}
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->endArray();
_pHandler->endArray();
}
}
@ -784,9 +786,9 @@ bool Parser::readElements(bool firstCall)
if (token->asChar() == ',')
{
if (_handler != NULL)
if (!_pHandler.isNull())
{
_handler->comma();
_pHandler->comma();
}
return true;
}

View File

@ -88,10 +88,7 @@ void JSONTest::testNullProperty()
Var result;
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -115,10 +112,7 @@ void JSONTest::testTrueProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -144,10 +138,7 @@ void JSONTest::testFalseProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -173,10 +164,7 @@ void JSONTest::testNumberProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -203,10 +191,7 @@ void JSONTest::testUnsignedNumberProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -234,10 +219,7 @@ void JSONTest::testNumber64Property()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -264,10 +246,7 @@ void JSONTest::testUnsignedNumber64Property()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -295,10 +274,7 @@ void JSONTest::testStringProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -324,10 +300,7 @@ void JSONTest::testEmptyObject()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -404,10 +377,7 @@ void JSONTest::testComplexObject()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -427,10 +397,7 @@ void JSONTest::testDoubleProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -456,10 +423,7 @@ void JSONTest::testDouble2Property()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -485,10 +449,7 @@ void JSONTest::testDouble3Property()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -514,10 +475,7 @@ void JSONTest::testObjectProperty()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -550,10 +508,7 @@ void JSONTest::testObjectArray()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -580,10 +535,7 @@ void JSONTest::testArrayOfObjects()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -611,10 +563,7 @@ void JSONTest::testEmptyArray()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -637,10 +586,7 @@ void JSONTest::testNestedArray()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -663,10 +609,7 @@ void JSONTest::testNullElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -691,10 +634,7 @@ void JSONTest::testTrueElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -720,10 +660,7 @@ void JSONTest::testFalseElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -749,10 +686,7 @@ void JSONTest::testNumberElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -778,10 +712,7 @@ void JSONTest::testStringElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -807,10 +738,7 @@ void JSONTest::testEmptyObjectElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -834,10 +762,7 @@ void JSONTest::testDoubleElement()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -863,10 +788,7 @@ void JSONTest::testOptValue()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -890,10 +812,7 @@ void JSONTest::testQuery()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -915,12 +834,12 @@ void JSONTest::testPrintHandler()
std::string json = "{ \"name\" : \"Homer\", \"age\" : 38, \"wife\" : \"Marge\", \"age\" : 36, \"children\" : [ \"Bart\", \"Lisa\", \"Maggie\" ] }";
Parser parser;
std::ostringstream ostr;
PrintHandler handler(ostr);
parser.setHandler(&handler);
PrintHandler::Ptr pHandler = new PrintHandler(ostr);
parser.setHandler(pHandler);
parser.parse(json);
assert (ostr.str() == "{\"name\":\"Homer\",\"age\":38,\"wife\":\"Marge\",\"age\":36,\"children\":[\"Bart\",\"Lisa\",\"Maggie\"]}");
handler.setIndent(1);
pHandler->setIndent(1);
ostr.str("");
parser.parse(json);
assert (ostr.str() == "{\n"
@ -936,7 +855,7 @@ void JSONTest::testPrintHandler()
"}"
);
handler.setIndent(2);
pHandler->setIndent(2);
ostr.str("");
parser.parse(json);
assert (ostr.str() == "{\n"
@ -952,7 +871,7 @@ void JSONTest::testPrintHandler()
"}"
);
handler.setIndent(4);
pHandler->setIndent(4);
ostr.str("");
parser.parse(json);
assert (ostr.str() == "{\n"
@ -980,10 +899,7 @@ void JSONTest::testStringify()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -1104,15 +1020,14 @@ void JSONTest::testStringifyPreserveOrder()
std::string json = "{ \"Simpsons\" : { \"husband\" : { \"name\" : \"Homer\" , \"age\" : 38 }, \"wife\" : { \"name\" : \"Marge\", \"age\" : 36 }, "
"\"children\" : [ \"Bart\", \"Lisa\", \"Maggie\" ], "
"\"address\" : { \"number\" : 742, \"street\" : \"Evergreen Terrace\", \"town\" : \"Springfield\" } } }";
Parser parser;
ParseHandler::Ptr pHandler = new ParseHandler(true);
Parser parser(pHandler);
Var result;
try
{
ParseHandler handler(true);
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.parse(json);
}
catch(JSONException& jsone)
{
@ -1124,6 +1039,7 @@ void JSONTest::testStringifyPreserveOrder()
std::ostringstream ostr;
Stringifier::condense(result, ostr);
std::cout << ostr.str() << std::endl;
assert (ostr.str() == "{\"Simpsons\":{\"husband\":{\"name\":\"Homer\",\"age\":38},\"wife\":{\"name\":\"Marge\",\"age\":36},"
"\"children\":[\"Bart\",\"Lisa\",\"Maggie\"],"
"\"address\":{\"number\":742,\"street\":\"Evergreen Terrace\",\"town\":\"Springfield\"}}}");
@ -1235,10 +1151,8 @@ void JSONTest::testValidJanssonFiles()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(fis);
result = handler.result();
result = parser.result();
std::cout << "Ok!" << std::endl;
}
catch(JSONException& jsone)
@ -1283,10 +1197,8 @@ void JSONTest::testInvalidJanssonFiles()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(fis);
result = handler.result();
result = parser.result();
// We shouldn't get here.
std::cout << "We didn't get an exception. This is the result: " << result.convert<std::string>() << std::endl;
fail(result.convert<std::string>());
@ -1327,10 +1239,8 @@ void JSONTest::testInvalidUnicodeJanssonFiles()
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(fis);
result = handler.result();
result = parser.result();
// We shouldn't get here.
std::cout << "We didn't get an exception. This is the result: " << result.convert<std::string>() << std::endl;
fail(result.convert<std::string>());
@ -1375,10 +1285,8 @@ void JSONTest::testUnicode()
Var result;
try
{
ParseHandler handler;
parser.setHandler(&handler);
parser.parse(json);
result = handler.result();
result = parser.result();
}
catch(JSONException& jsone)
{