in main/extensions/source/ole/unoconversionutilities.hxx [304:611]
void UnoConversionUtilities<T>::variantToAny( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange /* = sal_True */)
{
try
{
HRESULT hr;
bool bFail = false;
bool bCannotConvert = false;
CComVariant var;
// There is no need to support indirect values, since they're not supported by UNO
if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pArg)))) // remove VT_BYREF
throw BridgeRuntimeError(
OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n"
"VariantCopyInd failed for reason : ") + OUString::valueOf(hr));
bool bHandled = convertValueObject( & var, rAny);
if( bHandled)
OSL_ENSURE( rAny.getValueType() == ptype, "type in Value Object must match the type parameter");
if( ! bHandled)
{
// convert into a variant type that is the equivalent to the type
// the sequence expects. Thus variantToAny produces the correct type
// E.g. An Array object contains VT_I4 and the sequence expects shorts
// than the vartype must be changed. The reason is, you can't specify the
// type in JavaScript and the script engine determines the type being used.
switch( ptype.getTypeClass())
{
case TypeClass_CHAR: // could be: new Array( 12, 'w', "w")
if( var.vt == VT_BSTR)
{
if(SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
rAny.setValue( (void*)V_BSTR( &var), ptype);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
}
else
{
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
rAny.setValue((void*) & var.iVal, ptype);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
}
break;
case TypeClass_INTERFACE: // could also be an IUnknown
case TypeClass_STRUCT:
{
rAny = createOleObjectWrapper( & var, ptype);
break;
}
case TypeClass_ENUM:
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I4)))
rAny.setValue((void*) & var.lVal, ptype);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_SEQUENCE:
// There are different ways of receiving a sequence:
// 1: JScript, VARTYPE: VT_DISPATCH
// 2. VBScript simple arraysVT_VARIANT|VT_BYREF the referenced VARIANT contains
// a VT_ARRAY| <type>
// 3. VBScript multi dimensional arrays: VT_ARRAY|VT_BYREF
if( pArg->vt == VT_DISPATCH)
{
dispatchExObject2Sequence( pArg, rAny, ptype);
}
else
{
if ((var.vt & VT_ARRAY) != 0)
{
VARTYPE oleType = ::sal::static_int_cast< VARTYPE, int >( var.vt ^ VT_ARRAY );
Sequence<Any> unoSeq = createOleArrayWrapper( var.parray, oleType, ptype);
Reference<XTypeConverter> conv = getTypeConverter();
if (conv.is())
{
try
{
Any anySeq = makeAny(unoSeq);
Any convAny = conv->convertTo(anySeq, ptype);
rAny = convAny;
}
catch (IllegalArgumentException& e)
{
throw BridgeRuntimeError(
OUSTR("[automation bridge]com.sun.star.lang.IllegalArgumentException "
"in UnoConversionUtilities<T>::variantToAny! Message: ") +
e.Message);
}
catch (CannotConvertException& e)
{
throw BridgeRuntimeError(
OUSTR("[automation bridge]com.sun.star.script.CannotConvertException "
"in UnoConversionUtilities<T>::variantToAny! Message: ") +
e.Message);
}
}
}
}
break;
case TypeClass_VOID:
rAny.setValue(NULL,Type());
break;
case TypeClass_ANY: // Any
// There could be a JScript Array that needs special handling
// If an Any is expected and this Any must contain a Sequence
// then we cannot figure out what element type is required.
// Therefore we convert to Sequence< Any >
if( pArg->vt == VT_DISPATCH && isJScriptArray( pArg))
{
dispatchExObject2Sequence( pArg, rAny,
getCppuType((Sequence<Any>*) 0));
}
else if (pArg->vt == VT_DECIMAL)
{
//Decimal maps to hyper in calls from COM -> UNO
// It does not matter if we create a sal_uInt64 or sal_Int64,
// because the UNO object is called through invocation which
//will do a type conversion if necessary
if (var.decVal.sign == 0)
{
// positive value
variantToAny( & var, rAny, getCppuType( (sal_uInt64*) 0),
bReduceValueRange);
}
else
{
//negative value
variantToAny( & var, rAny, getCppuType( (sal_Int64*) 0),
bReduceValueRange);
}
}
else
{
variantToAny( & var, rAny);
}
break;
case TypeClass_BOOLEAN: // VARIANT could be VARIANT_BOOL or other
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BOOL)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_STRING: // UString
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BSTR)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_FLOAT: // float
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R4)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_DOUBLE: // double
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R8)))
variantToAny(& var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_BYTE: // BYTE
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I1)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_SHORT: // INT16
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_LONG:
if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_I4)))
variantToAny( & var, rAny, bReduceValueRange);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_HYPER:
if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
{
if (var.decVal.Lo64 > SAL_CONST_UINT64(0x8000000000000000)
|| var.decVal.Hi32 > 0
|| var.decVal.scale > 0)
{
bFail = true;
break;
}
sal_Int64 value = var.decVal.Lo64;
if (var.decVal.sign == DECIMAL_NEG)
value |= SAL_CONST_UINT64(0x8000000000000000);
rAny <<= value;
}
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_UNSIGNED_SHORT: // UINT16
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI2)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_UNSIGNED_LONG:
if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI4)))
variantToAny( & var, rAny, bReduceValueRange);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_UNSIGNED_HYPER:
if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
{
if (var.decVal.Hi32 > 0 || var.decVal.scale > 0)
{
bFail = true;
break;
}
rAny <<= var.decVal.Lo64;
}
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
case TypeClass_TYPE:
if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_UNKNOWN)))
variantToAny( & var, rAny);
else if (hr == DISP_E_TYPEMISMATCH)
bCannotConvert = true;
else
bFail = true;
break;
default:
// case TypeClass_SERVICE: break; // meta construct
// case TypeClass_TYPEDEF: break;
// case TypeClass_UNION: break;
// case TypeClass_MODULE: break; // module
// case TypeClass_EXCEPTION: break;
// case TypeClass_ARRAY: break; // there's no Array at the moment
// case TypeClass_UNKNOWN: break;
bCannotConvert = true;
break;
}
}
if (bCannotConvert)
throw CannotConvertException(
OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n"
"Cannot convert the value of vartype :\"") +
OUString::valueOf((sal_Int32) var.vt) +
OUSTR("\" to the expected UNO type of type class: ") +
OUString::valueOf((sal_Int32) ptype.getTypeClass()),
0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
if (bFail)
throw IllegalArgumentException(
OUSTR("[automation bridge]UnoConversionUtilities<T>:variantToAny\n"
"The provided VARIANT of type\" ") + OUString::valueOf((sal_Int32) var.vt) +
OUSTR("\" is inappropriate for conversion!"), Reference<XInterface>(), -1);
}
catch (CannotConvertException &)
{
throw;
}
catch (IllegalArgumentException &)
{
throw;
}
catch (BridgeRuntimeError &)
{
throw;
}
catch (Exception & e)
{
throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
"UnoConversionUtilities<T>::variantToAny ! Message : \n") +
e.Message);
}
catch(...)
{
throw BridgeRuntimeError(
OUSTR("[automation bridge] unexpected exception in "
"UnoConversionUtilities<T>::variantToAny !"));
}
}