@@ -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