bool KviKvsTreeNodeHashElement::evaluateReadOnlyInObjectScope(KviKvsObject *o,KviKvsRunTimeContext * c,KviKvsVariant * pBuffer)
{
	KviKvsVariant key;
	if(!m_pKey->evaluateReadOnly(c,&key))return false;

	QString szKey;
	key.asString(szKey);

	if(szKey.isEmpty())
	{
		c->warning(this,__tr2qs_ctx("Hash key evaluated to empty string: fix the script","kvs"));
		pBuffer->setNothing();
		return true;
	}

	KviKvsVariant val;
	if(o)
	{
		if(!m_pSource->evaluateReadOnlyInObjectScope(o,c,&val))return false;
	} else {
		if(!m_pSource->evaluateReadOnly(c,&val))return false;
	}

	if(!val.isHash())
	{
		if(!val.isNothing())
		{
			QString szType;
			val.getTypeName(szType);
			c->warning(this,__tr2qs_ctx("The argument of the {} subscript didn't evaluate to a hash: automatic conversion from type '%Q' supplied","kvs"),&szType);
		}
		pBuffer->setNothing();
		return true;
	}

	KviKvsVariant * v = val.hash()->find(szKey);
	if(!v)
	{
		pBuffer->setNothing();
		return true;
	}

	pBuffer->copyFrom(v);
	return true;
}
	bool process(KviKvsVariantList * pVariantList, KviKvsRunTimeContext * pContext, KviKvsParameterProcessor::ParameterFormat * pFmtArray)
	{
		KviKvsVariant * v = pVariantList->first();

		while(pFmtArray->szName)
		{
			if(!v)
			{
				// parameter not present
				// it MUST be optional
				if(!(pFmtArray->uFlags & KVS_PF_OPTIONAL))
				{
					// bad luck
					QString szError = QString(__tr2qs_ctx("Missing non-optional parameter \"%1\"", "kvs")).arg(pFmtArray->szName);
					pContext->error(szError);
					return false;
				}
				// ok, missing but optional (all the following are implicitly optional too)
				// set to default values
				do
				{
					setDefaultValue(pFmtArray);
					pFmtArray++;
				} while(pFmtArray->szName);
				return true;
			}
			// here we do only "light" casts: hard ones must be done explicitly by the user
			switch(pFmtArray->uType)
			{
				case KVS_PT_STRING:
					v->asString(*((QString *)(pFmtArray->pContainer)));
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QString *)(pFmtArray->pContainer)) += QChar(' ');
							v->appendAsString(*((QString *)(pFmtArray->pContainer)));
							v = pVariantList->next();
						}
						return true;
					}
					break;
				case KVS_PT_STRINGLIST:
				{
					((QStringList *)(pFmtArray->pContainer))->clear();
					QString pSz;
					v->asString(pSz);
					((QStringList *)(pFmtArray->pContainer))->append(pSz);
					v = pVariantList->next();
					while(v)
					{
						v->asString(pSz);
						((QStringList *)(pFmtArray->pContainer))->append(pSz);
						v = pVariantList->next();
					}
					return true;
				}
				break;
				case KVS_PT_VARIANTLIST:
				{
					((KviKvsVariantList *)(pFmtArray->pContainer))->clear();
					((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false);
					((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
					v = pVariantList->next();
					while(v)
					{
						((KviKvsVariantList *)(pFmtArray->pContainer))->append(v);
						v = pVariantList->next();
					}
					return true;
				}
				break;
				case KVS_PT_NONEMPTYSTRING:
				{
					v->asString(*((QString *)(pFmtArray->pContainer)));
					bool bDoReturn = false;
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QString *)(pFmtArray->pContainer)) += QChar(' ');
							v->appendAsString(*((QString *)(pFmtArray->pContainer)));
							v = pVariantList->next();
						}
						bDoReturn = true;
					}
					if(((QString *)(pFmtArray->pContainer))->isEmpty())
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found empty string while a non empty one was expected", "kvs")).arg(pFmtArray->szName);
						pContext->error(szError);
						return false;
					}
					if(bDoReturn)
						return true;
				}
				break;
				case KVS_PT_CSTRING:
				{
					QString tmp;
					v->asString(tmp);
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QByteArray *)(pFmtArray->pContainer)) += ' ';
							v->appendAsString(tmp);
							v = pVariantList->next();
						}
						*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
						return true;
					}
					*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
				}
				break;
				case KVS_PT_NONEMPTYCSTRING:
				{
					QString tmp;
					v->asString(tmp);
					bool bDoReturn = false;
					if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
					{
						v = pVariantList->next();
						while(v)
						{
							*((QByteArray *)(pFmtArray->pContainer)) += ' ';
							v->appendAsString(tmp);
							v = pVariantList->next();
						}
						*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
						bDoReturn = true;
					}
					*((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8();
					if(((QByteArray *)(pFmtArray->pContainer))->isEmpty())
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found empty string while a non empty one was expected", "kvs")).arg(pFmtArray->szName);
						pContext->error(szError);
						return false;
					}
					if(bDoReturn)
						return true;
				}
				break;
				case KVS_PT_INT:
					if(!v->asInteger(*((kvs_int_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "integer"))
							return false;
					}
					break;
				case KVS_PT_UINT:
				{
					kvs_int_t iTmp;
					if(!v->asInteger(iTmp))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "unsigned integer"))
							return false;
					}
					if(iTmp < 0)
					{
						QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\": found signed integer \"%2\" where type 'unsigned integer' was expected", "kvs")).arg(pFmtArray->szName).arg(iTmp);
						pContext->error(szError);
						return false;
					}
					*((kvs_uint_t *)(pFmtArray->pContainer)) = (kvs_uint_t)iTmp;
				}
				break;
				case KVS_PT_DOUBLE:
					if(!v->asReal(*((kvs_real_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "real"))
							return false;
					}
					break;
				case KVS_PT_HASH:
					if(!v->isHash())
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "hash"))
							return false;
					}
					else
					{
						*((KviKvsHash **)(pFmtArray->pContainer)) = v->hash();
					}
					break;
				case KVS_PT_ARRAYCAST:
					v->castToArray((KviKvsArrayCast *)(pFmtArray->pContainer));
					break;
				case KVS_PT_ARRAY:
					if(!v->isArray())
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "array"))
							return false;
					}
					else
					{
						*((KviKvsArray **)(pFmtArray->pContainer)) = v->array();
					}
					break;
				case KVS_PT_BOOL:
					// this never fails: anything is converted to a boolean
					*((bool *)(pFmtArray->pContainer)) = v->asBoolean();
					break;
				case KVS_PT_VARIANT:
					*((KviKvsVariant **)(pFmtArray->pContainer)) = v;
					break;
				case KVS_PT_HOBJECT:
					if(!v->asHObject(*((kvs_hobject_t *)(pFmtArray->pContainer))))
					{
						if(!handleParameterTypeError(pContext, pFmtArray, v, "hobject"))
							return false;
					}
					break;
				case KVS_PT_IGNORE:
					// ignore
					break;
				default:
					qDebug("Internal error in KviKvsParameterProcessor::processAsParameters(): unknown parameter type %d", pFmtArray->uType);
					return false;
					break;
			}
			pFmtArray++;
			v = pVariantList->next();
		}
		return true;
	}