Skip to content

Commit 0cf2c1b

Browse files
feature (new Variant) Type conversions for one dimension arrays
1 parent 6718780 commit 0cf2c1b

File tree

1 file changed

+76
-12
lines changed

1 file changed

+76
-12
lines changed

ext/com_dotnet/com_variant.c

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -457,30 +457,94 @@ PHP_METHOD(variant, __construct)
457457
/* If already an array and VT_ARRAY is passed then:
458458
- if only VT_ARRAY passed then do not perform a conversion
459459
- if VT_ARRAY plus other type passed then perform conversion
460-
but will probably fail (original behavior)
461460
*/
462-
if ((vt & VT_ARRAY) && (V_VT(&obj->v) & VT_ARRAY)) {
463-
zend_long orig_vt = vt;
464461

465-
vt &= ~VT_ARRAY;
466-
if (vt) {
467-
vt = orig_vt;
462+
res = S_OK;
463+
SAFEARRAYBOUND Bound;
464+
465+
if (!(V_VT(&obj->v) & VT_BYREF) && //not supported
466+
(vt & ~VT_ARRAY) && //new variant have some type except VT_ARRAY
467+
(V_VT(&obj->v) & VT_ARRAY) && //old variant is array
468+
SafeArrayGetDim(V_ARRAY(&obj->v)) == 1 && //old array have one dimension
469+
SUCCEEDED(res = SafeArrayGetLBound(V_ARRAY(&obj->v), 1, &Bound.lLbound)) &&
470+
SUCCEEDED(res = SafeArrayGetUBound(V_ARRAY(&obj->v), 1, &Bound.cElements)))
471+
{
472+
473+
zend_long need_vt = vt & ~VT_ARRAY;
474+
zend_long old_vt = V_VT(&obj->v) & ~VT_ARRAY;
475+
476+
Bound.cElements -= Bound.lLbound - 1;
477+
SAFEARRAY * newArray = SafeArrayCreate(need_vt, 1, &Bound);
478+
479+
if (newArray) {
480+
481+
for (LONG i = Bound.lLbound; i < Bound.lLbound + Bound.cElements; i++) {
482+
VARIANT temp;
483+
VariantInit(&temp);
484+
if (old_vt != VT_VARIANT)
485+
V_VT(&temp) = old_vt;
486+
487+
switch (old_vt) {
488+
case VT_VARIANT:
489+
res = SafeArrayGetElement(V_ARRAY(&obj->v), &i, &temp); break;
490+
default:
491+
res = SafeArrayGetElement(V_ARRAY(&obj->v), &i, &V_I8(&temp)); break;
492+
}
493+
494+
if (FAILED(res))
495+
break;
496+
497+
if (FAILED(res = VariantChangeType(&temp, &temp, 0, (VARTYPE)need_vt))) {
498+
VariantClear(&temp);
499+
break;
500+
}
501+
502+
switch (need_vt) {
503+
case VT_VARIANT:
504+
res = SafeArrayPutElement(newArray, &i, &temp); break;
505+
case VT_DISPATCH:
506+
case VT_UNKNOWN:
507+
case VT_BSTR:
508+
res = SafeArrayPutElement(newArray, &i, V_DISPATCH(&temp)); break;
509+
default:
510+
res = SafeArrayPutElement(newArray, &i, &V_I8(&temp));
511+
break;
512+
}
513+
514+
VariantClear(&temp);
515+
if (FAILED(res))
516+
break;
517+
}
518+
519+
if (SUCCEEDED(res)) {
520+
SafeArrayDestroy(V_ARRAY(&obj->v));
521+
V_ARRAY(&obj->v) = newArray;
522+
V_VT(&obj->v) = vt | VT_ARRAY; //Set VT_ARRAY automatically
523+
vt = VT_EMPTY;//No need change type any more
524+
}
525+
else
526+
SafeArrayDestroy(newArray);
468527
}
469528
}
470529

471-
if (vt) {
530+
/** Try to system conversion function if our array conversion
531+
* function don't do conversion before (vt is not VT_EMPTY)
532+
* and wasn't tried it (SUCCEEDED(res))
533+
*/
534+
535+
if (SUCCEEDED(res) && vt) {
472536
res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
537+
}
473538

474-
if (FAILED(res)) {
475-
char *werr, *msg;
539+
if (FAILED(res)) {
540+
char *werr, *msg;
476541

477542
werr = php_win32_error_to_msg(res);
478543
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
479544
php_win32_error_msg_free(werr);
480545

481-
php_com_throw_exception(res, msg);
482-
efree(msg);
483-
}
546+
php_com_throw_exception(res, msg);
547+
efree(msg);
484548
}
485549
}
486550

0 commit comments

Comments
 (0)