Skip to content

Commit d90ab53

Browse files
committed
ext/com_dotnet: Use modern HashTable APIs
1 parent e3bcbb2 commit d90ab53

File tree

2 files changed

+50
-112
lines changed

2 files changed

+50
-112
lines changed

ext/com_dotnet/com_variant.c

+20-41
Original file line numberDiff line numberDiff line change
@@ -24,72 +24,51 @@
2424
#include "php_com_dotnet.h"
2525
#include "php_com_dotnet_internal.h"
2626

27-
/* create an automation SafeArray from a PHP array.
27+
/* create an automation SafeArray from a PHP array (HashTable).
2828
* Only creates a single-dimensional array of variants.
2929
* The keys of the PHP hash MUST be numeric. If the array
3030
* is sparse, then the gaps will be filled with NULL variants */
31-
static void safe_array_from_zval(VARIANT *v, zval *z, int codepage)
31+
static void safe_array_from_hashtable(VARIANT *v, HashTable *ht, int codepage)
3232
{
3333
SAFEARRAY *sa = NULL;
3434
SAFEARRAYBOUND bound;
35-
HashPosition pos;
36-
int keytype;
37-
zend_string *strindex;
38-
zend_ulong intindex = 0;
3935
VARIANT *va;
40-
zval *item;
4136

4237
/* find the largest array index, and assert that all keys are integers */
43-
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(z), &pos);
44-
for (;; zend_hash_move_forward_ex(Z_ARRVAL_P(z), &pos)) {
45-
46-
keytype = zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
38+
if (!zend_array_is_list(ht)) {
39+
// TODO: Make this a ValueError
40+
php_error_docref(NULL, E_WARNING, "COM: converting from PHP array to VARIANT array; only arrays with numeric keys are allowed");
41+
V_VT(v) = VT_NULL;
42+
return;
43+
}
44+
// TODO: Check not empty?
4745

48-
if (HASH_KEY_IS_STRING == keytype) {
49-
goto bogus;
50-
} else if (HASH_KEY_NON_EXISTENT == keytype) {
51-
break;
52-
} else if (intindex > UINT_MAX) {
53-
php_error_docref(NULL, E_WARNING, "COM: max number %u of elements in safe array exceeded", UINT_MAX);
54-
break;
55-
}
46+
uint32_t nb_values = zend_hash_num_elements(ht);
47+
if (nb_values > UINT_MAX) {
48+
// TODO: Make this a ValueError?
49+
php_error_docref(NULL, E_WARNING, "COM: max number %u of elements in safe array exceeded", UINT_MAX);
5650
}
5751

5852
/* allocate the structure */
5953
bound.lLbound = 0;
60-
bound.cElements = zend_hash_num_elements(Z_ARRVAL_P(z));
54+
bound.cElements = nb_values;
6155
sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
6256

6357
/* get a lock on the array itself */
6458
SafeArrayAccessData(sa, &va);
6559
va = (VARIANT*)sa->pvData;
6660

6761
/* now fill it in */
68-
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(z), &pos);
69-
for (;; zend_hash_move_forward_ex(Z_ARRVAL_P(z), &pos)) {
70-
if (NULL == (item = zend_hash_get_current_data_ex(Z_ARRVAL_P(z), &pos))) {
71-
break;
72-
}
73-
zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
74-
php_com_variant_from_zval(&va[intindex], item, codepage);
75-
}
62+
zend_ulong index = 0;
63+
zval *value;
64+
ZEND_HASH_FOREACH_NUM_KEY_VAL(ht, index, value) {
65+
php_com_variant_from_zval(&va[index], value, codepage);
66+
} ZEND_HASH_FOREACH_END();
7667

7768
/* Unlock it and stuff it into our variant */
7869
SafeArrayUnaccessData(sa);
7970
V_VT(v) = VT_ARRAY|VT_VARIANT;
8071
V_ARRAY(v) = sa;
81-
82-
return;
83-
84-
bogus:
85-
php_error_docref(NULL, E_WARNING, "COM: converting from PHP array to VARIANT array; only arrays with numeric keys are allowed");
86-
87-
V_VT(v) = VT_NULL;
88-
89-
if (sa) {
90-
SafeArrayUnlock(sa);
91-
SafeArrayDestroy(sa);
92-
}
9372
}
9473

9574
static void php_com_variant_from_zval_ex(VARIANT *v, zval *z, int codepage, VARTYPE vt)
@@ -141,7 +120,7 @@ static void php_com_variant_from_zval_ex(VARIANT *v, zval *z, int codepage, VART
141120

142121
case IS_ARRAY:
143122
/* map as safe array */
144-
safe_array_from_zval(v, z, codepage);
123+
safe_array_from_hashtable(v, Z_ARRVAL_P(z), codepage);
145124
break;
146125

147126
case IS_LONG:

ext/com_dotnet/com_wrapper.c

+30-71
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,8 @@ static struct IDispatchExVtbl php_dispatch_vtbl = {
421421
* dispatch ids */
422422
static void generate_dispids(php_dispatchex *disp)
423423
{
424-
HashPosition pos;
425424
zend_string *name = NULL;
426-
zval *tmp, tmp2;
427-
int keytype;
425+
zval tmp;
428426
zend_ulong pid;
429427

430428
if (disp->dispid_to_name == NULL) {
@@ -436,71 +434,42 @@ static void generate_dispids(php_dispatchex *disp)
436434

437435
/* properties */
438436
if (Z_OBJPROP(disp->object)) {
439-
zend_hash_internal_pointer_reset_ex(Z_OBJPROP(disp->object), &pos);
440-
while (HASH_KEY_NON_EXISTENT != (keytype =
441-
zend_hash_get_current_key_ex(Z_OBJPROP(disp->object), &name,
442-
&pid, &pos))) {
443-
char namebuf[32];
444-
if (keytype == HASH_KEY_IS_LONG) {
445-
snprintf(namebuf, sizeof(namebuf), ZEND_ULONG_FMT, pid);
446-
name = zend_string_init(namebuf, strlen(namebuf), 0);
447-
} else {
448-
zend_string_addref(name);
449-
}
450-
451-
zend_hash_move_forward_ex(Z_OBJPROP(disp->object), &pos);
437+
ZEND_HASH_FOREACH_STR_KEY(Z_OBJPROP(disp->object), name) {
438+
ZEND_ASSERT(name);
452439

453-
/* Find the existing id */
454-
if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) {
455-
zend_string_release_ex(name, 0);
440+
/* Check ID exists */
441+
if (!zend_hash_exists(disp->name_to_dispid, name)) {
456442
continue;
457443
}
458444

459445
/* add the mappings */
460-
ZVAL_STR_COPY(&tmp2, name);
446+
ZVAL_STR_COPY(&tmp, name);
461447
pid = zend_hash_next_free_element(disp->dispid_to_name);
462-
zend_hash_index_update(disp->dispid_to_name, pid, &tmp2);
463-
464-
ZVAL_LONG(&tmp2, pid);
465-
zend_hash_update(disp->name_to_dispid, name, &tmp2);
448+
zend_hash_index_update(disp->dispid_to_name, pid, &tmp);
466449

467-
zend_string_release_ex(name, 0);
468-
}
450+
ZVAL_LONG(&tmp, pid);
451+
zend_hash_update(disp->name_to_dispid, name, &tmp);
452+
} ZEND_HASH_FOREACH_END();
469453
}
470454

471455
/* functions */
472456
if (Z_OBJCE(disp->object)) {
473-
zend_hash_internal_pointer_reset_ex(&Z_OBJCE(disp->object)->function_table, &pos);
474-
while (HASH_KEY_NON_EXISTENT != (keytype =
475-
zend_hash_get_current_key_ex(&Z_OBJCE(disp->object)->function_table,
476-
&name, &pid, &pos))) {
477-
478-
char namebuf[32];
479-
if (keytype == HASH_KEY_IS_LONG) {
480-
snprintf(namebuf, sizeof(namebuf), ZEND_ULONG_FMT, pid);
481-
name = zend_string_init(namebuf, strlen(namebuf), 0);
482-
} else {
483-
zend_string_addref(name);
484-
}
485-
486-
zend_hash_move_forward_ex(&Z_OBJCE(disp->object)->function_table, &pos);
457+
ZEND_HASH_FOREACH_STR_KEY(&Z_OBJCE(disp->object)->function_table, name) {
458+
ZEND_ASSERT(name);
487459

488-
/* Find the existing id */
489-
if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) {
490-
zend_string_release_ex(name, 0);
460+
/* Check ID exists */
461+
if (!zend_hash_exists(disp->name_to_dispid, name)) {
491462
continue;
492463
}
493464

494465
/* add the mappings */
495-
ZVAL_STR_COPY(&tmp2, name);
466+
ZVAL_STR_COPY(&tmp, name);
496467
pid = zend_hash_next_free_element(disp->dispid_to_name);
497-
zend_hash_index_update(disp->dispid_to_name, pid, &tmp2);
498-
499-
ZVAL_LONG(&tmp2, pid);
500-
zend_hash_update(disp->name_to_dispid, name, &tmp2);
468+
zend_hash_index_update(disp->dispid_to_name, pid, &tmp);
501469

502-
zend_string_release_ex(name, 0);
503-
}
470+
ZVAL_LONG(&tmp, pid);
471+
zend_hash_update(disp->name_to_dispid, name, &tmp);
472+
} ZEND_HASH_FOREACH_END();
504473
}
505474
}
506475

@@ -541,15 +510,9 @@ static void disp_destructor(php_dispatchex *disp)
541510
CoTaskMemFree(disp);
542511
}
543512

544-
PHP_COM_DOTNET_API IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *sinkid,
545-
HashTable *id_to_name)
513+
PHP_COM_DOTNET_API IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name)
546514
{
547515
php_dispatchex *disp = disp_constructor(val);
548-
HashPosition pos;
549-
zend_string *name = NULL;
550-
zval tmp, *ntmp;
551-
int keytype;
552-
zend_ulong pid;
553516

554517
disp->dispid_to_name = id_to_name;
555518

@@ -559,20 +522,16 @@ PHP_COM_DOTNET_API IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *si
559522
ALLOC_HASHTABLE(disp->name_to_dispid);
560523
zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0);
561524

562-
zend_hash_internal_pointer_reset_ex(id_to_name, &pos);
563-
while (HASH_KEY_NON_EXISTENT != (keytype =
564-
zend_hash_get_current_key_ex(id_to_name, &name, &pid, &pos))) {
565-
566-
if (keytype == HASH_KEY_IS_LONG) {
567-
568-
ntmp = zend_hash_get_current_data_ex(id_to_name, &pos);
569-
570-
ZVAL_LONG(&tmp, pid);
571-
zend_hash_update(disp->name_to_dispid, Z_STR_P(ntmp), &tmp);
572-
}
573-
574-
zend_hash_move_forward_ex(id_to_name, &pos);
575-
}
525+
ZEND_ASSERT(zend_array_is_list(id_to_name));
526+
zend_ulong pid;
527+
zval *value;
528+
ZEND_HASH_FOREACH_NUM_KEY_VAL(id_to_name, pid, value) {
529+
ZEND_ASSERT(Z_TYPE_P(value) == IS_STRING);
530+
531+
zval tmp;
532+
ZVAL_LONG(&tmp, pid);
533+
zend_hash_update(disp->name_to_dispid, Z_STR_P(value), &tmp);
534+
} ZEND_HASH_FOREACH_END();
576535

577536
return (IDispatch*)disp;
578537
}

0 commit comments

Comments
 (0)