You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/kvs/kvi_kvs_parameterprocessor.cpp

372 lines
11 KiB

//=============================================================================
//
// File : kvi_kvs_parameterprocessor.cpp
// Created on Sun 17 Apr 2005 16:47:09 by Szymon Stefanek
//
// This file is part of the KVIrc IRC client distribution
// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot net>
//
// This program is FREE software. You can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your opinion) any later version.
//
// This program is distributed in the HOPE that it will be USEFUL,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, write to the Free Software Foundation,
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
#define __KVIRC__
#include "kvi_kvs_parameterprocessor.h"
#include "kvi_kvs_variantlist.h"
#include "kvi_kvs_runtimecontext.h"
#include "kvi_kvs_variantlist.h"
#include "kvi_kvs_array.h"
#include "kvi_kvs_arraycast.h"
#include "kvi_kvs_hash.h"
#include "kvi_kvs_object.h"
#include "kvi_qstring.h"
#include "kvi_locale.h"
#include "kvi_pointerlist.h"
#include <tqstringlist.h>
namespace KviKvsParameterProcessor
{
void setDefaultValue(KviKvsParameterProcessor::ParameterFormat * pFmtArray)
{
#ifdef COMPILE_NEW_KVS
switch(pFmtArray->uType)
{
case KVS_PT_STRING:
case KVS_PT_NONEMPTYSTRING:
*((TQString *)(pFmtArray->pContainer)) = TQString();
break;
case KVS_PT_INT:
*((kvs_int_t *)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_UINT:
*((kvs_uint_t *)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_DOUBLE:
*((kvs_real_t *)(pFmtArray->pContainer)) = 0.0;
break;
case KVS_PT_BOOL:
*((bool *)(pFmtArray->pContainer)) = false;
break;
case KVS_PT_HASH:
*((KviKvsHash **)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_ARRAY:
*((KviKvsArray **)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_ARRAYCAST:
((KviKvsArrayCast *)(pFmtArray->pContainer))->clear();
break;
case KVS_PT_VARIANT:
*((KviKvsVariant **)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_CSTRING:
case KVS_PT_NONEMPTYCSTRING:
*((KviTQCString *)(pFmtArray->pContainer)) = 0;
break;
case KVS_PT_STRINGLIST:
((TQStringList *)(pFmtArray->pContainer))->clear();
break;
case KVS_PT_VARIANTLIST:
((KviKvsVariantList *)(pFmtArray->pContainer))->clear();
((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false);
break;
case KVS_PT_HOBJECT:
*((kvs_hobject_t *)(pFmtArray->pContainer)) = (kvs_hobject_t)0;
break;
case KVS_PT_IGNORE:
// ignore :)
break;
default:
tqDebug("Internal error in KviKvsParameterProcessor::setDefaultValue(): unknown parameter type %d",pFmtArray->uType);
break;
}
#endif
}
bool handleParameterTypeError(KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray,KviKvsVariant * v,const char * szExpectedType)
{
if(pFmtArray->uFlags & KVS_PF_OPTIONAL)
{
if(v->isEmpty())
{
setDefaultValue(pFmtArray);
return true; // empty optional
}
}
TQString szError;
KviTQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
szError += ": ";
if(v->isString())
{
TQString tmp = v->string();
if(tmp.isEmpty())
{
KviTQString::appendFormatted(szError,__tr2qs("found empty string where type '%s' was expected"),&tmp,szExpectedType);
} else {
if(tmp.length() > 15)
{
tmp.truncate(15);
tmp.append("...");
}
KviTQString::appendFormatted(szError,__tr2qs("found string value \"%Q\" where type '%s' was expected"),&tmp,szExpectedType);
}
} else {
TQString tmp;
v->getTypeName(tmp);
KviTQString::appendFormatted(szError,__tr2qs("found type %Q where type '%s' was expected"),&tmp,szExpectedType);
}
pContext->error(szError);
return false;
}
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
TQString szError;
KviTQString::sprintf(szError,__tr2qs("Missing non-optional parameter \"%s\""),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(*((TQString *)(pFmtArray->pContainer)));
if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
{
v = pVariantList->next();
while(v)
{
*((TQString *)(pFmtArray->pContainer)) += TQChar(' ');
v->appendAsString(*((TQString *)(pFmtArray->pContainer)));
v = pVariantList->next();
}
return true;
}
break;
case KVS_PT_STRINGLIST:
{
((TQStringList *)(pFmtArray->pContainer))->clear();
TQString pSz;
v->asString(pSz);
((TQStringList *)(pFmtArray->pContainer))->append(pSz);
v = pVariantList->next();
while(v)
{
v->asString(pSz);
((TQStringList *)(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(*((TQString *)(pFmtArray->pContainer)));
bool bDoReturn = false;
if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
{
v = pVariantList->next();
while(v)
{
*((TQString *)(pFmtArray->pContainer)) += TQChar(' ');
v->appendAsString(*((TQString *)(pFmtArray->pContainer)));
v = pVariantList->next();
}
bDoReturn = true;
}
if(((TQString *)(pFmtArray->pContainer))->isEmpty())
{
TQString szError;
KviTQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
szError += ": ";
KviTQString::sprintf(szError,__tr2qs("found empty string while a non empty one was expected"));
pContext->error(szError);
return false;
}
if(bDoReturn)return true;
}
break;
case KVS_PT_CSTRING:
{
TQString tmp;
v->asString(tmp);
if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
{
v = pVariantList->next();
while(v)
{
*((KviTQCString *)(pFmtArray->pContainer)) += ' ';
v->appendAsString(tmp);
v = pVariantList->next();
}
*((KviTQCString *)(pFmtArray->pContainer)) = tmp.utf8();
return true;
}
*((KviTQCString *)(pFmtArray->pContainer)) = tmp.utf8();
}
break;
case KVS_PT_NONEMPTYCSTRING:
{
TQString tmp;
v->asString(tmp);
bool bDoReturn = false;
if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING)
{
v = pVariantList->next();
while(v)
{
*((KviTQCString *)(pFmtArray->pContainer)) += ' ';
v->appendAsString(tmp);
v = pVariantList->next();
}
*((KviTQCString *)(pFmtArray->pContainer)) = tmp.utf8();
bDoReturn = true;
}
*((KviTQCString *)(pFmtArray->pContainer)) = tmp.utf8();
if(((KviTQCString *)(pFmtArray->pContainer))->isEmpty())
{
TQString szError;
KviTQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
szError += ": ";
KviTQString::sprintf(szError,__tr2qs("found empty string while a non empty one was expected"));
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)
{
TQString szError;
KviTQString::sprintf(szError,__tr2qs("Invalid data type for parameter \"%s\""),pFmtArray->szName);
szError += ": ";
KviTQString::sprintf(szError,__tr2qs("found signed integer \"%d\" where type 'unsigned integer' was expected"),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();
}
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:
tqDebug("Internal error in KviKvsParameterProcessor::processAsParameters(): unknown parameter type %d",pFmtArray->uType);
return false;
break;
}
pFmtArray++;
v = pVariantList->next();
}
return true;
}
};