aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormontellese <montellese@kodi.tv>2015-09-09 22:56:34 +0200
committermontellese <montellese@xbmc.org>2017-03-24 07:55:51 +0100
commitf169edb6959de7ef97f898e40658a474cff60c54 (patch)
treeefe359d5a76d9311a4b07217162bccecd252cb78
parentd8fbb5a3aec149f75eb7c9540fa141dea3232a54 (diff)
CJSONVariantParser: use RapidJSON instead of yajl
-rw-r--r--xbmc/addons/AddonDatabase.cpp4
-rw-r--r--xbmc/interfaces/builtins/ApplicationBuiltins.cpp8
-rw-r--r--xbmc/interfaces/json-rpc/JSONRPC.cpp3
-rw-r--r--xbmc/interfaces/json-rpc/JSONServiceDescription.cpp6
-rw-r--r--xbmc/network/test/TestWebServer.cpp3
-rw-r--r--xbmc/playlists/SmartPlayList.cpp5
-rw-r--r--xbmc/utils/JSONVariantParser.cpp230
-rw-r--r--xbmc/utils/JSONVariantParser.h65
-rw-r--r--xbmc/utils/test/TestJSONVariantParser.cpp177
9 files changed, 310 insertions, 191 deletions
diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp
index ad655d6ae8..97aa782bfb 100644
--- a/xbmc/addons/AddonDatabase.cpp
+++ b/xbmc/addons/AddonDatabase.cpp
@@ -81,7 +81,9 @@ static std::string SerializeMetadata(const IAddon& addon)
static void DeserializeMetadata(const std::string& document, CAddonBuilder& builder)
{
- CVariant variant = CJSONVariantParser::Parse(document);
+ CVariant variant;
+ if (!CJSONVariantParser::Parse(document, variant))
+ return;
builder.SetAuthor(variant["author"].asString());
builder.SetDisclaimer(variant["disclaimer"].asString());
diff --git a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp
index a5860c2c12..2ea99d19fc 100644
--- a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp
+++ b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp
@@ -91,7 +91,13 @@ static int NotifyAll(const std::vector<std::string>& params)
{
CVariant data;
if (params.size() > 2)
- data = CJSONVariantParser::Parse((const unsigned char *)params[2].c_str(), params[2].size());
+ {
+ if (!CJSONVariantParser::Parse(params[2], data))
+ {
+ CLog::Log(LOGERROR, "NotifyAll failed to parse data: %s", params[2].c_str());
+ return -3;
+ }
+ }
ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::Other, params[0].c_str(), params[1].c_str(), data);
diff --git a/xbmc/interfaces/json-rpc/JSONRPC.cpp b/xbmc/interfaces/json-rpc/JSONRPC.cpp
index 3749fe55d9..f9e00956c2 100644
--- a/xbmc/interfaces/json-rpc/JSONRPC.cpp
+++ b/xbmc/interfaces/json-rpc/JSONRPC.cpp
@@ -241,8 +241,7 @@ std::string CJSONRPC::MethodCall(const std::string &inputString, ITransportLayer
if(g_advancedSettings.CanLogComponent(LOGJSONRPC))
CLog::Log(LOGDEBUG, "JSONRPC: Incoming request: %s", inputString.c_str());
- inputroot = CJSONVariantParser::Parse((unsigned char *)inputString.c_str(), inputString.length());
- if (!inputroot.isNull())
+ if (CJSONVariantParser::Parse(inputString, inputroot) && !inputroot.isNull())
{
if (inputroot.isArray())
{
diff --git a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
index 19113e5fcd..bb06937d4c 100644
--- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
+++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
@@ -1424,14 +1424,10 @@ bool CJSONServiceDescription::prepareDescription(std::string &description, CVari
}
if (description.at(0) != '{')
- {
description = StringUtils::Format("{{{:s}}}", description);
- }
-
- descriptionObject = CJSONVariantParser::Parse((const unsigned char *)description.c_str(), description.size());
// Make sure the method description actually exists and represents an object
- if (!descriptionObject.isObject())
+ if (!CJSONVariantParser::Parse(description, descriptionObject) || !descriptionObject.isObject())
{
CLog::Log(LOGERROR, "JSONRPC: Unable to parse JSON Schema definition for \"%s\"", name.c_str());
return false;
diff --git a/xbmc/network/test/TestWebServer.cpp b/xbmc/network/test/TestWebServer.cpp
index 3a4d9c4b14..9d65628234 100644
--- a/xbmc/network/test/TestWebServer.cpp
+++ b/xbmc/network/test/TestWebServer.cpp
@@ -384,7 +384,8 @@ TEST_F(TestWebServer, CanGetJsonRpcResponse)
ASSERT_FALSE(result.empty());
// parse the JSON-RPC response
- CVariant resultObj = CJSONVariantParser::Parse(reinterpret_cast<const unsigned char*>(result.c_str()), result.size());
+ CVariant resultObj;
+ ASSERT_TRUE(CJSONVariantParser::Parse(result, resultObj));
// make sure it's an object
ASSERT_TRUE(resultObj.isObject());
diff --git a/xbmc/playlists/SmartPlayList.cpp b/xbmc/playlists/SmartPlayList.cpp
index 0ac73d93e1..e76a2ba8e4 100644
--- a/xbmc/playlists/SmartPlayList.cpp
+++ b/xbmc/playlists/SmartPlayList.cpp
@@ -1267,7 +1267,10 @@ bool CSmartPlaylist::LoadFromJson(const std::string &json)
if (json.empty())
return false;
- CVariant obj = CJSONVariantParser::Parse((const unsigned char *)json.c_str(), json.size());
+ CVariant obj;
+ if (!CJSONVariantParser::Parse(json, obj))
+ return false;
+
return Load(obj);
}
diff --git a/xbmc/utils/JSONVariantParser.cpp b/xbmc/utils/JSONVariantParser.cpp
index b4572802ff..f6f4d2b268 100644
--- a/xbmc/utils/JSONVariantParser.cpp
+++ b/xbmc/utils/JSONVariantParser.cpp
@@ -20,200 +20,202 @@
#include "JSONVariantParser.h"
-yajl_callbacks CJSONVariantParser::callbacks = {
- CJSONVariantParser::ParseNull,
- CJSONVariantParser::ParseBoolean,
- CJSONVariantParser::ParseInteger,
- CJSONVariantParser::ParseDouble,
- NULL,
- CJSONVariantParser::ParseString,
- CJSONVariantParser::ParseMapStart,
- CJSONVariantParser::ParseMapKey,
- CJSONVariantParser::ParseMapEnd,
- CJSONVariantParser::ParseArrayStart,
- CJSONVariantParser::ParseArrayEnd
-};
+#include <rapidjson/reader.h>
+
+class CJSONVariantParserHandler
+{
+public:
+ CJSONVariantParserHandler(CVariant& parsedObject);
+
+ bool Null();
+ bool Bool(bool b);
+ bool Int(int i);
+ bool Uint(unsigned u);
+ bool Int64(int64_t i);
+ bool Uint64(uint64_t u);
+ bool Double(double d);
+ bool String(const char* str, rapidjson::SizeType length, bool copy);
+ bool StartObject();
+ bool Key(const char* str, rapidjson::SizeType length, bool copy);
+ bool EndObject(rapidjson::SizeType memberCount);
+ bool StartArray();
+ bool EndArray(rapidjson::SizeType elementCount);
+
+private:
+ template <typename... TArgs>
+ bool Primitive(TArgs... args)
+ {
+ PushObject(CVariant(std::forward<TArgs>(args)...));
+ PopObject();
-CJSONVariantParser::CJSONVariantParser(IParseCallback *callback)
-{
- m_callback = callback;
+ return true;
+ }
- m_handler = yajl_alloc(&callbacks, NULL, this);
+ void PushObject(CVariant variant);
+ void PopObject();
- yajl_config(m_handler, yajl_allow_comments, 1);
- yajl_config(m_handler, yajl_dont_validate_strings, 0);
+ CVariant& m_parsedObject;
+ std::vector<CVariant *> m_parse;
+ std::string m_key;
- m_status = ParseVariable;
-}
+ enum class PARSE_STATUS
+ {
+ Variable,
+ Array,
+ Object
+ };
+ PARSE_STATUS m_status;
+};
-CJSONVariantParser::~CJSONVariantParser()
-{
- yajl_complete_parse(m_handler);
- yajl_free(m_handler);
-}
+CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant& parsedObject)
+ : m_parsedObject(parsedObject),
+ m_parse(),
+ m_key(),
+ m_status(PARSE_STATUS::Variable)
+{ }
-void CJSONVariantParser::push_buffer(const unsigned char *buffer, unsigned int length)
+bool CJSONVariantParserHandler::Null()
{
- yajl_parse(m_handler, buffer, length);
+ PushObject(CVariant::ConstNullVariant);
+ PopObject();
+
+ return true;
}
-CVariant CJSONVariantParser::Parse(const std::string& json)
+bool CJSONVariantParserHandler::Bool(bool b)
{
- return Parse(reinterpret_cast<const unsigned char*>(json.c_str()), json.length());
+ return Primitive(b);
}
-CVariant CJSONVariantParser::Parse(const unsigned char *json, unsigned int length)
+bool CJSONVariantParserHandler::Int(int i)
{
- CSimpleParseCallback callback;
- CJSONVariantParser parser(&callback);
-
- parser.push_buffer(json, length);
-
- return callback.GetOutput();
+ return Primitive(i);
}
-int CJSONVariantParser::ParseNull(void * ctx)
+bool CJSONVariantParserHandler::Uint(unsigned u)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant::VariantTypeNull);
- parser->PopObject();
-
- return 1;
+ return Primitive(u);
}
-int CJSONVariantParser::ParseBoolean(void * ctx, int boolean)
+bool CJSONVariantParserHandler::Int64(int64_t i)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant(boolean != 0));
- parser->PopObject();
-
- return 1;
+ return Primitive(i);
}
-int CJSONVariantParser::ParseInteger(void * ctx, long long integerVal)
+bool CJSONVariantParserHandler::Uint64(uint64_t u)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant((int64_t)integerVal));
- parser->PopObject();
-
- return 1;
+ return Primitive(u);
}
-int CJSONVariantParser::ParseDouble(void * ctx, double doubleVal)
+bool CJSONVariantParserHandler::Double(double d)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant((float)doubleVal));
- parser->PopObject();
-
- return 1;
+ return Primitive(d);
}
-int CJSONVariantParser::ParseString(void * ctx, const unsigned char * stringVal, size_t stringLen)
+bool CJSONVariantParserHandler::String(const char* str, rapidjson::SizeType length, bool copy)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant((const char *)stringVal, stringLen));
- parser->PopObject();
-
- return 1;
+ return Primitive(str, length);
}
-int CJSONVariantParser::ParseMapStart(void * ctx)
+bool CJSONVariantParserHandler::StartObject()
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PushObject(CVariant::VariantTypeObject);
+ PushObject(CVariant::VariantTypeObject);
- return 1;
+ return true;
}
-int CJSONVariantParser::ParseMapKey(void * ctx, const unsigned char * stringVal, size_t stringLen)
+bool CJSONVariantParserHandler::Key(const char* str, rapidjson::SizeType length, bool copy)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+ m_key = std::string(str, 0, length);
- parser->m_key = std::string((const char *)stringVal, 0, stringLen);
-
- return 1;
+ return true;
}
-int CJSONVariantParser::ParseMapEnd(void * ctx)
+bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PopObject();
+ PopObject();
- return 1;
+ return true;
}
-int CJSONVariantParser::ParseArrayStart(void * ctx)
+bool CJSONVariantParserHandler::StartArray()
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+ PushObject(CVariant::VariantTypeArray);
- parser->PushObject(CVariant::VariantTypeArray);
-
- return 1;
+ return true;
}
-int CJSONVariantParser::ParseArrayEnd(void * ctx)
+bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount)
{
- CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
-
- parser->PopObject();
+ PopObject();
- return 1;
+ return true;
}
-void CJSONVariantParser::PushObject(CVariant variant)
+void CJSONVariantParserHandler::PushObject(CVariant variant)
{
- if (m_status == ParseObject)
+ if (m_status == PARSE_STATUS::Object)
{
(*m_parse[m_parse.size() - 1])[m_key] = variant;
m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]);
}
- else if (m_status == ParseArray)
+ else if (m_status == PARSE_STATUS::Array)
{
CVariant *temp = m_parse[m_parse.size() - 1];
temp->push_back(variant);
m_parse.push_back(&(*temp)[temp->size() - 1]);
}
else if (m_parse.empty())
- {
m_parse.push_back(new CVariant(variant));
- }
if (variant.isObject())
- m_status = ParseObject;
+ m_status = PARSE_STATUS::Object;
else if (variant.isArray())
- m_status = ParseArray;
+ m_status = PARSE_STATUS::Array;
else
- m_status = ParseVariable;
+ m_status = PARSE_STATUS::Variable;
}
-void CJSONVariantParser::PopObject()
+void CJSONVariantParserHandler::PopObject()
{
CVariant *variant = m_parse[m_parse.size() - 1];
m_parse.pop_back();
- if (m_parse.size())
+ if (!m_parse.empty())
{
variant = m_parse[m_parse.size() - 1];
if (variant->isObject())
- m_status = ParseObject;
+ m_status = PARSE_STATUS::Object;
else if (variant->isArray())
- m_status = ParseArray;
+ m_status = PARSE_STATUS::Array;
else
- m_status = ParseVariable;
+ m_status = PARSE_STATUS::Variable;
}
- else if (m_callback)
+ else
{
- m_callback->onParsed(variant);
+ m_parsedObject = *variant;
delete variant;
- m_parse.clear();
- m_status = ParseVariable;
+ m_status = PARSE_STATUS::Variable;
}
}
+
+bool CJSONVariantParser::Parse(const char* json, CVariant& data)
+{
+ if (json == nullptr)
+ return false;
+
+ rapidjson::Reader reader;
+ rapidjson::StringStream stringStream(json);
+
+ CJSONVariantParserHandler handler(data);
+ if (reader.Parse(stringStream, handler))
+ return true;
+
+ return false;
+}
+
+bool CJSONVariantParser::Parse(const std::string& json, CVariant& data)
+{
+ return Parse(json.c_str(), data);
+}
diff --git a/xbmc/utils/JSONVariantParser.h b/xbmc/utils/JSONVariantParser.h
index 535636cb6a..8852b2309e 100644
--- a/xbmc/utils/JSONVariantParser.h
+++ b/xbmc/utils/JSONVariantParser.h
@@ -1,6 +1,6 @@
#pragma once
/*
- * Copyright (C) 2005-2013 Team XBMC
+ * Copyright (C) 2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -20,71 +20,14 @@
*/
#include <string>
-#include <vector>
#include "utils/Variant.h"
-#include <yajl/yajl_parse.h>
-
-class IParseCallback
-{
-public:
- virtual ~IParseCallback() { }
-
- virtual void onParsed(CVariant *variant) = 0;
-};
-
-class CSimpleParseCallback : public IParseCallback
-{
-public:
- virtual void onParsed(CVariant *variant) { m_parsed = *variant; }
- CVariant &GetOutput() { return m_parsed; }
-
-private:
- CVariant m_parsed;
-};
-
class CJSONVariantParser
{
public:
- CJSONVariantParser(IParseCallback *callback);
- ~CJSONVariantParser();
-
- void push_buffer(const unsigned char *buffer, unsigned int length);
-
- static CVariant Parse(const unsigned char *json, unsigned int length);
-
- static CVariant Parse(const std::string& json);
-
-private:
- static int ParseNull(void * ctx);
- static int ParseBoolean(void * ctx, int boolean);
- static int ParseInteger(void * ctx, long long integerVal);
- static int ParseDouble(void * ctx, double doubleVal);
- static int ParseString(void * ctx, const unsigned char * stringVal, size_t stringLen);
- static int ParseMapStart(void * ctx);
- static int ParseMapKey(void * ctx, const unsigned char * stringVal, size_t stringLen);
- static int ParseMapEnd(void * ctx);
- static int ParseArrayStart(void * ctx);
- static int ParseArrayEnd(void * ctx);
-
- void PushObject(CVariant variant);
- void PopObject();
-
- static yajl_callbacks callbacks;
-
- IParseCallback *m_callback;
- yajl_handle m_handler;
-
- CVariant m_parsedObject;
- std::vector<CVariant *> m_parse;
- std::string m_key;
+ CJSONVariantParser() = delete;
- enum PARSE_STATUS
- {
- ParseArray = 1,
- ParseObject = 2,
- ParseVariable = 0
- };
- PARSE_STATUS m_status;
+ static bool Parse(const char* json, CVariant& data);
+ static bool Parse(const std::string& json, CVariant& data);
};
diff --git a/xbmc/utils/test/TestJSONVariantParser.cpp b/xbmc/utils/test/TestJSONVariantParser.cpp
index 65b9f171bf..95dad4966f 100644
--- a/xbmc/utils/test/TestJSONVariantParser.cpp
+++ b/xbmc/utils/test/TestJSONVariantParser.cpp
@@ -23,12 +23,179 @@
#include "gtest/gtest.h"
-TEST(TestJSONVariantParser, Parse)
+TEST(TestJSONVariantParser, CannotParseNullptr)
{
CVariant variant;
- unsigned char buf[100];
+ ASSERT_FALSE(CJSONVariantParser::Parse(nullptr, variant));
+}
+
+TEST(TestJSONVariantParser, CannotParseEmptyString)
+{
+ CVariant variant;
+ ASSERT_FALSE(CJSONVariantParser::Parse("", variant));
+ ASSERT_FALSE(CJSONVariantParser::Parse(std::string(), variant));
+}
+
+TEST(TestJSONVariantParser, CannotParseInvalidJson)
+{
+ CVariant variant;
+ ASSERT_FALSE(CJSONVariantParser::Parse("{", variant));
+ ASSERT_FALSE(CJSONVariantParser::Parse("}", variant));
+ ASSERT_FALSE(CJSONVariantParser::Parse("[", variant));
+ ASSERT_FALSE(CJSONVariantParser::Parse("]", variant));
+ ASSERT_FALSE(CJSONVariantParser::Parse("foo", variant));
+}
+
+TEST(TestJSONVariantParser, CanParseNull)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("null", variant));
+ ASSERT_TRUE(variant.isNull());
+}
+
+TEST(TestJSONVariantParser, CanParseBoolean)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("true", variant));
+ ASSERT_TRUE(variant.isBoolean());
+ ASSERT_TRUE(variant.asBoolean());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("false", variant));
+ ASSERT_TRUE(variant.isBoolean());
+ ASSERT_FALSE(variant.asBoolean());
+}
+
+TEST(TestJSONVariantParser, CanParseSignedInteger)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("-1", variant));
+ ASSERT_TRUE(variant.isInteger());
+ ASSERT_EQ(-1, variant.asInteger());
+}
+
+TEST(TestJSONVariantParser, CanParseUnsignedInteger)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("0", variant));
+ ASSERT_TRUE(variant.isUnsignedInteger());
+ ASSERT_EQ(0, variant.asUnsignedInteger());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("1", variant));
+ ASSERT_TRUE(variant.isUnsignedInteger());
+ ASSERT_EQ(1, variant.asUnsignedInteger());
+}
+
+TEST(TestJSONVariantParser, CanParseSignedInteger64)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("-4294967296", variant));
+ ASSERT_TRUE(variant.isInteger());
+ ASSERT_EQ(-4294967296, variant.asInteger());
+}
+
+TEST(TestJSONVariantParser, CanParseUnsignedInteger64)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("4294967296", variant));
+ ASSERT_TRUE(variant.isUnsignedInteger());
+ ASSERT_EQ(4294967296, variant.asUnsignedInteger());
+}
+
+TEST(TestJSONVariantParser, CanParseDouble)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("0.0", variant));
+ ASSERT_TRUE(variant.isDouble());
+ ASSERT_EQ(0.0, variant.asDouble());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("1.0", variant));
+ ASSERT_TRUE(variant.isDouble());
+ ASSERT_EQ(1.0, variant.asDouble());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("-1.0", variant));
+ ASSERT_TRUE(variant.isDouble());
+ ASSERT_EQ(-1.0, variant.asDouble());
+}
+
+TEST(TestJSONVariantParser, CanParseString)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("\"\"", variant));
+ ASSERT_TRUE(variant.isString());
+ ASSERT_TRUE(variant.empty());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("\"foo\"", variant));
+ ASSERT_TRUE(variant.isString());
+ ASSERT_STREQ("foo", variant.asString().c_str());
+
+ ASSERT_TRUE(CJSONVariantParser::Parse("\"foo bar\"", variant));
+ ASSERT_TRUE(variant.isString());
+ ASSERT_STREQ("foo bar", variant.asString().c_str());
+}
+
+TEST(TestJSONVariantParser, CanParseObject)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("{}", variant));
+ ASSERT_TRUE(variant.isObject());
+ ASSERT_TRUE(variant.empty());
+
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("{ \"foo\": \"bar\" }", variant));
+ ASSERT_TRUE(variant.isObject());
+ ASSERT_TRUE(variant.isMember("foo"));
+ ASSERT_TRUE(variant["foo"].isString());
+ ASSERT_STREQ("bar", variant["foo"].asString().c_str());
+
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("{ \"foo\": \"bar\", \"bar\": true }", variant));
+ ASSERT_TRUE(variant.isObject());
+ ASSERT_TRUE(variant.isMember("foo"));
+ ASSERT_TRUE(variant["foo"].isString());
+ ASSERT_STREQ("bar", variant["foo"].asString().c_str());
+ ASSERT_TRUE(variant.isMember("bar"));
+ ASSERT_TRUE(variant["bar"].isBoolean());
+ ASSERT_TRUE(variant["bar"].asBoolean());
+
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("{ \"foo\": { \"sub-foo\": \"bar\" } }", variant));
+ ASSERT_TRUE(variant.isObject());
+ ASSERT_TRUE(variant.isMember("foo"));
+ ASSERT_TRUE(variant["foo"].isObject());
+ ASSERT_TRUE(variant["foo"].isMember("sub-foo"));
+ ASSERT_TRUE(variant["foo"]["sub-foo"].isString());
+ ASSERT_STREQ("bar", variant["foo"]["sub-foo"].asString().c_str());
+}
+
+TEST(TestJSONVariantParser, CanParseArray)
+{
+ CVariant variant;
+ ASSERT_TRUE(CJSONVariantParser::Parse("[]", variant));
+ ASSERT_TRUE(variant.isArray());
+ ASSERT_TRUE(variant.empty());
+
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("[ true ]", variant));
+ ASSERT_TRUE(variant.isArray());
+ ASSERT_EQ(1, variant.size());
+ ASSERT_TRUE(variant[0].isBoolean());
+ ASSERT_TRUE(variant[0].asBoolean());
+
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("[ true, \"foo\" ]", variant));
+ ASSERT_TRUE(variant.isArray());
+ ASSERT_EQ(2, variant.size());
+ ASSERT_TRUE(variant[0].isBoolean());
+ ASSERT_TRUE(variant[0].asBoolean());
+ ASSERT_TRUE(variant[1].isString());
+ ASSERT_STREQ("foo", variant[1].asString().c_str());
- memset(buf, 0, sizeof(buf));
- variant = CJSONVariantParser::Parse(buf, sizeof(buf));
- EXPECT_TRUE(variant.isNull());
+ variant.clear();
+ ASSERT_TRUE(CJSONVariantParser::Parse("[ { \"foo\": \"bar\" } ]", variant));
+ ASSERT_TRUE(variant.isArray());
+ ASSERT_EQ(1, variant.size());
+ ASSERT_TRUE(variant[0].isObject());
+ ASSERT_TRUE(variant[0].isMember("foo"));
+ ASSERT_TRUE(variant[0]["foo"].isString());
+ ASSERT_STREQ("bar", variant[0]["foo"].asString().c_str());
}