Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bdd287e

Browse files
Clean up generic sort method
1 parent d750813 commit bdd287e

2 files changed

Lines changed: 83 additions & 176 deletions

File tree

php_redis.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,6 @@ typedef void (*ResultCallback)(INTERNAL_FUNCTION_PARAMETERS,
247247

248248
PHP_REDIS_API int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent);
249249

250-
PHP_REDIS_API void generic_sort_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sort,
251-
int use_alpha);
252-
253250
PHP_REDIS_API void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd);
254251

255252
PHP_REDIS_API void generic_unsubscribe_cmd(INTERNAL_FUNCTION_PARAMETERS,

redis.c

Lines changed: 83 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -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]) */
16411551
PHP_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]) */
16491559
PHP_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]) */
16571567
PHP_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]) */
16651575
PHP_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

Comments
 (0)