@@ -1440,231 +1440,141 @@ PHP_METHOD(Redis, sort) {
14401440 }
14411441
14421442 REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
1443- if (have_store ) {
1444- IF_ATOMIC () {
1445- redis_long_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1446- NULL , NULL );
1447- }
1448- REDIS_PROCESS_RESPONSE (redis_long_response );
1449- } else {
1450- IF_ATOMIC () {
1451- if (redis_sock_read_multibulk_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1452- redis_sock , NULL , NULL )< 0 )
1453- {
1454- RETURN_FALSE ;
1455- }
1443+ IF_ATOMIC () {
1444+ if (redis_read_variant_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1445+ redis_sock , NULL , NULL ) < 0 )
1446+ {
1447+ RETURN_FALSE ;
14561448 }
1457- REDIS_PROCESS_RESPONSE (redis_sock_read_multibulk_reply );
14581449 }
1450+ REDIS_PROCESS_RESPONSE (redis_read_variant_reply );
14591451}
14601452
1461- PHP_REDIS_API void generic_sort_cmd ( INTERNAL_FUNCTION_PARAMETERS , char * sort ,
1462- int use_alpha )
1453+ static void
1454+ generic_sort_cmd ( INTERNAL_FUNCTION_PARAMETERS , int desc , int alpha )
14631455{
1464-
1465- zval * object ;
1456+ zval * object , * zele , * zget = NULL ;
14661457 RedisSock * redis_sock ;
1467- char * key = NULL , * pattern = NULL , * get = NULL , * store = NULL , * cmd ;
1468- int cmd_len , key_free ;
1469- zend_long sort_start = -1 , sort_count = -1 ;
1470- strlen_t key_len , pattern_len , get_len , store_len ;
1471-
1472- int cmd_elements ;
1473-
1474- char * cmd_lines [30 ];
1475- int cmd_sizes [30 ];
1476-
1477- int sort_len ;
1478- int i , pos ;
1458+ zend_string * zpattern ;
1459+ char * key = NULL , * pattern = NULL , * store = NULL ;
1460+ strlen_t keylen , patternlen , storelen ;
1461+ zend_long offset = -1 , count = -1 ;
1462+ int argc = 1 ; /* SORT key is the simplest SORT command */
1463+ smart_string cmd = {0 };
14791464
1465+ /* Parse myriad of sort arguments */
14801466 if (zend_parse_method_parameters (ZEND_NUM_ARGS () TSRMLS_CC , getThis (),
1481- "Os|sslls " , & object , redis_ce , & key ,
1482- & key_len , & pattern , & pattern_len , & get ,
1483- & get_len , & sort_start , & sort_count , & store ,
1484- & store_len ) == FAILURE )
1467+ "Os|s!z!lls " , & object , redis_ce , & key ,
1468+ & keylen , & pattern , & patternlen , & zget ,
1469+ & offset , & count , & store , & storelen )
1470+ == FAILURE )
14851471 {
14861472 RETURN_FALSE ;
14871473 }
14881474
1489- if (key_len == 0 || (redis_sock = redis_sock_get (object TSRMLS_CC , 0 )) == NULL ) {
1475+ /* Ensure we're sorting something, and we can get context */
1476+ if (keylen == 0 || !(redis_sock = redis_sock_get (object TSRMLS_CC , 0 )))
14901477 RETURN_FALSE ;
1478+
1479+ /* Start calculating argc depending on input arguments */
1480+ if (pattern && patternlen ) argc += 2 ; /* BY pattern */
1481+ if (offset >= 0 && count >= 0 ) argc += 3 ; /* LIMIT offset count */
1482+ if (alpha ) argc += 1 ; /* ALPHA */
1483+ if (store ) argc += 2 ; /* STORE destination */
1484+ if (desc ) argc += 1 ; /* DESC (ASC is the default) */
1485+
1486+ /* GET is special. It can be 0 .. N arguments depending what we have */
1487+ if (zget ) {
1488+ if (Z_TYPE_P (zget ) == IS_ARRAY )
1489+ argc += zend_hash_num_elements (Z_ARRVAL_P (zget ));
1490+ else if (Z_STRLEN_P (zget ) > 0 ) {
1491+ argc += 2 ; /* GET pattern */
1492+ }
14911493 }
14921494
1493- /* first line, sort. */
1494- cmd_lines [1 ] = estrndup ("$4" , 2 );
1495- cmd_sizes [1 ] = 2 ;
1496- cmd_lines [2 ] = estrndup ("SORT" , 4 );
1497- cmd_sizes [2 ] = 4 ;
1495+ /* Start constructing final command and append key */
1496+ redis_cmd_init_sstr (& cmd , argc , "SORT" , 4 );
1497+ redis_cmd_append_sstr_key (& cmd , key , keylen , redis_sock , NULL );
14981498
1499- /* Prefix our key if we need to */
1500- key_free = redis_key_prefix (redis_sock , & key , & key_len );
1499+ /* BY pattern */
1500+ if (pattern && patternlen ) {
1501+ redis_cmd_append_sstr (& cmd , "BY" , sizeof ("BY" ) - 1 );
1502+ redis_cmd_append_sstr (& cmd , pattern , patternlen );
1503+ }
15011504
1502- /* second line, key */
1503- cmd_sizes [3 ] = redis_cmd_format (& cmd_lines [3 ], "$%d" , key_len );
1504- cmd_lines [4 ] = estrndup (key , key_len );
1505- cmd_sizes [4 ] = key_len ;
1505+ /* LIMIT offset count */
1506+ if (offset >= 0 && count >= 0 ) {
1507+ redis_cmd_append_sstr (& cmd , "LIMIT" , sizeof ("LIMIT" ) - 1 );
1508+ redis_cmd_append_sstr_long (& cmd , offset );
1509+ redis_cmd_append_sstr_long (& cmd , count );
1510+ }
15061511
1507- /* If we prefixed our key, free it */
1508- if (key_free ) efree (key );
1512+ /* Handle any number of GET pattern arguments we've been passed */
1513+ if (zget != NULL ) {
1514+ if (Z_TYPE_P (zget ) == IS_ARRAY ) {
1515+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (zget ), zele ) {
1516+ zpattern = zval_get_string (zele );
1517+ redis_cmd_append_sstr (& cmd , "GET" , sizeof ("GET" ) - 1 );
1518+ redis_cmd_append_sstr (& cmd , zpattern -> val , zpattern -> len );
1519+ } ZEND_HASH_FOREACH_END ();
1520+ } else {
1521+ zpattern = zval_get_string (zget );
1522+ redis_cmd_append_sstr (& cmd , "GET" , sizeof ("GET" ) - 1 );
1523+ redis_cmd_append_sstr (& cmd , zpattern -> val , zpattern -> len );
1524+ zend_string_release (zpattern );
1525+ }
1526+ }
1527+
1528+ /* Append optional DESC and ALPHA modifiers */
1529+ if (desc ) redis_cmd_append_sstr (& cmd , "DESC" , sizeof ("DESC" ) - 1 );
1530+ if (alpha ) redis_cmd_append_sstr (& cmd , "ALPHA" , sizeof ("ALPHA" ) - 1 );
15091531
1510- cmd_elements = 5 ;
1511- if (pattern && pattern_len ) {
1512- /* BY */
1513- cmd_lines [cmd_elements ] = estrndup ("$2" , 2 );
1514- cmd_sizes [cmd_elements ] = 2 ;
1515- cmd_elements ++ ;
1516- cmd_lines [cmd_elements ] = estrndup ("BY" , 2 );
1517- cmd_sizes [cmd_elements ] = 2 ;
1518- cmd_elements ++ ;
1519-
1520- /* pattern */
1521- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ], "$%d" , pattern_len );
1522- cmd_elements ++ ;
1523- cmd_lines [cmd_elements ] = estrndup (pattern , pattern_len );
1524- cmd_sizes [cmd_elements ] = pattern_len ;
1525- cmd_elements ++ ;
1526- }
1527- if (sort_start >= 0 && sort_count >= 0 ) {
1528- /* LIMIT */
1529- cmd_lines [cmd_elements ] = estrndup ("$5" , 2 );
1530- cmd_sizes [cmd_elements ] = 2 ;
1531- cmd_elements ++ ;
1532- cmd_lines [cmd_elements ] = estrndup ("LIMIT" , 5 );
1533- cmd_sizes [cmd_elements ] = 5 ;
1534- cmd_elements ++ ;
1535-
1536- /* start */
1537- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ],
1538- "$%d" , integer_length (sort_start ));
1539- cmd_elements ++ ;
1540- cmd_sizes [cmd_elements ] = spprintf (& cmd_lines [cmd_elements ], 0 ,
1541- "%d" , (int )sort_start );
1542- cmd_elements ++ ;
1543-
1544- /* count */
1545- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ],
1546- "$%d" , integer_length (sort_count ));
1547- cmd_elements ++ ;
1548- cmd_sizes [cmd_elements ] = spprintf (& cmd_lines [cmd_elements ], 0 ,
1549- "%d" , (int )sort_count );
1550- cmd_elements ++ ;
1551- }
1552- if (get && get_len ) {
1553- /* GET */
1554- cmd_lines [cmd_elements ] = estrndup ("$3" , 2 );
1555- cmd_sizes [cmd_elements ] = 2 ;
1556- cmd_elements ++ ;
1557- cmd_lines [cmd_elements ] = estrndup ("GET" , 3 );
1558- cmd_sizes [cmd_elements ] = 3 ;
1559- cmd_elements ++ ;
1560-
1561- /* pattern */
1562- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ],
1563- "$%d" , get_len );
1564- cmd_elements ++ ;
1565- cmd_lines [cmd_elements ] = estrndup (get , get_len );
1566- cmd_sizes [cmd_elements ] = get_len ;
1567- cmd_elements ++ ;
1568- }
1569-
1570- /* add ASC or DESC */
1571- sort_len = strlen (sort );
1572- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ], "$%d" ,
1573- sort_len );
1574- cmd_elements ++ ;
1575- cmd_lines [cmd_elements ] = estrndup (sort , sort_len );
1576- cmd_sizes [cmd_elements ] = sort_len ;
1577- cmd_elements ++ ;
1578-
1579- if (use_alpha ) {
1580- /* ALPHA */
1581- cmd_lines [cmd_elements ] = estrndup ("$5" , 2 );
1582- cmd_sizes [cmd_elements ] = 2 ;
1583- cmd_elements ++ ;
1584- cmd_lines [cmd_elements ] = estrndup ("ALPHA" , 5 );
1585- cmd_sizes [cmd_elements ] = 5 ;
1586- cmd_elements ++ ;
1587- }
1588- if (store && store_len ) {
1589- /* STORE */
1590- cmd_lines [cmd_elements ] = estrndup ("$5" , 2 );
1591- cmd_sizes [cmd_elements ] = 2 ;
1592- cmd_elements ++ ;
1593- cmd_lines [cmd_elements ] = estrndup ("STORE" , 5 );
1594- cmd_sizes [cmd_elements ] = 5 ;
1595- cmd_elements ++ ;
1596-
1597- /* store key */
1598- cmd_sizes [cmd_elements ] = redis_cmd_format (& cmd_lines [cmd_elements ],
1599- "$%d" , store_len );
1600- cmd_elements ++ ;
1601- cmd_lines [cmd_elements ] = estrndup (store , store_len );
1602- cmd_sizes [cmd_elements ] = store_len ;
1603- cmd_elements ++ ;
1604- }
1605-
1606- /* first line has the star */
1607- cmd_sizes [0 ] = spprintf (& cmd_lines [0 ], 0 , "*%d" , (cmd_elements - 1 )/2 );
1608-
1609- /* compute the command size */
1610- cmd_len = 0 ;
1611- for (i = 0 ; i < cmd_elements ; ++ i ) {
1612- /* Each line followed by a _NL (\r\n) */
1613- cmd_len += cmd_sizes [i ] + sizeof (_NL ) - 1 ;
1614- }
1615-
1616- /* copy all lines into the final command. */
1617- cmd = emalloc (1 + cmd_len );
1618- pos = 0 ;
1619- for (i = 0 ; i < cmd_elements ; ++ i ) {
1620- memcpy (cmd + pos , cmd_lines [i ], cmd_sizes [i ]);
1621- pos += cmd_sizes [i ];
1622- memcpy (cmd + pos , _NL , sizeof (_NL ) - 1 );
1623- pos += sizeof (_NL ) - 1 ;
1624-
1625- /* free every line */
1626- efree (cmd_lines [i ]);
1532+ /* Finally append STORE if we've got it */
1533+ if (store && storelen ) {
1534+ redis_cmd_append_sstr (& cmd , "STORE" , sizeof ("STORE" ) - 1 );
1535+ redis_cmd_append_sstr_key (& cmd , store , storelen , redis_sock , NULL );
16271536 }
16281537
1629- REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
1538+ REDIS_PROCESS_REQUEST (redis_sock , cmd . c , cmd . len );
16301539 IF_ATOMIC () {
1631- if (redis_sock_read_multibulk_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1632- redis_sock , NULL , NULL ) < 0 ) {
1540+ if (redis_read_variant_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1541+ redis_sock , NULL , NULL ) < 0 )
1542+ {
16331543 RETURN_FALSE ;
16341544 }
16351545 }
1636- REDIS_PROCESS_RESPONSE (redis_sock_read_multibulk_reply );
1546+ REDIS_PROCESS_RESPONSE (redis_read_variant_reply );
16371547}
16381548
16391549/* {{{ proto array Redis::sortAsc(string key, string pattern, string get,
16401550 * int start, int end, bool getList]) */
16411551PHP_METHOD (Redis , sortAsc )
16421552{
1643- generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , "ASC" , 0 );
1553+ generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 , 0 );
16441554}
16451555/* }}} */
16461556
16471557/* {{{ proto array Redis::sortAscAlpha(string key, string pattern, string get,
16481558 * int start, int end, bool getList]) */
16491559PHP_METHOD (Redis , sortAscAlpha )
16501560{
1651- generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , "ASC" , 1 );
1561+ generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 , 1 );
16521562}
16531563/* }}} */
16541564
16551565/* {{{ proto array Redis::sortDesc(string key, string pattern, string get,
16561566 * int start, int end, bool getList]) */
16571567PHP_METHOD (Redis , sortDesc )
16581568{
1659- generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , "DESC" , 0 );
1569+ generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 , 0 );
16601570}
16611571/* }}} */
16621572
16631573/* {{{ proto array Redis::sortDescAlpha(string key, string pattern, string get,
16641574 * int start, int end, bool getList]) */
16651575PHP_METHOD (Redis , sortDescAlpha )
16661576{
1667- generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , "DESC" , 1 );
1577+ generic_sort_cmd (INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 , 1 );
16681578}
16691579/* }}} */
16701580
0 commit comments