Skip to content

Commit 71c9f7c

Browse files
committed
1 parent 48c8f2a commit 71c9f7c

File tree

2 files changed

+76
-15
lines changed

2 files changed

+76
-15
lines changed

common.h

+16
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,22 @@ zval_get_long(zval *op)
300300
return 0;
301301
}
302302

303+
static zend_always_inline double
304+
zval_get_double(zval *op)
305+
{
306+
switch (Z_TYPE_P(op)) {
307+
case IS_BOOL:
308+
case IS_LONG:
309+
return (double)Z_LVAL_P(op);
310+
case IS_DOUBLE:
311+
return Z_DVAL_P(op);
312+
case IS_STRING:
313+
return zend_strtod(Z_STRVAL_P(op), NULL);
314+
EMPTY_SWITCH_DEFAULT_CASE()
315+
}
316+
return 0.0;
317+
}
318+
303319
static void (*_php_var_serialize)(smart_str *, zval **, php_serialize_data_t * TSRMLS_DC) = &php_var_serialize;
304320
#define php_var_serialize(buf, struc, data) _php_var_serialize(buf, &struc, data TSRMLS_CC)
305321
static int (*_php_var_unserialize)(zval **, const unsigned char **, const unsigned char *, php_unserialize_data_t * TSRMLS_DC) = &php_var_unserialize;

redis_commands.c

+60-15
Original file line numberDiff line numberDiff line change
@@ -2577,25 +2577,57 @@ int redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
25772577
char **cmd, int *cmd_len, short *slot, void **ctx)
25782578
{
25792579
zval *z_args;
2580-
char *key, *val;
2580+
char *key, *val, *exp_type = NULL;
25812581
int key_len, key_free, val_len, val_free;
2582-
int argc = ZEND_NUM_ARGS(), i;
2582+
int num = ZEND_NUM_ARGS(), i = 1, argc;
2583+
zend_bool ch = 0, incr = 0;
25832584
smart_string cmdstr = {0};
25842585

2585-
z_args = emalloc(argc * sizeof(zval));
2586-
if (zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
2586+
if (num < 3) return FAILURE;
2587+
z_args = ecalloc(num, sizeof(zval));
2588+
if (zend_get_parameters_array(ht, num, z_args) == FAILURE) {
25872589
efree(z_args);
25882590
return FAILURE;
25892591
}
25902592

2591-
// Need key, score, value, [score, value...] */
2592-
if(argc>0) convert_to_string(&z_args[0]);
2593-
if(argc<3 || Z_TYPE(z_args[0])!=IS_STRING || (argc-1)%2 != 0) {
2594-
efree(z_args);
2595-
return FAILURE;
2593+
// Need key, [NX|XX] [CH] [INCR] score, value, [score, value...] */
2594+
if (num % 2 == 0) {
2595+
if (Z_TYPE(z_args[1]) != IS_ARRAY) {
2596+
efree(z_args);
2597+
return FAILURE;
2598+
}
2599+
zval *z_opt;
2600+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL(z_args[1]), z_opt) {
2601+
if (Z_TYPE_P(z_opt) == IS_STRING) {
2602+
if (Z_STRLEN_P(z_opt) == 2) {
2603+
if (IS_NX_XX_ARG(Z_STRVAL_P(z_opt))) {
2604+
exp_type = Z_STRVAL_P(z_opt);
2605+
} else if (strncasecmp(Z_STRVAL_P(z_opt), "ch", 2) == 0) {
2606+
ch = 1;
2607+
}
2608+
} else if (Z_STRLEN_P(z_opt) == 4 &&
2609+
strncasecmp(Z_STRVAL_P(z_opt), "incr", 4) == 0
2610+
) {
2611+
if (num > 4) {
2612+
// Only one score-element pair can be specified in this mode.
2613+
efree(z_args);
2614+
return FAILURE;
2615+
}
2616+
incr = 1;
2617+
}
2618+
2619+
}
2620+
} ZEND_HASH_FOREACH_END();
2621+
argc = num - 1;
2622+
if (exp_type) argc++;
2623+
argc += ch + incr;
2624+
i++;
2625+
} else {
2626+
argc = num;
25962627
}
25972628

25982629
// Prefix our key
2630+
convert_to_string(&z_args[0]);
25992631
key = Z_STRVAL(z_args[0]);
26002632
key_len = Z_STRLEN(z_args[0]);
26012633
key_free = redis_key_prefix(redis_sock, &key, &key_len);
@@ -2608,19 +2640,32 @@ int redis_zadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
26082640
CMD_SET_SLOT(slot,key,key_len);
26092641
if(key_free) efree(key);
26102642

2643+
if (exp_type) redis_cmd_append_sstr(&cmdstr, exp_type, 2);
2644+
if (ch) redis_cmd_append_sstr(&cmdstr, "CH", 2);
2645+
if (incr) redis_cmd_append_sstr(&cmdstr, "INCR", 4);
2646+
26112647
// Now the rest of our arguments
2612-
for(i=1;i<argc;i+=2) {
2613-
// Convert score to a double, serialize value if requested
2614-
convert_to_double(&z_args[i]);
2648+
while (i < num) {
2649+
// Append score and member
2650+
if (Z_TYPE(z_args[i]) == IS_STRING && (
2651+
/* The score values should be the string representation of a double
2652+
* precision floating point number. +inf and -inf values are valid
2653+
* values as well. */
2654+
strncasecmp(Z_STRVAL(z_args[i]), "-inf", 4) == 0 ||
2655+
strncasecmp(Z_STRVAL(z_args[i]), "+inf", 4) == 0
2656+
)) {
2657+
redis_cmd_append_sstr(&cmdstr, Z_STRVAL(z_args[i]), Z_STRLEN(z_args[i]));
2658+
} else {
2659+
redis_cmd_append_sstr_dbl(&cmdstr, zval_get_double(&z_args[i]));
2660+
}
2661+
// serialize value if requested
26152662
val_free = redis_serialize(redis_sock, &z_args[i+1], &val, &val_len
26162663
TSRMLS_CC);
2617-
2618-
// Append score and member
2619-
redis_cmd_append_sstr_dbl(&cmdstr, Z_DVAL(z_args[i]));
26202664
redis_cmd_append_sstr(&cmdstr, val, val_len);
26212665

26222666
// Free value if we serialized
26232667
if(val_free) efree(val);
2668+
i += 2;
26242669
}
26252670

26262671
// Push output values

0 commit comments

Comments
 (0)