Sitelet https://github.com/phpredis/phpredis/commit/bb66a547
Skip to content

Commit bb66a54

Browse files
Refactor HMGET command
Use new argument parsing API and simplify logic.
1 parent 40e1b1b commit bb66a54

1 file changed

Lines changed: 22 additions & 56 deletions

File tree

‎redis_commands.c‎

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,83 +2500,49 @@ int redis_hincrbyfloat_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25002500
int redis_hmget_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25012501
char **cmd, int *cmd_len, short *slot, void **ctx)
25022502
{
2503-
char *key;
2504-
zval *z_arr, *z_mems, *z_mem;
2505-
int i, count, valid = 0, key_free;
2506-
size_t key_len;
2507-
HashTable *ht_arr;
2503+
zval *field = NULL, *zctx = NULL;
25082504
smart_string cmdstr = {0};
2505+
HashTable *fields = NULL;
2506+
zend_string *key = NULL;
2507+
zend_ulong valid = 0;
25092508

2510-
// Parse arguments
2511-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &key, &key_len,
2512-
&z_arr) == FAILURE)
2513-
{
2514-
return FAILURE;
2515-
}
2516-
2517-
// Our HashTable
2518-
ht_arr = Z_ARRVAL_P(z_arr);
2509+
ZEND_PARSE_PARAMETERS_START(2, 2)
2510+
Z_PARAM_STR(key)
2511+
Z_PARAM_ARRAY_HT(fields)
2512+
ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
25192513

2520-
// We can abort if we have no elements
2521-
if ((count = zend_hash_num_elements(ht_arr)) == 0) {
2514+
if (zend_hash_num_elements(fields) == 0)
25222515
return FAILURE;
2523-
}
25242516

2525-
// Allocate memory for mems+1 so we can have a sentinel
2526-
z_mems = ecalloc(count + 1, sizeof(zval));
2517+
zctx = ecalloc(1 + zend_hash_num_elements(fields), sizeof(*zctx));
25272518

2528-
// Iterate over our member array
2529-
ZEND_HASH_FOREACH_VAL(ht_arr, z_mem) {
2530-
ZVAL_DEREF(z_mem);
2531-
// We can only handle string or long values here
2532-
if ((Z_TYPE_P(z_mem) == IS_STRING && Z_STRLEN_P(z_mem) > 0)
2533-
|| Z_TYPE_P(z_mem) == IS_LONG
2534-
) {
2535-
// Copy into our member array
2536-
ZVAL_ZVAL(&z_mems[valid], z_mem, 1, 0);
2519+
ZEND_HASH_FOREACH_VAL(fields, field) {
2520+
ZVAL_DEREF(field);
2521+
if (!((Z_TYPE_P(field) == IS_STRING && Z_STRLEN_P(field) > 0) || Z_TYPE_P(field) == IS_LONG))
2522+
continue;
25372523

2538-
// Increment the member count to actually send
2539-
valid++;
2540-
}
2524+
ZVAL_COPY(&zctx[valid++], field);
25412525
} ZEND_HASH_FOREACH_END();
25422526

2543-
// If nothing was valid, fail
25442527
if (valid == 0) {
2545-
efree(z_mems);
2528+
efree(zctx);
25462529
return FAILURE;
25472530
}
25482531

2549-
// Sentinel so we can free this even if it's used and then we discard
2550-
// the transaction manually or there is a transaction failure
2551-
ZVAL_NULL(&z_mems[valid]);
2552-
2553-
// Start command construction
2554-
redis_cmd_init_sstr(&cmdstr, valid+1, ZEND_STRL("HMGET"));
2555-
2556-
// Prefix our key
2557-
key_free = redis_key_prefix(redis_sock, &key, &key_len);
2532+
ZVAL_NULL(&zctx[valid]);
25582533

2559-
redis_cmd_append_sstr(&cmdstr, key, key_len);
2534+
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 1 + valid, "HMGET");
2535+
redis_cmd_append_sstr_key_zstr(&cmdstr, key, redis_sock, slot);
25602536

2561-
// Iterate over members, appending as arguments
2562-
for(i = 0; i< valid; i++) {
2563-
zend_string *zstr = zval_get_string(&z_mems[i]);
2564-
redis_cmd_append_sstr(&cmdstr, ZSTR_VAL(zstr), ZSTR_LEN(zstr));
2565-
zend_string_release(zstr);
2537+
for (zend_ulong i = 0; i < valid; i++) {
2538+
redis_cmd_append_sstr_zval(&cmdstr, &zctx[i], NULL);
25662539
}
25672540

2568-
// Set our slot
2569-
CMD_SET_SLOT(slot,key,key_len);
2570-
2571-
// Free our key if we prefixed it
2572-
if (key_free) efree(key);
2573-
25742541
// Push out command, length, and key context
25752542
*cmd = cmdstr.c;
25762543
*cmd_len = cmdstr.len;
2577-
*ctx = (void*)z_mems;
2544+
*ctx = zctx;
25782545

2579-
// Success!
25802546
return SUCCESS;
25812547
}
25822548

0 commit comments

Comments
 (0)