mirror of
https://github.com/php/php-src.git
synced 2024-11-24 02:15:04 +08:00
6df5d5ba20
Not yet complete, but should work for most people.
847 lines
21 KiB
C
847 lines
21 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 4 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2003 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.0 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_0.txt. |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Author: Wez Furlong <wez@thebrainroom.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "php.h"
|
|
#include "php_ini.h"
|
|
#include "ext/standard/info.h"
|
|
#include "php_com_dotnet.h"
|
|
#include "php_com_dotnet_internal.h"
|
|
|
|
PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
|
|
{
|
|
OLECHAR *olestring;
|
|
php_com_dotnet_object *obj;
|
|
|
|
switch (Z_TYPE_P(z)) {
|
|
case IS_NULL:
|
|
V_VT(v) = VT_NULL;
|
|
break;
|
|
|
|
case IS_BOOL:
|
|
V_VT(v) = VT_BOOL;
|
|
V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
break;
|
|
|
|
case IS_OBJECT:
|
|
if (php_com_is_valid_object(z TSRMLS_CC)) {
|
|
obj = CDNO_FETCH(z);
|
|
if (V_VT(&obj->v) == VT_DISPATCH) {
|
|
/* pass the underlying object */
|
|
V_VT(v) = VT_DISPATCH;
|
|
if (V_DISPATCH(&obj->v)) {
|
|
IDispatch_AddRef(V_DISPATCH(&obj->v));
|
|
}
|
|
V_DISPATCH(v) = V_DISPATCH(&obj->v);
|
|
} else {
|
|
/* pass the variant by reference */
|
|
V_VT(v) = VT_VARIANT | VT_BYREF;
|
|
V_VARIANTREF(v) = &obj->v;
|
|
}
|
|
} else {
|
|
/* TODO: export the object using our COM wrapper */
|
|
V_VT(v) = VT_NULL;
|
|
}
|
|
break;
|
|
|
|
case IS_ARRAY:
|
|
V_VT(v) = VT_NULL;
|
|
/* TODO: map as safe array ? */
|
|
break;
|
|
|
|
case IS_LONG:
|
|
V_VT(v) = VT_I4;
|
|
V_I4(v) = Z_LVAL_P(z);
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
V_VT(v) = VT_R8;
|
|
V_R8(v) = Z_DVAL_P(z);
|
|
break;
|
|
|
|
case IS_STRING:
|
|
V_VT(v) = VT_BSTR;
|
|
olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage TSRMLS_CC);
|
|
V_BSTR(v) = SysAllocStringByteLen((char*)olestring, Z_STRLEN_P(z) * sizeof(OLECHAR));
|
|
efree(olestring);
|
|
break;
|
|
|
|
case IS_RESOURCE:
|
|
case IS_CONSTANT:
|
|
case IS_CONSTANT_ARRAY:
|
|
default:
|
|
V_VT(v) = VT_NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC)
|
|
{
|
|
OLECHAR *olestring = NULL;
|
|
int ret = SUCCESS;
|
|
SYSTEMTIME systime;
|
|
struct tm tmv;
|
|
php_com_dotnet_object *obj;
|
|
|
|
switch (V_VT(v)) {
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
case VT_VOID:
|
|
ZVAL_NULL(z);
|
|
break;
|
|
case VT_UI1:
|
|
ZVAL_LONG(z, (long)V_UI1(v));
|
|
break;
|
|
case VT_I1:
|
|
ZVAL_LONG(z, (long)V_I1(v));
|
|
break;
|
|
case VT_UI2:
|
|
ZVAL_LONG(z, (long)V_UI2(v));
|
|
break;
|
|
case VT_I2:
|
|
ZVAL_LONG(z, (long)V_I2(v));
|
|
break;
|
|
case VT_UI4: /* TODO: promote to double if large? */
|
|
ZVAL_LONG(z, (long)V_UI4(v));
|
|
break;
|
|
case VT_I4:
|
|
ZVAL_LONG(z, (long)V_I4(v));
|
|
break;
|
|
case VT_INT:
|
|
ZVAL_LONG(z, V_INT(v));
|
|
break;
|
|
case VT_UINT: /* TODO: promote to double if large? */
|
|
ZVAL_LONG(z, (long)V_UINT(v));
|
|
break;
|
|
case VT_R4:
|
|
ZVAL_DOUBLE(z, (double)V_R4(v));
|
|
break;
|
|
case VT_R8:
|
|
ZVAL_DOUBLE(z, V_R8(v));
|
|
break;
|
|
case VT_BOOL:
|
|
ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0);
|
|
break;
|
|
case VT_BSTR:
|
|
olestring = V_BSTR(v);
|
|
if (olestring) {
|
|
Z_TYPE_P(z) = IS_STRING;
|
|
Z_STRVAL_P(z) = php_com_olestring_to_string(olestring,
|
|
&Z_STRLEN_P(z), codepage TSRMLS_CC);
|
|
olestring = NULL;
|
|
}
|
|
break;
|
|
case VT_UNKNOWN:
|
|
if (V_UNKNOWN(v) != NULL) {
|
|
IDispatch *disp;
|
|
|
|
if (SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, &disp))) {
|
|
php_com_wrap_dispatch(z, disp, codepage TSRMLS_CC);
|
|
IDispatch_Release(disp);
|
|
} else {
|
|
ret = FAILURE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_DISPATCH:
|
|
if (V_DISPATCH(v) != NULL) {
|
|
php_com_wrap_dispatch(z, V_DISPATCH(v), codepage TSRMLS_CC);
|
|
}
|
|
break;
|
|
|
|
case VT_VARIANT:
|
|
default:
|
|
php_com_wrap_variant(z, v, codepage TSRMLS_CC);
|
|
}
|
|
|
|
if (olestring) {
|
|
efree(olestring);
|
|
}
|
|
|
|
if (ret == FAILURE) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->zval: conversion from 0x%x ret=%d", V_VT(v), ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* {{{ com_variant_create_instance - ctor for new VARIANT() */
|
|
PHP_FUNCTION(com_variant_create_instance)
|
|
{
|
|
VARTYPE vt = VT_EMPTY;
|
|
long codepage = CP_ACP;
|
|
zval *object = getThis();
|
|
php_com_dotnet_object *obj;
|
|
zval *zvalue = NULL;
|
|
HRESULT res;
|
|
|
|
if (ZEND_NUM_ARGS() == 0) {
|
|
/* just leave things as-is - an empty variant */
|
|
return;
|
|
}
|
|
|
|
obj = CDNO_FETCH(object);
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"z!|ll", &zvalue, &vt, &codepage)) {
|
|
php_com_throw_exception("Invalid arguments" TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
if (ZEND_NUM_ARGS() == 3) {
|
|
obj->code_page = codepage;
|
|
}
|
|
|
|
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
|
|
|
|
if (ZEND_NUM_ARGS() >= 2) {
|
|
|
|
res = VariantChangeType(&obj->v, &obj->v, 0, vt);
|
|
|
|
if (FAILED(res)) {
|
|
char *werr, *msg;
|
|
|
|
werr = php_win_err(res);
|
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
|
LocalFree(werr);
|
|
|
|
php_com_throw_exception(msg TSRMLS_CC);
|
|
efree(msg);
|
|
}
|
|
}
|
|
|
|
if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) {
|
|
ITypeInfo_Release(obj->typeinfo);
|
|
obj->typeinfo = NULL;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto void variant_set(object variant, mixed value)
|
|
Assigns a new value for a variant object (like "set" in VB) */
|
|
PHP_FUNCTION(variant_set)
|
|
{
|
|
zval *zobj, *zvalue = NULL;
|
|
php_com_dotnet_object *obj;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"Oz!", &zobj, php_com_variant_class_entry, &zvalue)) {
|
|
return;
|
|
}
|
|
|
|
obj = CDNO_FETCH(zobj);
|
|
|
|
/* dtor the old value */
|
|
if (obj->typeinfo) {
|
|
ITypeInfo_Release(obj->typeinfo);
|
|
obj->typeinfo = NULL;
|
|
}
|
|
|
|
VariantClear(&obj->v);
|
|
|
|
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
|
|
}
|
|
/* }}} */
|
|
|
|
enum variant_binary_opcode {
|
|
VOP_ADD, VOP_CAT, VOP_SUB, VOP_MUL, VOP_AND, VOP_DIV,
|
|
VOP_EQV, VOP_IDIV, VOP_IMP, VOP_MOD, VOP_OR, VOP_POW,
|
|
VOP_XOR
|
|
};
|
|
|
|
enum variant_unary_opcode {
|
|
VOP_ABS, VOP_FIX, VOP_INT, VOP_NEG, VOP_NOT
|
|
};
|
|
|
|
static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
|
{
|
|
VARIANT vres;
|
|
VARIANT left_val, right_val;
|
|
VARIANT *vleft = NULL, *vright = NULL;
|
|
zval *zleft = NULL, *zright = NULL;
|
|
php_com_dotnet_object *obj;
|
|
HRESULT result;
|
|
int codepage = CP_ACP;
|
|
|
|
VariantInit(&left_val);
|
|
VariantInit(&right_val);
|
|
VariantInit(&vres);
|
|
|
|
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zleft, php_com_variant_class_entry,
|
|
&zright, php_com_variant_class_entry)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
obj = CDNO_FETCH(zright);
|
|
vright = &obj->v;
|
|
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "Oz!", &zleft, php_com_variant_class_entry,
|
|
&zright)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
vright = &right_val;
|
|
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
|
|
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "z!O", &zleft, &zright, php_com_variant_class_entry)) {
|
|
obj = CDNO_FETCH(zright);
|
|
vright = &obj->v;
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"z!z!", &zleft, &zright)) {
|
|
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
|
|
vright = &right_val;
|
|
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
|
|
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
switch (op) {
|
|
case VOP_ADD:
|
|
result = VarAdd(vleft, vright, &vres);
|
|
break;
|
|
case VOP_CAT:
|
|
result = VarCat(vleft, vright, &vres);
|
|
break;
|
|
case VOP_SUB:
|
|
result = VarSub(vleft, vright, &vres);
|
|
break;
|
|
case VOP_MUL:
|
|
result = VarMul(vleft, vright, &vres);
|
|
break;
|
|
case VOP_AND:
|
|
result = VarAnd(vleft, vright, &vres);
|
|
break;
|
|
case VOP_DIV:
|
|
result = VarDiv(vleft, vright, &vres);
|
|
break;
|
|
case VOP_EQV:
|
|
result = VarEqv(vleft, vright, &vres);
|
|
break;
|
|
case VOP_IDIV:
|
|
result = VarIdiv(vleft, vright, &vres);
|
|
break;
|
|
case VOP_IMP:
|
|
result = VarImp(vleft, vright, &vres);
|
|
break;
|
|
case VOP_MOD:
|
|
result = VarMod(vleft, vright, &vres);
|
|
break;
|
|
case VOP_OR:
|
|
result = VarOr(vleft, vright, &vres);
|
|
break;
|
|
case VOP_POW:
|
|
result = VarPow(vleft, vright, &vres);
|
|
break;
|
|
case VOP_XOR:
|
|
result = VarXor(vleft, vright, &vres);
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(result)) {
|
|
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
|
|
}
|
|
|
|
VariantClear(&vres);
|
|
VariantClear(&left_val);
|
|
VariantClear(&right_val);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_add(mixed left, mixed right)
|
|
"Adds" two variant values together and returns the result */
|
|
PHP_FUNCTION(variant_add)
|
|
{
|
|
variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_cat(mixed left, mixed right)
|
|
concatenates two variant values together and returns the result */
|
|
PHP_FUNCTION(variant_cat)
|
|
{
|
|
variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_sub(mixed left, mixed right)
|
|
subjects the value of the right variant from the left variant value and returns the result */
|
|
PHP_FUNCTION(variant_sub)
|
|
{
|
|
variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_mul(mixed left, mixed right)
|
|
multiplies the values of the two variants and returns the result */
|
|
PHP_FUNCTION(variant_mul)
|
|
{
|
|
variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_and(mixed left, mixed right)
|
|
performs a bitwise AND operation between two variants and returns the result */
|
|
PHP_FUNCTION(variant_and)
|
|
{
|
|
variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_div(mixed left, mixed right)
|
|
Returns the result from dividing two variants */
|
|
PHP_FUNCTION(variant_div)
|
|
{
|
|
variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_eqv(mixed left, mixed right)
|
|
Performs a bitwise equivalence on two variants */
|
|
PHP_FUNCTION(variant_eqv)
|
|
{
|
|
variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_idiv(mixed left, mixed right)
|
|
Converts variants to operands and then returns the result from dividing them */
|
|
PHP_FUNCTION(variant_idiv)
|
|
{
|
|
variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_imp(mixed left, mixed right)
|
|
Performs a bitwise implication on two variants */
|
|
PHP_FUNCTION(variant_imp)
|
|
{
|
|
variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_mod(mixed left, mixed right)
|
|
Divides two variants and returns only the remainder */
|
|
PHP_FUNCTION(variant_mod)
|
|
{
|
|
variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_or(mixed left, mixed right)
|
|
Performs a logical disjunction on two variants */
|
|
PHP_FUNCTION(variant_or)
|
|
{
|
|
variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_pow(mixed left, mixed right)
|
|
Returns the result of performing the power function with two variants */
|
|
PHP_FUNCTION(variant_pow)
|
|
{
|
|
variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_xor(mixed left, mixed right)
|
|
Performs a logical exclusion on two variants */
|
|
PHP_FUNCTION(variant_xor)
|
|
{
|
|
variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
|
|
{
|
|
VARIANT vres;
|
|
VARIANT left_val;
|
|
VARIANT *vleft = NULL;
|
|
zval *zleft = NULL;
|
|
php_com_dotnet_object *obj;
|
|
HRESULT result;
|
|
int codepage = CP_ACP;
|
|
|
|
VariantInit(&left_val);
|
|
VariantInit(&vres);
|
|
|
|
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "O", &zleft, php_com_variant_class_entry)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"z!", &zleft)) {
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
switch (op) {
|
|
case VOP_ABS:
|
|
result = VarAbs(vleft, &vres);
|
|
break;
|
|
case VOP_FIX:
|
|
result = VarFix(vleft, &vres);
|
|
break;
|
|
case VOP_INT:
|
|
result = VarInt(vleft, &vres);
|
|
break;
|
|
case VOP_NEG:
|
|
result = VarNeg(vleft, &vres);
|
|
break;
|
|
case VOP_NOT:
|
|
result = VarNot(vleft, &vres);
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(result)) {
|
|
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
|
|
}
|
|
|
|
VariantClear(&vres);
|
|
VariantClear(&left_val);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_abs(mixed left)
|
|
Returns the absolute value of a variant */
|
|
PHP_FUNCTION(variant_abs)
|
|
{
|
|
variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_fix(mixed left)
|
|
Returns the ? of a variant */
|
|
PHP_FUNCTION(variant_fix)
|
|
{
|
|
variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_int(mixed left)
|
|
Returns the integer portion of a variant */
|
|
PHP_FUNCTION(variant_int)
|
|
{
|
|
variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_neg(mixed left)
|
|
Performs logical negation on a variant */
|
|
PHP_FUNCTION(variant_neg)
|
|
{
|
|
variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_not(mixed left)
|
|
Performs bitwise not negation on a variant */
|
|
PHP_FUNCTION(variant_not)
|
|
{
|
|
variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_round(mixed left, int decimals)
|
|
Rounds a variant to the specified number of decimal places */
|
|
PHP_FUNCTION(variant_round)
|
|
{
|
|
VARIANT vres;
|
|
VARIANT left_val;
|
|
VARIANT *vleft = NULL;
|
|
zval *zleft = NULL;
|
|
php_com_dotnet_object *obj;
|
|
HRESULT result;
|
|
int codepage = CP_ACP;
|
|
long decimals = 0;
|
|
|
|
VariantInit(&left_val);
|
|
VariantInit(&vres);
|
|
|
|
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zleft, php_com_variant_class_entry, &decimals)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"z!l", &zleft, &decimals)) {
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
if (SUCCEEDED(VarRound(vleft, decimals, &vres))) {
|
|
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
|
|
}
|
|
|
|
VariantClear(&vres);
|
|
VariantClear(&left_val);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto int variant_cmp(mixed left, mixed right [, int lcid [, int flags]])
|
|
Compares two variants */
|
|
PHP_FUNCTION(variant_cmp)
|
|
{
|
|
VARIANT left_val, right_val;
|
|
VARIANT *vleft = NULL, *vright = NULL;
|
|
zval *zleft = NULL, *zright = NULL;
|
|
php_com_dotnet_object *obj;
|
|
HRESULT result;
|
|
int codepage = CP_ACP;
|
|
long lcid = LOCALE_SYSTEM_DEFAULT;
|
|
long flags = 0;
|
|
/* it is safe to ignore the warning for this line; see the comments in com_handlers.c */
|
|
STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
|
|
|
|
VariantInit(&left_val);
|
|
VariantInit(&right_val);
|
|
|
|
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "OO|ll", &zleft, php_com_variant_class_entry,
|
|
&zright, php_com_variant_class_entry, &lcid, &flags)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
obj = CDNO_FETCH(zright);
|
|
vright = &obj->v;
|
|
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "Oz!|ll", &zleft, php_com_variant_class_entry,
|
|
&zright, &lcid, &flags)) {
|
|
obj = CDNO_FETCH(zleft);
|
|
vleft = &obj->v;
|
|
vright = &right_val;
|
|
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
|
|
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "z!O|ll", &zleft, &zright, php_com_variant_class_entry,
|
|
&lcid, &flags)) {
|
|
obj = CDNO_FETCH(zright);
|
|
vright = &obj->v;
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"z!z!|ll", &zleft, &zright, &lcid, &flags)) {
|
|
|
|
vleft = &left_val;
|
|
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
|
|
|
|
vright = &right_val;
|
|
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
|
|
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
ZVAL_LONG(return_value, VarCmp(vleft, vright, lcid, flags));
|
|
|
|
VariantClear(&left_val);
|
|
VariantClear(&right_val);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto int variant_date_to_timestamp(object variant)
|
|
Converts a variant date/time value to unix timestamp */
|
|
PHP_FUNCTION(variant_date_to_timestamp)
|
|
{
|
|
VARIANT vres;
|
|
zval *zleft = NULL;
|
|
php_com_dotnet_object *obj;
|
|
|
|
VariantInit(&vres);
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"O", &zleft, php_com_variant_class_entry)) {
|
|
return;
|
|
}
|
|
obj = CDNO_FETCH(zleft);
|
|
|
|
if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) {
|
|
SYSTEMTIME systime;
|
|
struct tm tmv;
|
|
|
|
VariantTimeToSystemTime(V_DATE(&vres), &systime);
|
|
|
|
memset(&tmv, 0, sizeof(tmv));
|
|
tmv.tm_year = systime.wYear - 1900;
|
|
tmv.tm_mon = systime.wMonth - 1;
|
|
tmv.tm_mday = systime.wDay;
|
|
tmv.tm_hour = systime.wHour;
|
|
tmv.tm_min = systime.wMinute;
|
|
tmv.tm_sec = systime.wSecond;
|
|
tmv.tm_isdst = -1;
|
|
|
|
tzset();
|
|
RETVAL_LONG(mktime(&tmv));
|
|
}
|
|
|
|
VariantClear(&vres);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto object variant_date_from_timestamp(int timestamp)
|
|
Returns a variant date representation of a unix timestamp */
|
|
PHP_FUNCTION(variant_date_from_timestamp)
|
|
{
|
|
int timestamp;
|
|
SYSTEMTIME systime;
|
|
struct tm *tmv;
|
|
VARIANT res;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
|
|
×tamp)) {
|
|
return;
|
|
}
|
|
|
|
VariantInit(&res);
|
|
tmv = gmtime(×tamp);
|
|
memset(&systime, 0, sizeof(systime));
|
|
|
|
systime.wDay = tmv->tm_mday;
|
|
systime.wHour = tmv->tm_hour;
|
|
systime.wMinute = tmv->tm_min;
|
|
systime.wMonth = tmv->tm_mon + 1;
|
|
systime.wSecond = tmv->tm_sec;
|
|
systime.wYear = tmv->tm_year + 1900;
|
|
|
|
V_VT(&res) = VT_DATE;
|
|
SystemTimeToVariantTime(&systime, &V_DATE(&res));
|
|
|
|
php_com_wrap_variant(return_value, &res, CP_ACP TSRMLS_CC);
|
|
|
|
VariantClear(&res);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto int variant_get_type(object variant)
|
|
Returns the VT_XXX type code for a variant */
|
|
PHP_FUNCTION(variant_get_type)
|
|
{
|
|
zval *zobj;
|
|
php_com_dotnet_object *obj;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"O", &zobj, php_com_variant_class_entry)) {
|
|
return;
|
|
}
|
|
obj = CDNO_FETCH(zobj);
|
|
|
|
RETURN_LONG(V_VT(&obj->v));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto void variant_set_type(object variant, int type)
|
|
Convert a variant into another type. Variant is modified "in-place" */
|
|
PHP_FUNCTION(variant_set_type)
|
|
{
|
|
zval *zobj;
|
|
php_com_dotnet_object *obj;
|
|
VARTYPE vt;
|
|
HRESULT res;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"Ol", &zobj, php_com_variant_class_entry, &vt)) {
|
|
return;
|
|
}
|
|
obj = CDNO_FETCH(zobj);
|
|
|
|
res = VariantChangeType(&obj->v, &obj->v, 0, vt);
|
|
|
|
if (SUCCEEDED(res)) {
|
|
if (vt != VT_DISPATCH && obj->typeinfo) {
|
|
ITypeInfo_Release(obj->typeinfo);
|
|
obj->typeinfo = NULL;
|
|
}
|
|
} else {
|
|
char *werr, *msg;
|
|
|
|
werr = php_win_err(res);
|
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
|
LocalFree(werr);
|
|
|
|
php_com_throw_exception(msg TSRMLS_CC);
|
|
efree(msg);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto object variant_cast(object variant, int type)
|
|
Convert a variant into a new variant object of another type */
|
|
PHP_FUNCTION(variant_cast)
|
|
{
|
|
zval *zobj;
|
|
php_com_dotnet_object *obj;
|
|
VARTYPE vt;
|
|
VARIANT vres;
|
|
HRESULT res;
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
|
"Ol", &zobj, php_com_variant_class_entry, &vt)) {
|
|
return;
|
|
}
|
|
obj = CDNO_FETCH(zobj);
|
|
|
|
VariantInit(&vres);
|
|
res = VariantChangeType(&vres, &obj->v, 0, vt);
|
|
|
|
if (SUCCEEDED(res)) {
|
|
php_com_wrap_variant(return_value, &vres, obj->code_page TSRMLS_CC);
|
|
} else {
|
|
char *werr, *msg;
|
|
|
|
werr = php_win_err(res);
|
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
|
LocalFree(werr);
|
|
|
|
php_com_throw_exception(msg TSRMLS_CC);
|
|
efree(msg);
|
|
}
|
|
|
|
VariantClear(&vres);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto mixed variant_index_get(object variant, mixed index1 [, mixed index2 [, ...]])
|
|
Get the value of a multi dimensional array property */
|
|
PHP_FUNCTION(variant_index_get)
|
|
{
|
|
zval *zobj;
|
|
php_com_dotnet_object *obj;
|
|
VARIANT vres;
|
|
HRESULT res;
|
|
|
|
if (FAILURE == zend_parse_parameters(1 TSRMLS_CC,
|
|
"O", &zobj, php_com_variant_class_entry)) {
|
|
return;
|
|
}
|
|
obj = CDNO_FETCH(zobj);
|
|
|
|
/* TODO: finish... */
|
|
}
|
|
/* }}} */
|