void VirtualValue::setTo(const Variant& value, StringCache& stringcache) { if ( value.isInt() ) { setNumber(value.asInt()); } else if ( value.isReal() ) { setReal(value.asReal()); } else if ( value.isBool() ) { setBoolean(value.asBool()); } else if ( value.isChar() ) { setChar(value.asChar()); } else if ( value.isString() ) { setString(stringcache.lookup(value.asString())); } else { mKind = eEmpty; } }
void PnData::write(const Variant& value) { switch (value.getType()) { case qpid::types::VAR_VOID: pn_data_put_null(data); break; case qpid::types::VAR_BOOL: pn_data_put_bool(data, value.asBool()); break; case qpid::types::VAR_UINT64: pn_data_put_ulong(data, value.asUint64()); break; case qpid::types::VAR_INT64: pn_data_put_long(data, value.asInt64()); break; case qpid::types::VAR_DOUBLE: pn_data_put_double(data, value.asDouble()); break; case qpid::types::VAR_STRING: pn_data_put_string(data, str(value.asString())); break; case qpid::types::VAR_MAP: write(value.asMap()); break; case qpid::types::VAR_LIST: write(value.asList()); break; default: break; } }
bool JsAgent::onHandleReturn(const Variant& varRet) { if(!varRet.isObject()) { Debug::println("JsAgent::onHandleReturn> NPN_Invoke did not return an object"); return false; } NPObject* pReturn = varRet.asObject(); Variant varFlag; if(!NPN_GetProperty(getNPP(), pReturn, methods.index0, varFlag.ptr())) { Debug::println("JsAgent::onHandleReturn> ret[0] failed"); return false; } Variant varResult; if(!NPN_GetProperty(getNPP(), pReturn, methods.index1, varResult.ptr())) { Debug::println("JsAgent::onHandleReturn> ret[1] failed"); return false; } if(!varFlag.isBool()) { Debug::println("JsAgent::onHandleReturn> flag was not bool"); return false; } ReturnMessage retMsg; retMsg.isException = varFlag.asBool(); std::string strRet = varResult.toString(getNPP()); if(retMsg.isException) { Debug::println("JsAgent::onHandleReturn> Exception: '%s'", strRet.c_str()); NPN_SetException(this, strRet.c_str()); } else { Debug::println("JsAgent::onHandleReturn> returned: %s", strRet.c_str()); } if(!wrapLocalValue(varResult, retMsg.value)) { Debug::println("JsAgent::onHandleReturn> wrapLocalValue() failed"); return false; } ArchiveWriter<Channel> ar(*m_channel); if(!Message::send(retMsg, ar)) { Debug::println("JsAgent::onHandleReturn> Message::send() failed"); return false; } return true; }
bool JsAgent::wrapLocalValue(const Variant& var, JsValue& value) { if(var.isInt()) { value.tag = VT_Int; value.intValue = var.asInt(); } else if(var.isString()) { value.tag = VT_String; value.strValue = var.asString(); } else if(var.isObject()) { NPObject* pObject = var.asObject(); if(pObject->_class == GetNPClass<JsObjectWrapper>()) { uint32_t id = 0; value.tag = VT_Object; value.intValue = id; } else { uint32_t id = getRefId(pObject); value.tag = VT_JsObject; value.intValue = id; } } else if(var.isNull()) { value.tag = VT_Null; } else if(var.isBool()) { value.tag = VT_Bool; value.boolValue = var.asBool(); } else if(var.isDouble()) { value.tag = VT_Double; value.doubleValue = var.asDouble(); } else if(var.isVoid()) { value.tag = VT_Void; } else { return false; } return true; }
void encode(const Variant& value, qpid::framing::Buffer& buffer) { switch (value.getType()) { case VAR_VOID: buffer.putOctet(0xf0); break; case VAR_BOOL: buffer.putOctet(0x08); buffer.putOctet(value.asBool()); break; case VAR_INT8: buffer.putOctet(0x01); buffer.putInt8(value.asInt8()); break; case VAR_UINT8: buffer.putOctet(0x02); buffer.putOctet(value.asUint8()); break; case VAR_INT16: buffer.putOctet(0x11); buffer.putInt16(value.asInt16()); break; case VAR_UINT16: buffer.putOctet(0x12); buffer.putShort(value.asUint16()); break; case VAR_INT32: buffer.putOctet(0x21); buffer.putInt32(value.asInt32()); break; case VAR_UINT32: buffer.putOctet(0x22); buffer.putLong(value.asUint32()); break; case VAR_FLOAT: buffer.putOctet(0x23); buffer.putFloat(value.asFloat()); break; case VAR_INT64: buffer.putOctet(0x31); buffer.putInt64(value.asInt64()); break; case VAR_UINT64: buffer.putOctet(0x32); buffer.putLongLong(value.asUint64()); break; case VAR_DOUBLE: buffer.putOctet(0x33); buffer.putDouble(value.asDouble()); break; case VAR_UUID: buffer.putOctet(0x48); buffer.putBin128(value.asUuid().data()); break; case VAR_MAP: buffer.putOctet(0xa8); encode(value.asMap(), encodedSize(value.asMap()), buffer); break; case VAR_LIST: buffer.putOctet(0xa9); encode(value.asList(), encodedSize(value.asList()), buffer); break; case VAR_STRING: encode(value.getString(), value.getEncoding(), buffer); break; } }
Variant& StackMachine::evaluate(const VariableStore& store, const FunctionRegistry& functions) { reset(); for(const auto& instruction : _instructions) { switch(instruction._opCode) { case NOP: { break; } case PUSH: { _valueStack.emplace(instruction._value); break; } case PUSHVAR: { if(instruction._value.getType() != INT) { CSVSQLDB_THROW(StackMachineException, "expected an INT as variable index"); } int64_t index = instruction._value.asInt(); _valueStack.emplace(store[static_cast<size_t>(index)]); break; } case ADD: case SUB: case DIV: case MOD: case MUL: case EQ: case NEQ: case IS: case ISNOT: case GT: case GE: case LT: case LE: case AND: case OR: case CONCAT: { const Variant lhs(getNextValue()); Variant& rhs(getTopValue()); rhs = binaryOperation(mapOpCodeToBinaryOperationType(instruction._opCode), lhs, rhs); break; } case NOT: { Variant& rhs(getTopValue()); rhs = unaryOperation(OP_NOT, BOOLEAN, rhs); break; } case PLUS: { // this is a nop, as the value will not change, so just leave it on the stack break; } case MINUS: { Variant& rhs = getTopValue(); rhs = unaryOperation(OP_MINUS, rhs.getType(), rhs); break; } case BETWEEN: { const Variant lhs = getNextValue(); const Variant from = getNextValue(); Variant& to = getTopValue(); Variant result(BOOLEAN); if(not(lhs.isNull() || from.isNull() || to.isNull())) { if(binaryOperation(OP_GE, to, from).asBool()) { result = binaryOperation(OP_GE, lhs, from); if(result.asBool()) { result = binaryOperation(OP_LE, lhs, to); } } else { result = binaryOperation(OP_GE, lhs, to); if(result.asBool()) { result = binaryOperation(OP_LE, lhs, from); } } } to = result; break; } case FUNC: { if(instruction._value.getType() != STRING) { CSVSQLDB_THROW(StackMachineException, "expected a string as variable name"); } std::string funcname = instruction._value.asString(); Function::Ptr func = functions.getFunction(funcname); if(!func) { CSVSQLDB_THROW(StackMachineException, "function '" << funcname << "' not found"); } Variants parameter; size_t count = func->getParameterTypes().size(); for(const auto& param : func->getParameterTypes()) { Variant v = getNextValue(); if(param != v.getType()) { try { v = unaryOperation(OP_CAST, param, v); } catch(const std::exception&) { CSVSQLDB_THROW(StackMachineException, "calling function '" << funcname << "' with wrong parameter"); } } parameter.emplace(parameter.end(), v); --count; } if(count) { CSVSQLDB_THROW(StackMachineException, "too much parameters for function '" << funcname << "'"); } _valueStack.emplace(func->call(parameter)); break; } case CAST: { Variant& rhs = getTopValue(); rhs = unaryOperation(OP_CAST, instruction._value.getType(), rhs); break; } case IN: { size_t count = static_cast<size_t>(instruction._value.asInt()); const Variant lhs = getNextValue(); bool found(false); for(size_t n = 0; n < count; ++n) { Variant result = binaryOperation(OP_EQ, lhs, getNextValue()); if(result.asBool()) { found = true; ++n; for(; n < count; ++n) { // remove rest of the values from stack _valueStack.pop(); } break; } } if(found) { _valueStack.emplace(Variant(true)); } else { _valueStack.emplace(Variant(false)); } break; } case LIKE: { if(!instruction._r) { CSVSQLDB_THROW(StackMachineException, "expected a regexp in LIKE expression"); } Variant lhs = getTopValue(); if(lhs.getType() != STRING) { lhs = unaryOperation(OP_CAST, STRING, lhs); CSVSQLDB_THROW(StackMachineException, "can only do like operations on strings"); } if(instruction._r->match(lhs.asString())) { _valueStack.emplace(Variant(true)); } else { _valueStack.emplace(Variant(false)); } break; } } } return _valueStack.top(); }