예제 #1
0
void iterateArray(Value::ConstValueIterator& itr,
		Value::ConstValueIterator& itrEnd, StringBuffer *buffer,
		Writer<StringBuffer> *writer, stringstream& ss) {
	for (; itr != itrEnd; itr++) {
		if (itr->IsObject()) {
			Value::ConstMemberIterator itr_ = itr->MemberBegin();
			Value::ConstMemberIterator itrEnd_ = itr->MemberEnd();
			iterateObject(itr_, itrEnd_, buffer, writer, ss);
		} else if (itr->IsArray()) {
			Value::ConstValueIterator itr_ = itr->Begin();
			Value::ConstValueIterator itrEnd_ = itr->End();
			iterateArray(itr_, itrEnd_, buffer, writer, ss);
		} else if (itr->IsBool()) {
			ss << DELIM << itr->GetBool();
		} else if (itr->IsInt()) {
			ss << DELIM << itr->GetInt();
		} else if (itr->IsInt64()) {
			ss << DELIM << itr->GetInt64();
		} else if (itr->IsDouble()) {
			ss << DELIM << itr->GetDouble();
		} else if (itr->IsString()) {
			ss << DELIM << "\"" << itr->GetString() << "\"";
		} else {
			throw runtime_error(string("Case missing from tokenizer"));
		}
	}
}
예제 #2
0
 void JSONArray::_parseRapidJSONArray(void *value) {
     rapidjson::Value *rapidjsonValue = (rapidjson::Value *)value;
     
     for (Value::ConstValueIterator currentValue = rapidjsonValue->Begin(); currentValue != rapidjsonValue->End(); ++currentValue)
         
         switch (currentValue->GetType()) {
             case kNullType:
                 break;
             case kFalseType:
             case kTrueType:
                 this->appendValue(shared_ptr<JSONNumber> (new JSONNumber(kTrueType ? true: false)));
                 break;
             case kObjectType: {
                 shared_ptr<JSONObject> obj(new JSONObject());
                 obj->_parseRapidJSONObject((void*)currentValue);
                 this->appendValue(obj);
             }
                 break;
             case kArrayType: {
                 shared_ptr<JSONArray> obj(new JSONArray());
                 obj->_parseRapidJSONArray((void*)currentValue);
                 this->appendValue(obj);
             }
                 break;
             case kStringType:
                 this->appendValue(shared_ptr<JSONString> (new JSONString(currentValue->GetString())));
                 break;
             case kNumberType:
                 if (rapidjsonValue->IsDouble()) {
                     this->appendValue(shared_ptr<JSONNumber> (new JSONNumber(currentValue->GetDouble())));
                 } else if (rapidjsonValue->IsInt() || currentValue->IsInt64()) {
                     this->appendValue(shared_ptr<JSONNumber> (new JSONNumber(currentValue->GetInt())));
                 } else if (currentValue->IsUint() || currentValue->IsUint64()) {
                     this->appendValue(shared_ptr<JSONNumber> (new JSONNumber(currentValue->GetUint())));
                 }
                 
                 break;
         }
 }
예제 #3
0
int main(int, char*[]) {
	////////////////////////////////////////////////////////////////////////////
	// 1. Parse a JSON text string to a document.

	const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
	printf("Original JSON:\n %s\n", json);

	Document document;  // Default template parameter uses UTF8 and MemoryPoolAllocator.

#if 0
	// "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream().
	if (document.Parse(json).HasParseError())
		return 1;
#else
	// In-situ parsing, decode strings directly in the source string. Source must be string.
	char buffer[sizeof(json)];
	memcpy(buffer, json, sizeof(json));
	if (document.ParseInsitu(buffer).HasParseError())
		return 1;
#endif

	printf("\nParsing to document succeeded.\n");

	////////////////////////////////////////////////////////////////////////////
	// 2. Access values in document. 

	printf("\nAccess values in document:\n");
	assert(document.IsObject());    // Document is a JSON value represents the root of DOM. Root can be either an object or array.

	assert(document.HasMember("hello"));
	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::MemberIterator hello = document.FindMember("hello");
	assert(hello != document.MemberEnd());
	assert(hello->value.IsString());
	assert(strcmp("world", hello->value.GetString()) == 0);
	(void)hello;

	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");

	assert(document["f"].IsBool());
	printf("f = %s\n", document["f"].GetBool() ? "true" : "false");

	printf("n = %s\n", document["n"].IsNull() ? "null" : "?");

	assert(document["i"].IsNumber());   // Number is a JSON type, but C++ needs more specific type.
	assert(document["i"].IsInt());      // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
	printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]

	assert(document["pi"].IsNumber());
	assert(document["pi"].IsDouble());
	printf("pi = %g\n", document["pi"].GetDouble());

	{
		const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster.
		assert(a.IsArray());
		for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t.
			printf("a[%d] = %d\n", i, a[i].GetInt());

		int y = a[0].GetInt();
		(void)y;

		// 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
	{
		uint64_t f20 = 1;   // compute factorial of 20
		for (uint64_t j = 1; j <= 20; j++)
			f20 *= j;
		document["i"] = f20;    // Alternate form: document["i"].SetUint64(f20)
		assert(!document["i"].IsInt()); // No longer can be cast as int or uint.
	}

	// Adding values to array.
	{
		Value& a = document["a"];   // This time we uses non-const reference.
		Document::AllocatorType& allocator = document.GetAllocator();
		for (int i = 5; i <= 10; i++)
			a.PushBack(i, allocator);   // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.

		// Fluent API
		a.PushBack("Lua", allocator).PushBack("Mio", allocator);
	}

	// Making string values.

	// This version of SetString() just store the pointer to the string.
	// So it is for literal and string that exists within value's life-cycle.
	{
		document["hello"] = "rapidjson";    // This will invoke strlen()
		// Faster version:
		// document["hello"].SetString("rapidjson", 9);
	}

	// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
	Value author;
	{
		char buffer[10];
		int len = sprintf(buffer, "%s %s", "Milo", "Yip");  // synthetic example of dynamically created string.

		author.SetString(buffer, static_cast<size_t>(len), document.GetAllocator());
		// Shorter but slower version:
		// document["hello"].SetString(buffer, document.GetAllocator());

		// Constructor version: 
		// Value author(buffer, len, document.GetAllocator());
		// Value author(buffer, document.GetAllocator());
		memset(buffer, 0, sizeof(buffer)); // For demonstration purpose.
	}
	// Variable 'buffer' is unusable now but 'author' has already made a copy.
	document.AddMember("author", author, document.GetAllocator());

	assert(author.IsNull());        // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.

	////////////////////////////////////////////////////////////////////////////
	// 4. Stringify JSON

	printf("\nModified JSON with reformatting:\n");
	StringBuffer sb;
	PrettyWriter<StringBuffer> writer(sb);
	document.Accept(writer);    // Accept() traverses the DOM and generates Handler events.
	puts(sb.GetString());

	return 0;
}
예제 #4
0
TEST(Value, Array) {
	Value x(kArrayType);
	const Value& y = x;
	Value::AllocatorType allocator;

	EXPECT_EQ(kArrayType, x.GetType());
	EXPECT_TRUE(x.IsArray());
	EXPECT_TRUE(x.Empty());
	EXPECT_EQ(0u, x.Size());
	EXPECT_TRUE(y.IsArray());
	EXPECT_TRUE(y.Empty());
	EXPECT_EQ(0u, y.Size());

	EXPECT_FALSE(x.IsNull());
	EXPECT_FALSE(x.IsBool());
	EXPECT_FALSE(x.IsFalse());
	EXPECT_FALSE(x.IsTrue());
	EXPECT_FALSE(x.IsString());
	EXPECT_FALSE(x.IsObject());

	// PushBack()
	Value v;
	x.PushBack(v, allocator);
	v.SetBool(true);
	x.PushBack(v, allocator);
	v.SetBool(false);
	x.PushBack(v, allocator);
	v.SetInt(123);
	x.PushBack(v, allocator);

	EXPECT_FALSE(x.Empty());
	EXPECT_EQ(4u, x.Size());
	EXPECT_FALSE(y.Empty());
	EXPECT_EQ(4u, y.Size());
	EXPECT_TRUE(x[SizeType(0)].IsNull());
	EXPECT_TRUE(x[1u].IsTrue());
	EXPECT_TRUE(x[2u].IsFalse());
	EXPECT_TRUE(x[3u].IsInt());
	EXPECT_EQ(123, x[3u].GetInt());
	EXPECT_TRUE(y[SizeType(0)].IsNull());
	EXPECT_TRUE(y[1u].IsTrue());
	EXPECT_TRUE(y[2u].IsFalse());
	EXPECT_TRUE(y[3u].IsInt());
	EXPECT_EQ(123, y[3u].GetInt());

	// iterator
	Value::ValueIterator itr = x.Begin();
	EXPECT_TRUE(itr != x.End());
	EXPECT_TRUE(itr->IsNull());
	++itr;
	EXPECT_TRUE(itr != x.End());
	EXPECT_TRUE(itr->IsTrue());
	++itr;
	EXPECT_TRUE(itr != x.End());
	EXPECT_TRUE(itr->IsFalse());
	++itr;
	EXPECT_TRUE(itr != x.End());
	EXPECT_TRUE(itr->IsInt());
	EXPECT_EQ(123, itr->GetInt());

	// const iterator
	Value::ConstValueIterator citr = y.Begin();
	EXPECT_TRUE(citr != y.End());
	EXPECT_TRUE(citr->IsNull());
	++citr;
	EXPECT_TRUE(citr != y.End());
	EXPECT_TRUE(citr->IsTrue());
	++citr;
	EXPECT_TRUE(citr != y.End());
	EXPECT_TRUE(citr->IsFalse());
	++citr;
	EXPECT_TRUE(citr != y.End());
	EXPECT_TRUE(citr->IsInt());
	EXPECT_EQ(123, citr->GetInt());

	// PopBack()
	x.PopBack();
	EXPECT_EQ(3u, x.Size());
	EXPECT_TRUE(y[SizeType(0)].IsNull());
	EXPECT_TRUE(y[1].IsTrue());
	EXPECT_TRUE(y[2].IsFalse());

	// Clear()
	x.Clear();
	EXPECT_TRUE(x.Empty());
	EXPECT_EQ(0u, x.Size());
	EXPECT_TRUE(y.Empty());
	EXPECT_EQ(0u, y.Size());

	// SetArray()
	Value z;
	z.SetArray();
	EXPECT_TRUE(z.IsArray());
	EXPECT_TRUE(z.Empty());
}
예제 #5
0
TEST(Value, Array) {
    Value x(kArrayType);
    const Value& y = x;
    Value::AllocatorType allocator;

    EXPECT_EQ(kArrayType, x.GetType());
    EXPECT_TRUE(x.IsArray());
    EXPECT_TRUE(x.Empty());
    EXPECT_EQ(0u, x.Size());
    EXPECT_TRUE(y.IsArray());
    EXPECT_TRUE(y.Empty());
    EXPECT_EQ(0u, y.Size());

    EXPECT_FALSE(x.IsNull());
    EXPECT_FALSE(x.IsBool());
    EXPECT_FALSE(x.IsFalse());
    EXPECT_FALSE(x.IsTrue());
    EXPECT_FALSE(x.IsString());
    EXPECT_FALSE(x.IsObject());

    // PushBack()
    Value v;
    x.PushBack(v, allocator);
    v.SetBool(true);
    x.PushBack(v, allocator);
    v.SetBool(false);
    x.PushBack(v, allocator);
    v.SetInt(123);
    x.PushBack(v, allocator);
    //x.PushBack((const char*)"foo", allocator); // should not compile
    x.PushBack("foo", allocator);

    EXPECT_FALSE(x.Empty());
    EXPECT_EQ(5u, x.Size());
    EXPECT_FALSE(y.Empty());
    EXPECT_EQ(5u, y.Size());
    EXPECT_TRUE(x[SizeType(0)].IsNull());
    EXPECT_TRUE(x[1].IsTrue());
    EXPECT_TRUE(x[2].IsFalse());
    EXPECT_TRUE(x[3].IsInt());
    EXPECT_EQ(123, x[3].GetInt());
    EXPECT_TRUE(y[SizeType(0)].IsNull());
    EXPECT_TRUE(y[1].IsTrue());
    EXPECT_TRUE(y[2].IsFalse());
    EXPECT_TRUE(y[3].IsInt());
    EXPECT_EQ(123, y[3].GetInt());
    EXPECT_TRUE(y[4].IsString());
    EXPECT_STREQ("foo", y[4].GetString());

#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
    // PushBack(GenericValue&&, Allocator&);
    {
        Value y(kArrayType);
        y.PushBack(Value(true), allocator);
        y.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator);
        EXPECT_EQ(2u, y.Size());
        EXPECT_TRUE(y[0].IsTrue());
        EXPECT_TRUE(y[1].IsArray());
        EXPECT_EQ(2u, y[1].Size());
        EXPECT_TRUE(y[1][0].IsInt());
        EXPECT_TRUE(y[1][1].IsString());
    }
#endif

    // iterator
    Value::ValueIterator itr = x.Begin();
    EXPECT_TRUE(itr != x.End());
    EXPECT_TRUE(itr->IsNull());
    ++itr;
    EXPECT_TRUE(itr != x.End());
    EXPECT_TRUE(itr->IsTrue());
    ++itr;
    EXPECT_TRUE(itr != x.End());
    EXPECT_TRUE(itr->IsFalse());
    ++itr;
    EXPECT_TRUE(itr != x.End());
    EXPECT_TRUE(itr->IsInt());
    EXPECT_EQ(123, itr->GetInt());
    ++itr;
    EXPECT_TRUE(itr != x.End());
    EXPECT_TRUE(itr->IsString());
    EXPECT_STREQ("foo", itr->GetString());

    // const iterator
    Value::ConstValueIterator citr = y.Begin();
    EXPECT_TRUE(citr != y.End());
    EXPECT_TRUE(citr->IsNull());
    ++citr;
    EXPECT_TRUE(citr != y.End());
    EXPECT_TRUE(citr->IsTrue());
    ++citr;
    EXPECT_TRUE(citr != y.End());
    EXPECT_TRUE(citr->IsFalse());
    ++citr;
    EXPECT_TRUE(citr != y.End());
    EXPECT_TRUE(citr->IsInt());
    EXPECT_EQ(123, citr->GetInt());
    ++citr;
    EXPECT_TRUE(citr != y.End());
    EXPECT_TRUE(citr->IsString());
    EXPECT_STREQ("foo", citr->GetString());

    // PopBack()
    x.PopBack();
    EXPECT_EQ(4u, x.Size());
    EXPECT_TRUE(y[SizeType(0)].IsNull());
    EXPECT_TRUE(y[1].IsTrue());
    EXPECT_TRUE(y[2].IsFalse());
    EXPECT_TRUE(y[3].IsInt());

    // Clear()
    x.Clear();
    EXPECT_TRUE(x.Empty());
    EXPECT_EQ(0u, x.Size());
    EXPECT_TRUE(y.Empty());
    EXPECT_EQ(0u, y.Size());

    // Erase(ValueIterator)

    // Use array of array to ensure removed elements' destructor is called.
    // [[0],[1],[2],...]
    for (int i = 0; i < 10; i++)
        x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator);

    // Erase the first
    itr = x.Erase(x.Begin());
    EXPECT_EQ(x.Begin(), itr);
    EXPECT_EQ(9u, x.Size());
    for (int i = 0; i < 9; i++)
        EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt());

    // Ease the last
    itr = x.Erase(x.End() - 1);
    EXPECT_EQ(x.End(), itr);
    EXPECT_EQ(8u, x.Size());
    for (int i = 0; i < 8; i++)
        EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt());

    // Erase the middle
    itr = x.Erase(x.Begin() + 4);
    EXPECT_EQ(x.Begin() + 4, itr);
    EXPECT_EQ(7u, x.Size());
    for (int i = 0; i < 4; i++)
        EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt());
    for (int i = 4; i < 7; i++)
        EXPECT_EQ(i + 2, x[static_cast<SizeType>(i)][0].GetInt());

    // Erase(ValueIterator, ValueIterator)
    // Exhaustive test with all 0 <= first < n, first <= last <= n cases
    const unsigned n = 10;
    for (unsigned first = 0; first < n; first++) {
        for (unsigned last = first; last <= n; last++) {
            x.Clear();
            for (unsigned i = 0; i < n; i++)
                x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator);
            
            itr = x.Erase(x.Begin() + first, x.Begin() + last);
            if (last == n)
                EXPECT_EQ(x.End(), itr);
            else
                EXPECT_EQ(x.Begin() + first, itr);

            size_t removeCount = last - first;
            EXPECT_EQ(n - removeCount, x.Size());
            for (unsigned i = 0; i < first; i++)
                EXPECT_EQ(i, x[i][0].GetUint());
            for (unsigned i = first; i < n - removeCount; i++)
                EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUint());
        }
    }

    // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
    // http://en.wikipedia.org/wiki/Erase-remove_idiom
    x.Clear();
    for (int i = 0; i < 10; i++)
        if (i % 2 == 0)
            x.PushBack(i, allocator);
        else
            x.PushBack(Value(kNullType).Move(), allocator);

    const Value null(kNullType);
    x.Erase(std::remove(x.Begin(), x.End(), null), x.End());
    EXPECT_EQ(5u, x.Size());
    for (int i = 0; i < 5; i++)
        EXPECT_EQ(i * 2, x[static_cast<SizeType>(i)]);

    // SetArray()
    Value z;
    z.SetArray();
    EXPECT_TRUE(z.IsArray());
    EXPECT_TRUE(z.Empty());
}