From 9b960b6b0af48494bbe1b77becef58851b89e697 Mon Sep 17 00:00:00 2001 From: "miloyip@gmail.com" Date: Wed, 14 Nov 2012 07:07:06 +0000 Subject: [PATCH] Fixed Issue 7: GenericValue& operator[](const Ch* name) - bug if key not found Makes GenericValue::FindMember() public. Added array element and object member iteration APIs in examples. git-svn-id: https://rapidjson.googlecode.com/svn/trunk@83 c5894555-1306-4e8d-425f-1f6f381ee07c --- example/tutorial/tutorial.cpp | 18 +++++++++++++++ include/rapidjson/document.h | 43 +++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/example/tutorial/tutorial.cpp b/example/tutorial/tutorial.cpp index 60bac7d..1b5cacb 100644 --- a/example/tutorial/tutorial.cpp +++ b/example/tutorial/tutorial.cpp @@ -41,6 +41,12 @@ int main(int argc, char* argv[]) { assert(document["hello"].IsString()); printf("hello = %s\n", document["hello"].GetString()); + // Since version 0.2, you can use single lookup to check the existing of member and its value: + Value::Member* hello = document.FindMember("hello"); + assert(hello != 0); + assert(hello->value.IsString()); + assert(strcmp("world", hello->value.GetString()) == 0); + assert(document["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue(). printf("t = %s\n", document["t"].GetBool() ? "true" : "false"); @@ -67,8 +73,20 @@ int main(int argc, char* argv[]) { //int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. int z = a[0u].GetInt(); // This works too. + + // Iterating array with iterators + printf("a = "); + for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + printf("%d ", itr->GetInt()); + printf("\n"); } + // Iterating object members + static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; + for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) + printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]); + + //////////////////////////////////////////////////////////////////////////// // 3. Modify values in document. // Change i to a bigger number diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 7e90899..f848322 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -227,11 +227,18 @@ public: //! Set this value as an empty object. GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } - //! Get the value associated with the object's name. + //! Get the value associated with the name. + /*! + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use the now public FindMember(). + */ GenericValue& operator[](const Ch* name) { if (Member* member = FindMember(name)) return member->value; else { + RAPIDJSON_ASSERT(false); // see above note static GenericValue NullValue; return NullValue; } @@ -245,8 +252,28 @@ public: MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } //! Check whether a member exists in the object. + /*! + \note It is better to use FindMember() directly if you need the obtain the value as well. + */ bool HasMember(const Ch* name) const { return FindMember(name) != 0; } + //! Find member by name. + /*! + \return Return the member if exists. Otherwise returns null pointer. + */ + Member* FindMember(const Ch* name) { + RAPIDJSON_ASSERT(name); + RAPIDJSON_ASSERT(IsObject()); + + Object& o = data_.o; + for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) + if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) + return member; + + return 0; + } + const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + //! Add a member (name-value pair) to the object. /*! \param name A string value as name of member. \param value Value of any type. @@ -613,20 +640,6 @@ private: Array a; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - //! Find member by name. - Member* FindMember(const Ch* name) { - RAPIDJSON_ASSERT(name); - RAPIDJSON_ASSERT(IsObject()); - - Object& o = data_.o; - for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) - if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) - return member; - - return 0; - } - const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } - // Initialize this value as array with initial data, without calling destructor. void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { flags_ = kArrayFlag;