bool KviKvsTreeNodeSpecialCommandForeach::execute(KviKvsRunTimeContext * c) { KviKvsVariantList l; l.setAutoDelete(true); if(!m_pIterationData->evaluate(c,&l)) return false; KviKvsSwitchList swl; if(m_pSwitches) { if(!(m_pSwitches->evaluate(c,&swl))) return false; } bool bIncludeEmptyScalars = swl.find('a',"all") != 0; for(KviKvsVariant * pArg = l.first(); pArg; pArg = l.next()) { switch(pArg->type()) { case KviKvsVariantData::Array: { unsigned int uCnt = pArg->array()->size(); unsigned int idx = 0; while(idx < uCnt) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; KviKvsVariant * pOne = pArg->array()->at(idx); if(pOne) { if(bIncludeEmptyScalars || (!pOne->isEmpty())) { v->result()->copyFrom(*pOne); } else { delete v; // we're done with it for this iteration idx++; continue; } } else { if(bIncludeEmptyScalars) { v->result()->setNothing(); } else { delete v; // we're done with it for this iteration idx++; continue; } } delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); idx++; continue; } return false; // propagate the false return value } idx++; } } break; case KviKvsVariantData::Hash: { KviKvsHashIterator it(*(pArg->hash()->dict())); while(KviKvsVariant * pOne = it.current()) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; if(bIncludeEmptyScalars || (!pOne->isEmpty())) { v->result()->copyFrom(*pOne); } else { delete v; // we're done with it for this iteration ++it; continue; } delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); ++it; continue; } return false; // propagate the false return value } ++it; } } break; default: if(bIncludeEmptyScalars || (!pArg->isEqualToNothing())) { // we evaluate this each time (as it may actually be killed at each iteration) // FIXME: maybe some kind of reference counting or a observer pattern might be a bit more efficient here // (but might be far less efficient everywhere else...) KviKvsRWEvaluationResult * v = m_pIterationVariable->evaluateReadWrite(c); if(!v) return false; v->result()->copyFrom(*pArg); delete v; // we're done with it for this iteration if(!m_pLoop->execute(c)) { if(c->error()) return false; // break allowed! if(c->breakPending()) { c->handleBreak(); return true; } if(c->continuePending()) { c->handleContinue(); continue; } return false; // propagate the false return value } } break; } } 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; }