int qspAutoConvertCompare(QSPVariant *v1, QSPVariant *v2) { int res; if (v1->IsStr != v2->IsStr) { if (v2->IsStr) { if (qspIsCanConvertToNum(v2)) qspConvertVariantTo(v2, QSP_FALSE); else qspConvertVariantTo(v1, QSP_TRUE); } else { if (qspIsCanConvertToNum(v1)) qspConvertVariantTo(v1, QSP_FALSE); else qspConvertVariantTo(v2, QSP_TRUE); } } if (v1->IsStr) res = QSP_STRCOLL(QSP_PSTR(v1), QSP_PSTR(v2)); else res = (QSP_PNUM(v1) > QSP_PNUM(v2) ? 1 : (QSP_PNUM(v1) < QSP_PNUM(v2) ? -1 : 0)); return res; }
void qspCopyVariant(QSPVariant *dest, QSPVariant *src) { if (dest->IsStr = src->IsStr) QSP_PSTR(dest) = qspGetNewText(QSP_PSTR(src), -1); else QSP_PNUM(dest) = QSP_PNUM(src); }
static void qspSetVar(QSP_CHAR *name, QSPVariant *val, QSP_CHAR op) { QSPVariant oldVal; QSPVar *var; int index; if (!(var = qspGetVarData(name, QSP_TRUE, &index))) return; if (op == QSP_EQUAL[0]) { if (qspConvertVariantTo(val, *name == QSP_STRCHAR[0])) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } qspSetVarValueByReference(var, index, val); } else if (op == QSP_ADD[0]) { oldVal = qspGetVarValueByReference(var, index, *name == QSP_STRCHAR[0]); if (oldVal.IsStr && val->IsStr) QSP_STR(oldVal) = qspGetAddText(QSP_STR(oldVal), QSP_PSTR(val), -1, -1); else if (qspIsCanConvertToNum(&oldVal) && qspIsCanConvertToNum(val)) { qspConvertVariantTo(&oldVal, QSP_FALSE); qspConvertVariantTo(val, QSP_FALSE); QSP_NUM(oldVal) += QSP_PNUM(val); qspConvertVariantTo(&oldVal, *name == QSP_STRCHAR[0]); } else { if (!oldVal.IsStr) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } qspConvertVariantTo(val, QSP_TRUE); QSP_STR(oldVal) = qspGetAddText(QSP_STR(oldVal), QSP_PSTR(val), -1, -1); } qspSetVarValueByReference(var, index, &oldVal); if (oldVal.IsStr) free(QSP_STR(oldVal)); } else if (qspIsInList(QSP_SUB QSP_DIV QSP_MUL, op)) { if (qspConvertVariantTo(val, QSP_FALSE)) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } oldVal = qspGetVarValueByReference(var, index, *name == QSP_STRCHAR[0]); if (qspConvertVariantTo(&oldVal, QSP_FALSE)) { qspSetError(QSP_ERR_TYPEMISMATCH); free(QSP_STR(oldVal)); return; } if (op == QSP_SUB[0]) QSP_NUM(oldVal) -= QSP_PNUM(val); else if (op == QSP_DIV[0]) { if (!QSP_PNUM(val)) { qspSetError(QSP_ERR_DIVBYZERO); return; } QSP_NUM(oldVal) /= QSP_PNUM(val); } else QSP_NUM(oldVal) *= QSP_PNUM(val); qspConvertVariantTo(&oldVal, *name == QSP_STRCHAR[0]); qspSetVarValueByReference(var, index, &oldVal); if (oldVal.IsStr) free(QSP_STR(oldVal)); } }
QSP_BOOL qspConvertVariantTo(QSPVariant *val, QSP_BOOL isToString) { int num; QSP_CHAR buf[12]; QSP_BOOL isValid; if (val->IsStr) { if (!isToString) { num = qspStrToNum(QSP_PSTR(val), &isValid); if (!isValid) return QSP_TRUE; free(QSP_PSTR(val)); QSP_PNUM(val) = num; val->IsStr = QSP_FALSE; } } else if (isToString) { QSP_PSTR(val) = qspGetNewText(qspNumToStr(buf, QSP_PNUM(val)), -1); val->IsStr = QSP_TRUE; } return QSP_FALSE; }
void qspApplyResult(QSPVar *varRes, QSPVariant *res) { QSP_CHAR *text; if (varRes->ValsCount) { if (text = varRes->Values[0].Str) { res->IsStr = QSP_TRUE; QSP_PSTR(res) = qspGetNewText(text, -1); } else { res->IsStr = QSP_FALSE; QSP_PNUM(res) = varRes->Values[0].Num; } } else { res->IsStr = QSP_TRUE; QSP_PSTR(res) = qspGetNewText(QSP_FMT(""), 0); } }
int qspArrayPos(QSP_CHAR *varName, QSPVariant *val, int ind, QSP_BOOL isRegExp) { int num, count; QSPVar *var; QSP_CHAR *str; regex_t *regExp; QSP_BOOL isString; if (!(var = qspVarReferenceWithType(varName, QSP_FALSE, &isString))) return -1; if (qspConvertVariantTo(val, isRegExp || isString)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (isRegExp) { regExp = qspRegExpGetCompiled(QSP_PSTR(val)); if (!regExp) return -1; } count = var->ValsCount; if (ind < 0) ind = 0; else if (ind > count) ind = count; while (ind <= count) { if (val->IsStr) { if (!(ind < count && (str = var->Values[ind].Str))) str = QSP_FMT(""); if (isRegExp) { if (qspRegExpStrMatch(regExp, str)) return ind; } else if (!qspStrsComp(str, QSP_PSTR(val))) return ind; } else { num = (ind < count ? var->Values[ind].Num : 0); if (num == QSP_PNUM(val)) return ind; } ++ind; } return -1; }
void qspSetVarValueByReference(QSPVar *var, int ind, QSPVariant *val) { int count, oldCount = var->ValsCount; if (ind >= oldCount) { count = var->ValsCount = ind + 1; var->Values = (QSPVarValue *)realloc(var->Values, count * sizeof(QSPVarValue)); while (oldCount < count) { var->Values[oldCount].Num = 0; var->Values[oldCount].Str = nullptr; ++oldCount; } } if (ind >= 0) { if (val->IsStr) var->Values[ind].Str = qspGetAddText(var->Values[ind].Str, QSP_PSTR(val), 0, -1); else var->Values[ind].Num = QSP_PNUM(val); } }
int qspArrayPos(QSPVariant *args, int argsCount, QSP_BOOL isRegExp) { int num, count, ind; QSPVar *var; QSPVariant *val; QSP_CHAR *str; OnigUChar *tempBeg, *tempEnd; regex_t *onigExp; OnigErrorInfo onigInfo; QSP_BOOL isString; if (qspConvertVariantTo(args, argsCount == 2)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (argsCount == 2) { str = QSP_STR(args[0]); ind = 0; val = args + 1; } else { qspConvertVariantTo(args + 1, QSP_TRUE); str = QSP_STR(args[1]); ind = QSP_NUM(args[0]); val = args + 2; if (ind < 0) ind = 0; } if (!(var = qspVarReferenceWithType(str, QSP_FALSE, &isString))) return -1; if (qspConvertVariantTo(val, isRegExp || isString)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (isRegExp) { tempBeg = (OnigUChar *)QSP_PSTR(val); tempEnd = (OnigUChar *)qspStrEnd(QSP_PSTR(val)); if (onig_new(&onigExp, tempBeg, tempEnd, ONIG_OPTION_DEFAULT, QSP_ONIG_ENC, ONIG_SYNTAX_PERL_NG, &onigInfo)) { qspSetError(QSP_ERR_INCORRECTREGEXP); return -1; } } count = var->ValsCount; if (ind > count) ind = count; while (ind <= count) { if (val->IsStr) { if (!(ind < count && (str = var->Values[ind].Str))) str = QSP_FMT(""); if (isRegExp) { tempBeg = (OnigUChar *)str; tempEnd = (OnigUChar *)qspStrEnd(str); if (onig_match(onigExp, tempBeg, tempEnd, tempBeg, 0, ONIG_OPTION_NONE) == tempEnd - tempBeg) { onig_free(onigExp); return ind; } } else if (!qspStrsComp(str, QSP_PSTR(val))) return ind; } else { num = (ind < count ? var->Values[ind].Num : 0); if (num == QSP_PNUM(val)) return ind; } ++ind; } if (isRegExp) onig_free(onigExp); return -1; }