Esempio n. 1
0
bool VariantStreamHandler::write(const Variant& v, const NodePtr& node, bool writeType)
{
	// Variant only accepts binary/text streams for streamin/out, so we get to do this fun little stream dance.
	ResizingMemoryStream s;
	TextStream ts(s);
	ts << v;

	// Get the type to be used - leave it null if we shouldn't write the type, setValueRawData won't write a type
	const char* nodeTypeName = nullptr;
	size_t nodeTypeSize = 0;
	if (writeType)
	{
		nodeTypeName = variantName_;
		nodeTypeSize = strlen(nodeTypeName);
	}

	// ResizingMemoryStream is not guaranteed to be null terminated.
	node->setValueRawData(s.buffer().c_str(), s.buffer().size(), nodeTypeName, nodeTypeSize);
	node->setHandlerName(handlerName_);

	auto variantTypeName = this->getReservedNames().variantInternalType;
	auto typeNode = node->createEmptyChild(variantTypeName, strlen(variantTypeName));
	const char* internalTypeName = v.type()->typeId().getName();
	typeNode->setValueString(internalTypeName, strlen(internalTypeName));

	return true;
}
Esempio n. 2
0
bool CollectionHandler::write(const Variant& v, const NodePtr& node, bool writeType)
{
	node->setHandlerName(handlerName_);
	if (writeType)
	{
		node->setType(collectionName_, strlen(collectionName_));
	}

	bool success = false;

	Collection c;
	if (!v.tryCast<Collection>(c))
	{
		return false;
	}

	if (c.empty())
	{
		return true;
	}

	// Check that the key isn't a collection, since we can't serialize those.
	if (c.begin().key().canCast<Collection>())
	{
		return false;
	}

	// Find and hold on to our handlers
	std::shared_ptr<SerializationHandler> keyHandler = nullptr;
	std::shared_ptr<SerializationHandler> valueHandler = nullptr;
	const MetaType* keyMetaType = MetaType::find(c.keyType().getName());
	const MetaType* valueMetaType = MetaType::find(c.valueType().getName());
	// If a type in the collection is Variant, then the handler can vary, so leave it as nullptr.
	if (keyMetaType != MetaType::get<Variant>())
	{
		keyHandler = handlerManager_.findHandlerWrite(c.begin().key());
	}
	if (valueMetaType != MetaType::get<Variant>())
	{
		valueHandler = handlerManager_.findHandlerWrite(c.begin().value());
	}

	// Create a base node for all the elements in the collection.
	auto baseNode = node->createEmptyChild(collectionBaseNodeName_, strlen(collectionBaseNodeName_));

	// Iterate through all the objects in the collection
	for (auto iter = c.begin(); iter != c.end(); ++iter)
	{
		// Write the key, if it exists
		Variant key = iter.key();
		if (!key.isVoid())
		{
			// Create the key node
			std::unique_ptr<SerializationNode> keyNode;
			if (keyHandler.get() == nullptr)
			{
				// Variant type, go through the entire system
				keyNode = baseNode->createChildVariant(keyName_, strlen(keyName_), key);
			}
			else
			{
				// Non-Variant type, use our handler
				keyNode = baseNode->createEmptyChild(keyName_, strlen(keyName_));
				if (!keyHandler->write(key, keyNode, false))
				{
					return false;
				}
			}
			if (keyNode == nullptr)
			{
				return false;
			}

			// Write the value
			Variant value = iter.value();
			if (!value.isVoid())
			{
				// Create the value node
				std::unique_ptr<SerializationNode> valueNode;
				if (valueHandler.get() == nullptr)
				{
					// Variant type, go through the entire system
					valueNode = keyNode->createChildVariant(valueName_, strlen(valueName_), value);
				}
				else
				{
					// Non-Variant type, use our handler
					valueNode = keyNode->createEmptyChild(valueName_, strlen(valueName_));
					if (!valueHandler->write(value, valueNode, false))
					{
						return false;
					}
				}
				if (valueNode == nullptr)
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}

	// Write the types and handlers last so that the serialized list can be iterated through intuitively
	// Container type
	const char* collectionContainerName = this->getReservedNames().collectionContainerType;
	auto containerTypeNode = node->createEmptyChild(collectionContainerName, strlen(collectionContainerName));
	const char* collectionContainerType = c.impl()->containerType().getName();
	containerTypeNode->setType(collectionContainerType, strlen(collectionContainerType));
	// Key variant type
	const char* collectionKeyVName = this->getReservedNames().collectionKeyVariantType;
	auto keyVTypeNode = node->createEmptyChild(collectionKeyVName, strlen(collectionKeyVName));
	const char* collectionKeyVType = c.keyType().getName();
	keyVTypeNode->setType(collectionKeyVType, strlen(collectionKeyVType));
	// Value variant type
	const char* collectionValueVName = this->getReservedNames().collectionValueVariantType;
	auto valueVTypeNode = node->createEmptyChild(collectionValueVName, strlen(collectionValueVName));
	const char* collectionValueVType = c.valueType().getName();
	valueVTypeNode->setType(collectionValueVType, strlen(collectionValueVType));
	// Key internal type
	const char* collectionKeyIName = this->getReservedNames().collectionKeyInternalType;
	auto keyITypeNode = node->createEmptyChild(collectionKeyIName, strlen(collectionKeyIName));
	const char* collectionKeyIType = keyHandler->getInternalTypeOf(c.begin().key(), node);
	keyITypeNode->setType(collectionKeyIType, strlen(collectionKeyIType));
	// Value internal type
	const char* collectionValueIName = this->getReservedNames().collectionValueInternalType;
	auto valueITypeNode = node->createEmptyChild(collectionValueIName, strlen(collectionValueIName));
	const char* collectionValueIType = valueHandler->getInternalTypeOf(c.begin().value(), node);
	valueITypeNode->setType(collectionValueIType, strlen(collectionValueIType));
	// Key handler
	if (keyHandler.get() != nullptr)
	{
		const char* collectionKeyHandlerName = this->getReservedNames().collectionKeyHandler;
		auto keyHandlerNode = node->createEmptyChild(collectionKeyHandlerName, strlen(collectionKeyHandlerName));
		const char* collectionKeyHandler = keyHandler->getName();
		keyHandlerNode->setValueString(collectionKeyHandler, strlen(collectionKeyHandler));
	}
	// Value handler
	if (valueHandler.get() != nullptr)
	{
		const char* collectionValueHandlerName = this->getReservedNames().collectionValueHandler;
		auto valueHandlerNode = node->createEmptyChild(collectionValueHandlerName, strlen(collectionValueHandlerName));
		const char* collectionValueHandler = valueHandler->getName();
		valueHandlerNode->setValueString(collectionValueHandler, strlen(collectionValueHandler));
	}

	return true;
}