Skip to content

Commit e56c506

Browse files
committed
Refactor DBA
Use proper ZPP union types Use standard function signature semantics for dba_fetch() Re-ordering of checks
1 parent e21d02a commit e56c506

File tree

5 files changed

+174
-174
lines changed

5 files changed

+174
-174
lines changed

UPGRADING

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ PHP 8.2 UPGRADE NOTES
5959
5. Changed Functions
6060
========================================
6161

62+
- DBA
63+
. dba_fetch()'s optional skip argument is now at the end in line with
64+
PHP userland semantics its signature now is:
65+
dba_fetch(string|array $key, $dba, int $skip = 0): string|false
66+
The overloaded signature
67+
dba_fetch(string|array $key, $skip, $dba): string|false
68+
is still accepted, but it is recommended to use the new standard variant.
69+
6270
========================================
6371
6. New Functions
6472
========================================

ext/dba/dba.c

Lines changed: 120 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -90,61 +90,45 @@ ZEND_GET_MODULE(dba)
9090
#endif
9191

9292
/* {{{ php_dba_myke_key */
93-
static size_t php_dba_make_key(zval *key, char **key_str, char **key_free)
93+
static zend_string* php_dba_make_key(HashTable *key)
9494
{
95-
if (Z_TYPE_P(key) == IS_ARRAY) {
96-
zval *group, *name;
97-
HashPosition pos;
98-
size_t len;
99-
100-
if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
101-
zend_argument_error(NULL, 1, "must have exactly two elements: \"key\" and \"name\"");
102-
return 0;
103-
}
104-
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
105-
group = zend_hash_get_current_data_ex(Z_ARRVAL_P(key), &pos);
106-
zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos);
107-
name = zend_hash_get_current_data_ex(Z_ARRVAL_P(key), &pos);
108-
convert_to_string(group);
109-
convert_to_string(name);
110-
if (Z_STRLEN_P(group) == 0) {
111-
*key_str = Z_STRVAL_P(name);
112-
*key_free = NULL;
113-
return Z_STRLEN_P(name);
114-
}
115-
len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_P(group), Z_STRVAL_P(name));
116-
*key_free = *key_str;
117-
return len;
118-
} else {
119-
zval tmp;
120-
size_t len;
121-
122-
ZVAL_COPY(&tmp, key);
123-
convert_to_string(&tmp);
124-
125-
len = Z_STRLEN(tmp);
126-
if (len) {
127-
*key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
128-
}
129-
zval_ptr_dtor(&tmp);
130-
return len;
131-
}
95+
zval *group, *name;
96+
HashPosition pos;
97+
98+
if (zend_hash_num_elements(key) != 2) {
99+
zend_argument_error(NULL, 1, "must have exactly two elements: \"key\" and \"name\"");
100+
return NULL;
101+
}
102+
103+
// TODO: Use ZEND_HASH_FOREACH_VAL() API?
104+
zend_hash_internal_pointer_reset_ex(key, &pos);
105+
group = zend_hash_get_current_data_ex(key, &pos);
106+
zend_hash_move_forward_ex(key, &pos);
107+
name = zend_hash_get_current_data_ex(key, &pos);
108+
// TODO: Use zval_try_get_string() or try_convert_to_string() instead?
109+
convert_to_string(group);
110+
convert_to_string(name);
111+
if (Z_STRLEN_P(group) == 0) {
112+
return Z_STR_P(name);
113+
}
114+
return zend_strpprintf(0, "[%s]%s", Z_STRVAL_P(group), Z_STRVAL_P(name));
132115
}
133116
/* }}} */
134117

118+
#define DBA_RELEASE_HT_KEY_CREATION() if (key_ht) {zend_string_release_ex(key_str, false);}
119+
135120
#define DBA_FETCH_RESOURCE(info, id) \
136121
if ((info = (dba_info *)zend_fetch_resource2(Z_RES_P(id), "DBA identifier", le_db, le_pdb)) == NULL) { \
137122
RETURN_THROWS(); \
138123
}
139124

140-
#define DBA_FETCH_RESOURCE_WITH_ID(info, id) \
141-
if ((info = (dba_info *)zend_fetch_resource2(Z_RES_P(id), "DBA identifier", le_db, le_pdb)) == NULL) { \
142-
DBA_ID_DONE; \
143-
RETURN_THROWS(); \
125+
/* check whether the user has write access */
126+
#define DBA_WRITE_CHECK(info) \
127+
if((info)->mode != DBA_WRITER && (info)->mode != DBA_TRUNC && (info)->mode != DBA_CREAT) { \
128+
php_error_docref(NULL, E_WARNING, "You cannot perform a modification to a database without proper access"); \
129+
RETURN_FALSE; \
144130
}
145131

146-
#define DBA_ID_DONE \
147-
if (key_free) efree(key_free)
148132
/* a DBA handler must have specific routines */
149133

150134
#define DBA_NAMED_HND(alias, name, flags) \
@@ -156,21 +140,6 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free)
156140

157141
#define DBA_HND(name, flags) DBA_NAMED_HND(name, name, flags)
158142

159-
/* check whether the user has write access */
160-
#define DBA_WRITE_CHECK \
161-
if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
162-
php_error_docref(NULL, E_WARNING, "You cannot perform a modification to a database without proper access"); \
163-
RETURN_FALSE; \
164-
}
165-
166-
/* the same check, but with a call to DBA_ID_DONE before returning */
167-
#define DBA_WRITE_CHECK_WITH_ID \
168-
if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
169-
php_error_docref(NULL, E_WARNING, "You cannot perform a modification to a database without proper access"); \
170-
DBA_ID_DONE; \
171-
RETURN_FALSE; \
172-
}
173-
174143
/* }}} */
175144

176145
/* {{{ globals */
@@ -420,33 +389,32 @@ PHP_MINFO_FUNCTION(dba)
420389
/* {{{ php_dba_update */
421390
static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
422391
{
423-
size_t val_len;
424392
zval *id;
425393
dba_info *info = NULL;
426-
zval *key;
427-
char *val;
428-
char *key_str, *key_free;
429-
size_t key_len;
394+
HashTable *key_ht = NULL;
395+
zend_string *key_str = NULL;
396+
zend_string *value;
430397

431-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zsr", &key, &val, &val_len, &id) == FAILURE) {
432-
RETURN_THROWS();
433-
}
398+
ZEND_PARSE_PARAMETERS_START(3, 3)
399+
Z_PARAM_ARRAY_HT_OR_STR(key_ht, key_str)
400+
Z_PARAM_STR(value)
401+
Z_PARAM_RESOURCE(id);
402+
ZEND_PARSE_PARAMETERS_END();
434403

435-
if ((key_len = php_dba_make_key(key, &key_str, &key_free)) == 0) {
436-
RETURN_FALSE;
437-
}
438-
439-
DBA_FETCH_RESOURCE_WITH_ID(info, id);
440-
441-
DBA_WRITE_CHECK_WITH_ID;
404+
DBA_FETCH_RESOURCE(info, id);
405+
DBA_WRITE_CHECK(info);
442406

443-
if (info->hnd->update(info, key_str, key_len, val, val_len, mode) == SUCCESS) {
444-
DBA_ID_DONE;
445-
RETURN_TRUE;
407+
if (key_ht) {
408+
key_str = php_dba_make_key(key_ht);
409+
if (!key_str) {
410+
// TODO ValueError?
411+
RETURN_FALSE;
412+
}
446413
}
447414

448-
DBA_ID_DONE;
449-
RETURN_FALSE;
415+
RETVAL_BOOL(info->hnd->update(info, ZSTR_VAL(key_str), ZSTR_LEN(key_str),
416+
ZSTR_VAL(value), ZSTR_LEN(value), mode) == SUCCESS);
417+
DBA_RELEASE_HT_KEY_CREATION();
450418
}
451419
/* }}} */
452420

@@ -895,61 +863,68 @@ PHP_FUNCTION(dba_exists)
895863
{
896864
zval *id;
897865
dba_info *info = NULL;
898-
zval *key;
899-
char *key_str, *key_free;
900-
size_t key_len;
866+
HashTable *key_ht = NULL;
867+
zend_string *key_str = NULL;
901868

902-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zr", &key, &id) == FAILURE) {
903-
RETURN_THROWS();
904-
}
905-
if ((key_len = php_dba_make_key(key, &key_str, &key_free)) == 0) {
906-
RETURN_FALSE;
907-
}
908-
DBA_FETCH_RESOURCE_WITH_ID(info, id);
869+
ZEND_PARSE_PARAMETERS_START(2, 2)
870+
Z_PARAM_ARRAY_HT_OR_STR(key_ht, key_str)
871+
Z_PARAM_RESOURCE(id);
872+
ZEND_PARSE_PARAMETERS_END();
909873

910-
if(info->hnd->exists(info, key_str, key_len) == SUCCESS) {
911-
DBA_ID_DONE;
912-
RETURN_TRUE;
874+
DBA_FETCH_RESOURCE(info, id);
875+
876+
if (key_ht) {
877+
key_str = php_dba_make_key(key_ht);
878+
if (!key_str) {
879+
// TODO ValueError?
880+
RETURN_FALSE;
881+
}
913882
}
914-
DBA_ID_DONE;
915-
RETURN_FALSE;
883+
884+
RETVAL_BOOL(info->hnd->exists(info, ZSTR_VAL(key_str), ZSTR_LEN(key_str)) == SUCCESS);
885+
DBA_RELEASE_HT_KEY_CREATION();
916886
}
917887
/* }}} */
918888

919889
/* {{{ Fetches the data associated with key */
920890
PHP_FUNCTION(dba_fetch)
921891
{
922-
char *val;
923-
size_t len = 0;
924892
zval *id;
925893
dba_info *info = NULL;
926-
zval *key;
927-
char *key_str, *key_free;
928-
size_t key_len;
894+
HashTable *key_ht = NULL;
895+
zend_string *key_str = NULL;
929896
zend_long skip = 0;
930897

931-
switch(ZEND_NUM_ARGS()) {
932-
case 2:
933-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zr", &key, &id) == FAILURE) {
934-
RETURN_THROWS();
935-
}
936-
break;
937-
case 3:
938-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zlr", &key, &skip, &id) == FAILURE) {
939-
RETURN_THROWS();
940-
}
941-
break;
942-
default:
943-
WRONG_PARAM_COUNT;
944-
}
945-
if ((key_len = php_dba_make_key(key, &key_str, &key_free)) == 0) {
946-
RETURN_FALSE;
898+
/* Check for legacy signature */
899+
if (ZEND_NUM_ARGS() == 3) {
900+
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 3, 3)
901+
Z_PARAM_ARRAY_HT_OR_STR(key_ht, key_str)
902+
Z_PARAM_LONG(skip)
903+
Z_PARAM_RESOURCE(id);
904+
ZEND_PARSE_PARAMETERS_END_EX(goto standard;);
905+
} else {
906+
standard:
907+
ZEND_PARSE_PARAMETERS_START(2, 3)
908+
Z_PARAM_ARRAY_HT_OR_STR(key_ht, key_str)
909+
Z_PARAM_RESOURCE(id);
910+
Z_PARAM_OPTIONAL
911+
Z_PARAM_LONG(skip)
912+
ZEND_PARSE_PARAMETERS_END();
947913
}
948914

949-
DBA_FETCH_RESOURCE_WITH_ID(info, id);
915+
DBA_FETCH_RESOURCE(info, id);
950916

951-
if (ZEND_NUM_ARGS() == 3) {
917+
if (key_ht) {
918+
key_str = php_dba_make_key(key_ht);
919+
if (!key_str) {
920+
// TODO ValueError?
921+
RETURN_FALSE;
922+
}
923+
}
924+
925+
if (skip != 0) {
952926
if (!strcmp(info->hnd->name, "cdb")) {
927+
// TODO ValueError?
953928
if (skip < 0) {
954929
php_error_docref(NULL, E_NOTICE, "Handler %s accepts only skip values greater than or equal to zero, using skip=0", info->hnd->name);
955930
skip = 0;
@@ -962,24 +937,25 @@ PHP_FUNCTION(dba_fetch)
962937
* value to 0 ensures the first value.
963938
*/
964939
if (skip < -1) {
940+
// TODO ValueError?
965941
php_error_docref(NULL, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
966942
skip = 0;
967943
}
968944
} else {
969945
php_error_docref(NULL, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
970946
skip = 0;
971947
}
972-
} else {
973-
skip = 0;
974948
}
975-
if((val = info->hnd->fetch(info, key_str, key_len, skip, &len)) != NULL) {
976-
DBA_ID_DONE;
977-
RETVAL_STRINGL(val, len);
978-
efree(val);
979-
return;
949+
950+
char *val;
951+
size_t len = 0;
952+
if ((val = info->hnd->fetch(info, ZSTR_VAL(key_str), ZSTR_LEN(key_str), skip, &len)) == NULL) {
953+
DBA_RELEASE_HT_KEY_CREATION();
954+
RETURN_FALSE;
980955
}
981-
DBA_ID_DONE;
982-
RETURN_FALSE;
956+
DBA_RELEASE_HT_KEY_CREATION();
957+
RETVAL_STRINGL(val, len);
958+
efree(val);
983959
}
984960
/* }}} */
985961

@@ -1070,27 +1046,27 @@ PHP_FUNCTION(dba_delete)
10701046
{
10711047
zval *id;
10721048
dba_info *info = NULL;
1073-
zval *key;
1074-
char *key_str, *key_free;
1075-
size_t key_len;
1049+
HashTable *key_ht = NULL;
1050+
zend_string *key_str = NULL;
10761051

1077-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zr", &key, &id) == FAILURE) {
1078-
RETURN_THROWS();
1079-
}
1080-
if ((key_len = php_dba_make_key(key, &key_str, &key_free)) == 0) {
1081-
RETURN_FALSE;
1082-
}
1083-
DBA_FETCH_RESOURCE_WITH_ID(info, id);
1052+
ZEND_PARSE_PARAMETERS_START(2, 2)
1053+
Z_PARAM_ARRAY_HT_OR_STR(key_ht, key_str)
1054+
Z_PARAM_RESOURCE(id);
1055+
ZEND_PARSE_PARAMETERS_END();
10841056

1085-
DBA_WRITE_CHECK_WITH_ID;
1057+
DBA_FETCH_RESOURCE(info, id);
1058+
DBA_WRITE_CHECK(info);
10861059

1087-
if(info->hnd->delete(info, key_str, key_len) == SUCCESS)
1088-
{
1089-
DBA_ID_DONE;
1090-
RETURN_TRUE;
1060+
if (key_ht) {
1061+
key_str = php_dba_make_key(key_ht);
1062+
if (!key_str) {
1063+
// TODO ValueError?
1064+
RETURN_FALSE;
1065+
}
10911066
}
1092-
DBA_ID_DONE;
1093-
RETURN_FALSE;
1067+
1068+
RETVAL_BOOL(info->hnd->delete(info, ZSTR_VAL(key_str), ZSTR_LEN(key_str)) == SUCCESS);
1069+
DBA_RELEASE_HT_KEY_CREATION();
10941070
}
10951071
/* }}} */
10961072

@@ -1121,8 +1097,7 @@ PHP_FUNCTION(dba_optimize)
11211097
}
11221098

11231099
DBA_FETCH_RESOURCE(info, id);
1124-
1125-
DBA_WRITE_CHECK;
1100+
DBA_WRITE_CHECK(info);
11261101

11271102
if (info->hnd->optimize(info) == SUCCESS) {
11281103
RETURN_TRUE;

0 commit comments

Comments
 (0)