|
68 | 68 | #define SCORE_DECODE_INT 1 |
69 | 69 | #define SCORE_DECODE_DOUBLE 2 |
70 | 70 |
|
| 71 | +/* PhpRedis often returns either FALSE or NULL depending on whether we have |
| 72 | + * an option set, so this macro just wraps that often repeated logic */ |
| 73 | +#define REDIS_ZVAL_NULL(sock_, zv_) \ |
| 74 | + do { \ |
| 75 | + if ((sock_)->null_mbulk_as_null) { \ |
| 76 | + ZVAL_NULL((zv_)); \ |
| 77 | + } else { \ |
| 78 | + ZVAL_FALSE((zv_)); \ |
| 79 | + } \ |
| 80 | + } while (0) |
| 81 | + |
71 | 82 | #ifndef PHP_WIN32 |
72 | 83 | #include <netinet/tcp.h> /* TCP_NODELAY */ |
73 | 84 | #include <sys/socket.h> /* SO_KEEPALIVE */ |
@@ -464,9 +475,7 @@ PHP_REDIS_API int redis_subscribe_response(INTERNAL_FUNCTION_PARAMETERS, |
464 | 475 | // Consume response(s) from subscribe, which will vary on argc |
465 | 476 | while(sctx->argc--) { |
466 | 477 | ZVAL_NULL(&z_resp); |
467 | | - if (!redis_sock_read_multibulk_reply_zval( |
468 | | - INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_resp) |
469 | | - ) { |
| 478 | + if (!redis_sock_read_multibulk_reply_zval(redis_sock, &z_resp)) { |
470 | 479 | goto error; |
471 | 480 | } |
472 | 481 |
|
@@ -513,9 +522,7 @@ PHP_REDIS_API int redis_subscribe_response(INTERNAL_FUNCTION_PARAMETERS, |
513 | 522 | int tab_idx = 1, is_pmsg = 0; |
514 | 523 |
|
515 | 524 | ZVAL_NULL(&z_resp); |
516 | | - if (!redis_sock_read_multibulk_reply_zval( |
517 | | - INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_resp) |
518 | | - ) { |
| 525 | + if (!redis_sock_read_multibulk_reply_zval(redis_sock, &z_resp)) { |
519 | 526 | goto failure; |
520 | 527 | } |
521 | 528 |
|
@@ -606,8 +613,7 @@ PHP_REDIS_API int redis_unsubscribe_response(INTERNAL_FUNCTION_PARAMETERS, |
606 | 613 |
|
607 | 614 | while (sctx->argc--) { |
608 | 615 | ZVAL_NULL(&z_resp); |
609 | | - if (!redis_sock_read_multibulk_reply_zval( |
610 | | - INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_resp) || |
| 616 | + if (!redis_sock_read_multibulk_reply_zval(redis_sock, &z_resp) || |
611 | 617 | (z_chan = zend_hash_index_find(Z_ARRVAL(z_resp), 1)) == NULL |
612 | 618 | ) { |
613 | 619 | efree(sctx); |
@@ -642,8 +648,7 @@ PHP_REDIS_API int redis_unsubscribe_response(INTERNAL_FUNCTION_PARAMETERS, |
642 | 648 | } |
643 | 649 |
|
644 | 650 | PHP_REDIS_API zval * |
645 | | -redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, |
646 | | - RedisSock *redis_sock, zval *z_tab) |
| 651 | +redis_sock_read_multibulk_reply_zval(RedisSock *redis_sock, zval *z_tab) |
647 | 652 | { |
648 | 653 | int numElems; |
649 | 654 |
|
@@ -1617,6 +1622,87 @@ geosearch_cast(zval *zv) |
1617 | 1622 | return SUCCESS; |
1618 | 1623 | } |
1619 | 1624 |
|
| 1625 | +PHP_REDIS_API int |
| 1626 | +redis_read_mpop_response(RedisSock *redis_sock, zval *zdst, int elements, |
| 1627 | + void *ctx) |
| 1628 | +{ |
| 1629 | + int subele, keylen; |
| 1630 | + zval zele = {0}; |
| 1631 | + char *key; |
| 1632 | + |
| 1633 | + ZEND_ASSERT(ctx == NULL || ctx == PHPREDIS_CTX_PTR); |
| 1634 | + |
| 1635 | + if (elements < 0) { |
| 1636 | + REDIS_ZVAL_NULL(redis_sock, zdst); |
| 1637 | + return SUCCESS; |
| 1638 | + } |
| 1639 | + |
| 1640 | + /* Invariant: We should have two elements */ |
| 1641 | + ZEND_ASSERT(elements == 2); |
| 1642 | + |
| 1643 | + array_init(zdst); |
| 1644 | + |
| 1645 | + /* Key name and number of entries */ |
| 1646 | + if ((key = redis_sock_read(redis_sock, &keylen)) == NULL || |
| 1647 | + read_mbulk_header(redis_sock, &elements) < 0 || elements < 0) |
| 1648 | + { |
| 1649 | + if (key) efree(key); |
| 1650 | + goto fail; |
| 1651 | + } |
| 1652 | + |
| 1653 | + add_next_index_stringl(zdst, key, keylen); |
| 1654 | + efree(key); |
| 1655 | + |
| 1656 | + array_init_size(&zele, elements); |
| 1657 | + |
| 1658 | + if (ctx == PHPREDIS_CTX_PTR) { |
| 1659 | + for (int i = 0; i < elements; i++) { |
| 1660 | + if (read_mbulk_header(redis_sock, &subele) < 0 || subele != 2) { |
| 1661 | + zval_dtor(&zele); |
| 1662 | + goto fail; |
| 1663 | + } |
| 1664 | + redis_mbulk_reply_loop(redis_sock, &zele, subele, UNSERIALIZE_KEYS); |
| 1665 | + } |
| 1666 | + |
| 1667 | + array_zip_values_and_scores(redis_sock, &zele, SCORE_DECODE_DOUBLE); |
| 1668 | + } else { |
| 1669 | + redis_mbulk_reply_loop(redis_sock, &zele, elements, UNSERIALIZE_ALL); |
| 1670 | + } |
| 1671 | + |
| 1672 | + add_next_index_zval(zdst, &zele); |
| 1673 | + |
| 1674 | + return SUCCESS; |
| 1675 | + |
| 1676 | +fail: |
| 1677 | + zval_dtor(zdst); |
| 1678 | + ZVAL_FALSE(zdst); |
| 1679 | + |
| 1680 | + return FAILURE; |
| 1681 | +} |
| 1682 | + |
| 1683 | +PHP_REDIS_API int |
| 1684 | +redis_mpop_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, |
| 1685 | + zval *z_tab, void *ctx) |
| 1686 | +{ |
| 1687 | + int elements, res = SUCCESS; |
| 1688 | + zval zret = {0}; |
| 1689 | + |
| 1690 | + if (read_mbulk_header(redis_sock, &elements) == FAILURE || |
| 1691 | + redis_read_mpop_response(redis_sock, &zret, elements, ctx) == FAILURE) |
| 1692 | + { |
| 1693 | + res = FAILURE; |
| 1694 | + ZVAL_FALSE(&zret); |
| 1695 | + } |
| 1696 | + |
| 1697 | + if (IS_ATOMIC(redis_sock)) { |
| 1698 | + RETVAL_ZVAL(&zret, 0, 0); |
| 1699 | + } else { |
| 1700 | + add_next_index_zval(z_tab, &zret); |
| 1701 | + } |
| 1702 | + |
| 1703 | + return res; |
| 1704 | +} |
| 1705 | + |
1620 | 1706 | PHP_REDIS_API int |
1621 | 1707 | redis_geosearch_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, |
1622 | 1708 | zval *z_tab, void *ctx) |
|
0 commit comments