diff options
author | montellese <montellese@kodi.tv> | 2015-09-09 22:56:34 +0200 |
---|---|---|
committer | montellese <montellese@xbmc.org> | 2017-03-24 07:55:51 +0100 |
commit | f169edb6959de7ef97f898e40658a474cff60c54 (patch) | |
tree | efe359d5a76d9311a4b07217162bccecd252cb78 | |
parent | d8fbb5a3aec149f75eb7c9540fa141dea3232a54 (diff) |
CJSONVariantParser: use RapidJSON instead of yajl
-rw-r--r-- | xbmc/addons/AddonDatabase.cpp | 4 | ||||
-rw-r--r-- | xbmc/interfaces/builtins/ApplicationBuiltins.cpp | 8 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/JSONRPC.cpp | 3 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/JSONServiceDescription.cpp | 6 | ||||
-rw-r--r-- | xbmc/network/test/TestWebServer.cpp | 3 | ||||
-rw-r--r-- | xbmc/playlists/SmartPlayList.cpp | 5 | ||||
-rw-r--r-- | xbmc/utils/JSONVariantParser.cpp | 230 | ||||
-rw-r--r-- | xbmc/utils/JSONVariantParser.h | 65 | ||||
-rw-r--r-- | xbmc/utils/test/TestJSONVariantParser.cpp | 177 |
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()); } |