1 //============================================================================= 2 // 3 // File : KviKvsParameterProcessor.cpp 4 // Creation date : Sun 17 Apr 2005 16:47:09 by Szymon Stefanek 5 // 6 // This file is part of the KVIrc IRC client distribution 7 // Copyright (C) 2005-2010 Szymon Stefanek <pragma at kvirc dot net> 8 // 9 // This program is FREE software. You can redistribute it and/or 10 // modify it under the terms of the GNU General Public License 11 // as published by the Free Software Foundation; either version 2 12 // of the License, or (at your option) any later version. 13 // 14 // This program is distributed in the HOPE that it will be USEFUL, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 // See the GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with this program. If not, write to the Free Software Foundation, 21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 // 23 //============================================================================= 24 25 #include "KviKvsParameterProcessor.h" 26 #include "KviKvsVariantList.h" 27 #include "KviKvsRunTimeContext.h" 28 #include "KviKvsArray.h" 29 #include "KviKvsArrayCast.h" 30 #include "KviKvsHash.h" 31 #include "KviKvsObject.h" 32 #include "KviQString.h" 33 #include "KviLocale.h" 34 #include "KviPointerList.h" 35 36 #include <QStringList> 37 38 namespace KviKvsParameterProcessor 39 { setDefaultValue(KviKvsParameterProcessor::ParameterFormat * pFmtArray)40 void setDefaultValue(KviKvsParameterProcessor::ParameterFormat * pFmtArray) 41 { 42 switch(pFmtArray->uType) 43 { 44 case KVS_PT_STRING: 45 case KVS_PT_NONEMPTYSTRING: 46 *((QString *)(pFmtArray->pContainer)) = QString(); 47 break; 48 case KVS_PT_INT: 49 *((kvs_int_t *)(pFmtArray->pContainer)) = 0; 50 break; 51 case KVS_PT_UINT: 52 *((kvs_uint_t *)(pFmtArray->pContainer)) = 0; 53 break; 54 case KVS_PT_DOUBLE: 55 *((kvs_real_t *)(pFmtArray->pContainer)) = 0.0; 56 break; 57 case KVS_PT_BOOL: 58 *((bool *)(pFmtArray->pContainer)) = false; 59 break; 60 case KVS_PT_HASH: 61 *((KviKvsHash **)(pFmtArray->pContainer)) = nullptr; 62 break; 63 case KVS_PT_ARRAY: 64 *((KviKvsArray **)(pFmtArray->pContainer)) = nullptr; 65 break; 66 case KVS_PT_ARRAYCAST: 67 ((KviKvsArrayCast *)(pFmtArray->pContainer))->clear(); 68 break; 69 case KVS_PT_VARIANT: 70 *((KviKvsVariant **)(pFmtArray->pContainer)) = nullptr; 71 break; 72 case KVS_PT_CSTRING: 73 case KVS_PT_NONEMPTYCSTRING: 74 *((QByteArray *)(pFmtArray->pContainer)) = nullptr; 75 break; 76 case KVS_PT_STRINGLIST: 77 ((QStringList *)(pFmtArray->pContainer))->clear(); 78 break; 79 case KVS_PT_VARIANTLIST: 80 ((KviKvsVariantList *)(pFmtArray->pContainer))->clear(); 81 ((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false); 82 break; 83 case KVS_PT_HOBJECT: 84 *((kvs_hobject_t *)(pFmtArray->pContainer)) = (kvs_hobject_t) nullptr; 85 break; 86 case KVS_PT_IGNORE: 87 // ignore :) 88 break; 89 default: 90 qDebug("Internal error in KviKvsParameterProcessor::setDefaultValue(): unknown parameter type %d", pFmtArray->uType); 91 break; 92 } 93 } 94 handleParameterTypeError(KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray,KviKvsVariant * v,const char * szExpectedType)95 bool handleParameterTypeError(KviKvsRunTimeContext * pContext, KviKvsParameterProcessor::ParameterFormat * pFmtArray, KviKvsVariant * v, const char * szExpectedType) 96 { 97 if(pFmtArray->uFlags & KVS_PF_OPTIONAL) 98 { 99 if(v->isEmpty()) 100 { 101 setDefaultValue(pFmtArray); 102 return true; // empty optional 103 } 104 } 105 106 QString szError = QString(__tr2qs_ctx("Invalid data type for parameter \"%1\"", "kvs")).arg(pFmtArray->szName); 107 szError += ": "; 108 109 if(v->isString()) 110 { 111 QString tmp = v->string(); 112 if(tmp.isEmpty()) 113 { 114 KviQString::appendFormatted(szError, __tr2qs_ctx("found empty string where type '%s' was expected", "kvs"), &tmp, szExpectedType); 115 } 116 else 117 { 118 if(tmp.length() > 15) 119 { 120 tmp.truncate(15); 121 tmp.append("..."); 122 } 123 KviQString::appendFormatted(szError, __tr2qs_ctx("found string value \"%Q\" where type '%s' was expected", "kvs"), &tmp, szExpectedType); 124 } 125 } 126 else 127 { 128 QString tmp; 129 v->getTypeName(tmp); 130 KviQString::appendFormatted(szError, __tr2qs_ctx("found type %Q where type '%s' was expected", "kvs"), &tmp, szExpectedType); 131 } 132 pContext->error(szError); 133 return false; 134 } 135 process(KviKvsVariantList * pVariantList,KviKvsRunTimeContext * pContext,KviKvsParameterProcessor::ParameterFormat * pFmtArray)136 bool process(KviKvsVariantList * pVariantList, KviKvsRunTimeContext * pContext, KviKvsParameterProcessor::ParameterFormat * pFmtArray) 137 { 138 KviKvsVariant * v = pVariantList->first(); 139 140 while(pFmtArray->szName) 141 { 142 if(!v) 143 { 144 // parameter not present 145 // it MUST be optional 146 if(!(pFmtArray->uFlags & KVS_PF_OPTIONAL)) 147 { 148 // bad luck 149 QString szError = QString(__tr2qs_ctx("Missing non-optional parameter \"%1\"", "kvs")).arg(pFmtArray->szName); 150 pContext->error(szError); 151 return false; 152 } 153 // ok, missing but optional (all the following are implicitly optional too) 154 // set to default values 155 do 156 { 157 setDefaultValue(pFmtArray); 158 pFmtArray++; 159 } while(pFmtArray->szName); 160 return true; 161 } 162 // here we do only "light" casts: hard ones must be done explicitly by the user 163 switch(pFmtArray->uType) 164 { 165 case KVS_PT_STRING: 166 v->asString(*((QString *)(pFmtArray->pContainer))); 167 if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING) 168 { 169 v = pVariantList->next(); 170 while(v) 171 { 172 *((QString *)(pFmtArray->pContainer)) += QChar(' '); 173 v->appendAsString(*((QString *)(pFmtArray->pContainer))); 174 v = pVariantList->next(); 175 } 176 return true; 177 } 178 break; 179 case KVS_PT_STRINGLIST: 180 { 181 ((QStringList *)(pFmtArray->pContainer))->clear(); 182 QString pSz; 183 v->asString(pSz); 184 ((QStringList *)(pFmtArray->pContainer))->append(pSz); 185 v = pVariantList->next(); 186 while(v) 187 { 188 v->asString(pSz); 189 ((QStringList *)(pFmtArray->pContainer))->append(pSz); 190 v = pVariantList->next(); 191 } 192 return true; 193 } 194 break; 195 case KVS_PT_VARIANTLIST: 196 { 197 ((KviKvsVariantList *)(pFmtArray->pContainer))->clear(); 198 ((KviKvsVariantList *)(pFmtArray->pContainer))->setAutoDelete(false); 199 ((KviKvsVariantList *)(pFmtArray->pContainer))->append(v); 200 v = pVariantList->next(); 201 while(v) 202 { 203 ((KviKvsVariantList *)(pFmtArray->pContainer))->append(v); 204 v = pVariantList->next(); 205 } 206 return true; 207 } 208 break; 209 case KVS_PT_NONEMPTYSTRING: 210 { 211 v->asString(*((QString *)(pFmtArray->pContainer))); 212 bool bDoReturn = false; 213 if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING) 214 { 215 v = pVariantList->next(); 216 while(v) 217 { 218 *((QString *)(pFmtArray->pContainer)) += QChar(' '); 219 v->appendAsString(*((QString *)(pFmtArray->pContainer))); 220 v = pVariantList->next(); 221 } 222 bDoReturn = true; 223 } 224 if(((QString *)(pFmtArray->pContainer))->isEmpty()) 225 { 226 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); 227 pContext->error(szError); 228 return false; 229 } 230 if(bDoReturn) 231 return true; 232 } 233 break; 234 case KVS_PT_CSTRING: 235 { 236 QString tmp; 237 v->asString(tmp); 238 if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING) 239 { 240 v = pVariantList->next(); 241 while(v) 242 { 243 *((QByteArray *)(pFmtArray->pContainer)) += ' '; 244 v->appendAsString(tmp); 245 v = pVariantList->next(); 246 } 247 *((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8(); 248 return true; 249 } 250 *((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8(); 251 } 252 break; 253 case KVS_PT_NONEMPTYCSTRING: 254 { 255 QString tmp; 256 v->asString(tmp); 257 bool bDoReturn = false; 258 if(pFmtArray->uFlags & KVS_PF_APPENDREMAINING) 259 { 260 v = pVariantList->next(); 261 while(v) 262 { 263 *((QByteArray *)(pFmtArray->pContainer)) += ' '; 264 v->appendAsString(tmp); 265 v = pVariantList->next(); 266 } 267 *((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8(); 268 bDoReturn = true; 269 } 270 *((QByteArray *)(pFmtArray->pContainer)) = tmp.toUtf8(); 271 if(((QByteArray *)(pFmtArray->pContainer))->isEmpty()) 272 { 273 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); 274 pContext->error(szError); 275 return false; 276 } 277 if(bDoReturn) 278 return true; 279 } 280 break; 281 case KVS_PT_INT: 282 if(!v->asInteger(*((kvs_int_t *)(pFmtArray->pContainer)))) 283 { 284 if(!handleParameterTypeError(pContext, pFmtArray, v, "integer")) 285 return false; 286 } 287 break; 288 case KVS_PT_UINT: 289 { 290 kvs_int_t iTmp; 291 if(!v->asInteger(iTmp)) 292 { 293 if(!handleParameterTypeError(pContext, pFmtArray, v, "unsigned integer")) 294 return false; 295 } 296 if(iTmp < 0) 297 { 298 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); 299 pContext->error(szError); 300 return false; 301 } 302 *((kvs_uint_t *)(pFmtArray->pContainer)) = (kvs_uint_t)iTmp; 303 } 304 break; 305 case KVS_PT_DOUBLE: 306 if(!v->asReal(*((kvs_real_t *)(pFmtArray->pContainer)))) 307 { 308 if(!handleParameterTypeError(pContext, pFmtArray, v, "real")) 309 return false; 310 } 311 break; 312 case KVS_PT_HASH: 313 if(!v->isHash()) 314 { 315 if(!handleParameterTypeError(pContext, pFmtArray, v, "hash")) 316 return false; 317 } 318 else 319 { 320 *((KviKvsHash **)(pFmtArray->pContainer)) = v->hash(); 321 } 322 break; 323 case KVS_PT_ARRAYCAST: 324 v->castToArray((KviKvsArrayCast *)(pFmtArray->pContainer)); 325 break; 326 case KVS_PT_ARRAY: 327 if(!v->isArray()) 328 { 329 if(!handleParameterTypeError(pContext, pFmtArray, v, "array")) 330 return false; 331 } 332 else 333 { 334 *((KviKvsArray **)(pFmtArray->pContainer)) = v->array(); 335 } 336 break; 337 case KVS_PT_BOOL: 338 // this never fails: anything is converted to a boolean 339 *((bool *)(pFmtArray->pContainer)) = v->asBoolean(); 340 break; 341 case KVS_PT_VARIANT: 342 *((KviKvsVariant **)(pFmtArray->pContainer)) = v; 343 break; 344 case KVS_PT_HOBJECT: 345 if(!v->asHObject(*((kvs_hobject_t *)(pFmtArray->pContainer)))) 346 { 347 if(!handleParameterTypeError(pContext, pFmtArray, v, "hobject")) 348 return false; 349 } 350 break; 351 case KVS_PT_IGNORE: 352 // ignore 353 break; 354 default: 355 qDebug("Internal error in KviKvsParameterProcessor::processAsParameters(): unknown parameter type %d", pFmtArray->uType); 356 return false; 357 break; 358 } 359 pFmtArray++; 360 v = pVariantList->next(); 361 } 362 return true; 363 } 364 }; 365