Advertisement

Serializing and de-serializing dictionary

Started by February 27, 2020 03:52 PM
3 comments, last by robertomurta 4 years, 8 months ago

hi,
I registered a class and methods that should serialize and de-serialize a angelscript dictionary object (addon) from C++.
In order to do that, I should be able to iterate on dictionary structure, identify each item type, and get it's value. And then recurse if an item is a dictionary,. That's the goal.

For serialization (which I will think better after) I will need to create the objects used in angelscript and insert them into dictionary from C++ side.

I'm having trouble to manipulate dictionary class using CScriptDictionary::CIterator at C++ side.
Some constructors methods are protected, and I could not use CIterator properly.
Already tried some changes on CScriptDictionary, without success, and I think maybe there is a way whithout changing anything.

So, I need help.

For those with similar problem: I ended up using CScriptDictionary::GetKeys() wich returns a CScriptArray*, and then loop through it.

Also I found that the CScriptArray addon interface documentation gives good clues on creating an instance from C++ side.

In the code sample below, Pack() is the serializer method and has an overload for each type.

void WebsocketClient::Pack(const CScriptDictionary& dictionary)
{
	if (dictionary.IsEmpty())
		return;
	CScriptArray* keys = dictionary.GetKeys();
	asUINT size = dictionary.GetSize();

	PackMap(size);
	for (asUINT i = 0; i < size; i++)
	{
		dictKey_t key(*(dictKey_t*)keys->At(i));
		int type_id = dictionary[key]->GetTypeId();
		const void* value = dictionary[key]->GetAddressOfValue();
		if (!value)
			PackNil();

		Pack(key);
		switch (type_id)
		{
		case asTYPEID_DOUBLE:
			Pack(*(double*)value);
			break;
		case asTYPEID_FLOAT:
			Pack(*(float*)value);
			break;
		case asTYPEID_INT64:
			Pack(*(int64_t*)value);
			break;
		case asTYPEID_INT32:
			Pack(*(int32_t*)value);
			break;
		case asTYPEID_INT16:
			Pack(*(int16_t*)value);
			break;
		case asTYPEID_INT8:
			Pack(*(int8_t*)value);
			break;
		case asTYPEID_UINT64:
			Pack(*(uint64_t*)value);
			break;
		case asTYPEID_UINT32:
			Pack(*(uint32_t*)value);
			break;
		case asTYPEID_UINT16:
			Pack(*(uint16_t*)value);
			break;
		case asTYPEID_UINT8:
			Pack(*(uint8_t*)value);
			break;
		case asTYPEID_BOOL:
			Pack(*(bool*)value);
			break;

		// if it is not a const value, use cached type_id (type_id defined at AS engine runtime)
		default:
			if (type_id == m_string_type_id)
				Pack(*(std::string*)value);
			else if (type_id == m_vector2_type_id)
				Pack(*(Vector2*)value);
			else if (type_id == m_vector3_type_id)
				Pack(*(Vector3*)value);
			// check if type_id match with any of the template specialization
			else if (isCScriptArray(type_id))
				Pack(*(CScriptArray*)value);
			else if (type_id == m_dictionary_type_id)
				Pack(*(CScriptDictionary*)value);
		}
	}
}
Advertisement

If you still want to use the iterator, it works like this:

void foo(CScriptDictionary *dict)
{
	for (auto it : *dict)
	{
		std::string keyName = it.GetKey();
		int typeId = it.GetTypeId();
		const void *addressOfValue = it.GetAddressOfValue();

		// serialize the key and value pair the same way you already do
	}
}

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

That's much better. Thank you.

This topic is closed to new replies.

Advertisement