1 /*
2   +----------------------------------------------------------------------+
3   | Swoole                                                               |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 2.0 of the Apache license,    |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.apache.org/licenses/LICENSE-2.0.html                      |
9   | If you did not receive a copy of the Apache2.0 license and are unable|
10   | to obtain it through the world-wide-web, please send a note to       |
11   | license@swoole.com so we can mail you a copy immediately.            |
12   +----------------------------------------------------------------------+
13   | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
14   +----------------------------------------------------------------------+
15 */
16 
17 #include "php_swoole_cxx.h"
18 
19 #include "thirdparty/hiredis/hiredis.h"
20 
21 #include "ext/standard/php_var.h"
22 
23 using swoole::coroutine::Socket;
24 using namespace swoole;
25 
26 #define SW_REDIS_COMMAND_ALLOC_ARGS_ARR zval *z_args = (zval *) emalloc(argc * sizeof(zval));
27 #define SW_REDIS_COMMAND_ARGS_TYPE(arg) Z_TYPE(arg)
28 #define SW_REDIS_COMMAND_ARGS_LVAL(arg) Z_LVAL(arg)
29 #define SW_REDIS_COMMAND_ARGS_DVAL(arg) Z_DVAL(arg)
30 #define SW_REDIS_COMMAND_ARGS_ARRVAL(arg) Z_ARRVAL(arg)
31 #define SW_REDIS_COMMAND_ARGS_STRVAL(arg) Z_STRVAL(arg)
32 #define SW_REDIS_COMMAND_ARGS_STRLEN(arg) Z_STRLEN(arg)
33 #define SW_REDIS_COMMAND_ARGS_REF(arg) &arg
34 
35 #define SW_REDIS_COMMAND_BUFFER_SIZE 64
36 #define SW_BITOP_MIN_OFFSET 0
37 #define SW_BITOP_MAX_OFFSET 4294967295
38 #define SW_REDIS_TYPE_NOT_FOUND 0
39 #define SW_REDIS_TYPE_STRING 1
40 #define SW_REDIS_TYPE_SET 2
41 #define SW_REDIS_TYPE_LIST 3
42 #define SW_REDIS_TYPE_ZSET 4
43 #define SW_REDIS_TYPE_HASH 5
44 
45 /* The same errCode define with hiredis */
46 enum swRedisError {
47     SW_REDIS_ERR_IO = 1,       /* Error in read or write */
48     SW_REDIS_ERR_OTHER = 2,    /* Everything else... */
49     SW_REDIS_ERR_EOF = 3,      /* End of file */
50     SW_REDIS_ERR_PROTOCOL = 4, /* Protocol error */
51     SW_REDIS_ERR_OOM = 5,      /* Out of memory */
52     SW_REDIS_ERR_CLOSED = 6,   /* Closed */
53     SW_REDIS_ERR_NOAUTH = 7,   /* Authentication required */
54     SW_REDIS_ERR_ALLOC = 8,    /* Alloc failed */
55 };
56 
57 /* Extended SET argument detection */
58 // clang-format off
59 #define IS_EX_ARG(a) \
60     ((a[0]=='e' || a[0]=='E') && (a[1]=='x' || a[1]=='X') && a[2]=='\0')
61 #define IS_PX_ARG(a) \
62     ((a[0]=='p' || a[0]=='P') && (a[1]=='x' || a[1]=='X') && a[2]=='\0')
63 #define IS_NX_ARG(a) \
64     ((a[0]=='n' || a[0]=='N') && (a[1]=='x' || a[1]=='X') && a[2]=='\0')
65 #define IS_XX_ARG(a) \
66     ((a[0]=='x' || a[0]=='X') && (a[1]=='x' || a[1]=='X') && a[2]=='\0')
67 
68 static zend_class_entry *swoole_redis_coro_ce;
69 static zend_object_handlers swoole_redis_coro_handlers;
70 
71 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_construct, 0, 0, 0)
72     ZEND_ARG_INFO(0, config)
73 ZEND_END_ARG_INFO()
74 
75 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_connect, 0, 0, 1)
76     ZEND_ARG_INFO(0, host)
77     ZEND_ARG_INFO(0, port)
78     ZEND_ARG_INFO(0, serialize)
79 ZEND_END_ARG_INFO()
80 
81 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setOptions, 0, 0, 1)
82     ZEND_ARG_INFO(0, options)
83 ZEND_END_ARG_INFO()
84 
85 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setDefer, 0, 0, 1)
86     ZEND_ARG_INFO(0, defer)
87 ZEND_END_ARG_INFO()
88 
89 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_void, 0, 0, 0)
90 ZEND_END_ARG_INFO()
91 
92 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_key, 0, 0, 1)
93     ZEND_ARG_INFO(0, key)
94 ZEND_END_ARG_INFO()
95 
96 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_key_value, 0, 0, 2)
97     ZEND_ARG_INFO(0, key)
98     ZEND_ARG_INFO(0, value)
99 ZEND_END_ARG_INFO()
100 
101 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_key_long, 0, 0, 2)
102     ZEND_ARG_INFO(0, key)
103     ZEND_ARG_INFO(0, integer)
104 ZEND_END_ARG_INFO()
105 
106 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_request, 0, 0, 1)
107     ZEND_ARG_ARRAY_INFO(0, params, 0)
108 ZEND_END_ARG_INFO()
109 
110 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_append, 0, 0, 2)
111     ZEND_ARG_INFO(0, key)
112     ZEND_ARG_INFO(0, value)
113 ZEND_END_ARG_INFO()
114 
115 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_auth, 0, 0, 1)
116     ZEND_ARG_INFO(0, password)
117 ZEND_END_ARG_INFO()
118 
119 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bgSave, 0, 0, 0)
120 ZEND_END_ARG_INFO()
121 
122 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bgrewriteaof, 0, 0, 0)
123 ZEND_END_ARG_INFO()
124 
125 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bitcount, 0, 0, 1)
126     ZEND_ARG_INFO(0, key)
127 ZEND_END_ARG_INFO()
128 
129 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bitop, 0, 0, 3)
130     ZEND_ARG_INFO(0, operation)
131     ZEND_ARG_INFO(0, ret_key)
132     ZEND_ARG_INFO(0, key)
133     ZEND_ARG_INFO(0, other_keys)
134 ZEND_END_ARG_INFO()
135 
136 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_blPop, 0, 0, 2)
137     ZEND_ARG_INFO(0, key)
138     ZEND_ARG_INFO(0, timeout_or_key)
139     ZEND_ARG_INFO(0, extra_args)
140 ZEND_END_ARG_INFO()
141 
142 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_brPop, 0, 0, 2)
143     ZEND_ARG_INFO(0, key)
144     ZEND_ARG_INFO(0, timeout_or_key)
145     ZEND_ARG_INFO(0, extra_args)
146 ZEND_END_ARG_INFO()
147 
148 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_brpoplpush, 0, 0, 3)
149     ZEND_ARG_INFO(0, src)
150     ZEND_ARG_INFO(0, dst)
151     ZEND_ARG_INFO(0, timeout)
152 ZEND_END_ARG_INFO()
153 
154 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_close, 0, 0, 0)
155 ZEND_END_ARG_INFO()
156 
157 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_dbSize, 0, 0, 0)
158 ZEND_END_ARG_INFO()
159 
160 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_debug, 0, 0, 1)
161     ZEND_ARG_INFO(0, key)
162 ZEND_END_ARG_INFO()
163 
164 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_decr, 0, 0, 1)
165     ZEND_ARG_INFO(0, key)
166 ZEND_END_ARG_INFO()
167 
168 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_decrBy, 0, 0, 2)
169     ZEND_ARG_INFO(0, key)
170     ZEND_ARG_INFO(0, value)
171 ZEND_END_ARG_INFO()
172 
173 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_dump, 0, 0, 1)
174     ZEND_ARG_INFO(0, key)
175 ZEND_END_ARG_INFO()
176 
177 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_eval, 0, 0, 1)
178     ZEND_ARG_INFO(0, script)
179     ZEND_ARG_INFO(0, args)
180     ZEND_ARG_INFO(0, num_keys)
181 ZEND_END_ARG_INFO()
182 
183 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_evalsha, 0, 0, 1)
184     ZEND_ARG_INFO(0, script_sha)
185     ZEND_ARG_INFO(0, args)
186     ZEND_ARG_INFO(0, num_keys)
187 ZEND_END_ARG_INFO()
188 
189 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_exec, 0, 0, 0)
190 ZEND_END_ARG_INFO()
191 
192 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_exists, 0, 0, 1)
193     ZEND_ARG_INFO(0, key)
194     ZEND_ARG_INFO(0, other_keys)
195 ZEND_END_ARG_INFO()
196 
197 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_expireAt, 0, 0, 2)
198     ZEND_ARG_INFO(0, key)
199     ZEND_ARG_INFO(0, timestamp)
200 ZEND_END_ARG_INFO()
201 
202 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_flushAll, 0, 0, 0)
203 ZEND_END_ARG_INFO()
204 
205 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_flushDB, 0, 0, 0)
206 ZEND_END_ARG_INFO()
207 
208 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_get, 0, 0, 1)
209     ZEND_ARG_INFO(0, key)
210 ZEND_END_ARG_INFO()
211 
212 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_getBit, 0, 0, 2)
213     ZEND_ARG_INFO(0, key)
214     ZEND_ARG_INFO(0, offset)
215 ZEND_END_ARG_INFO()
216 
217 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_getKeys, 0, 0, 1)
218     ZEND_ARG_INFO(0, pattern)
219 ZEND_END_ARG_INFO()
220 
221 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_getRange, 0, 0, 3)
222     ZEND_ARG_INFO(0, key)
223     ZEND_ARG_INFO(0, start)
224     ZEND_ARG_INFO(0, end)
225 ZEND_END_ARG_INFO()
226 
227 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_getSet, 0, 0, 2)
228     ZEND_ARG_INFO(0, key)
229     ZEND_ARG_INFO(0, value)
230 ZEND_END_ARG_INFO()
231 
232 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hDel, 0, 0, 2)
233     ZEND_ARG_INFO(0, key)
234     ZEND_ARG_INFO(0, member)
235     ZEND_ARG_INFO(0, other_members)
236 ZEND_END_ARG_INFO()
237 
238 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hExists, 0, 0, 2)
239     ZEND_ARG_INFO(0, key)
240     ZEND_ARG_INFO(0, member)
241 ZEND_END_ARG_INFO()
242 
243 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hGet, 0, 0, 2)
244     ZEND_ARG_INFO(0, key)
245     ZEND_ARG_INFO(0, member)
246 ZEND_END_ARG_INFO()
247 
248 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hGetAll, 0, 0, 1)
249     ZEND_ARG_INFO(0, key)
250 ZEND_END_ARG_INFO()
251 
252 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hIncrBy, 0, 0, 3)
253     ZEND_ARG_INFO(0, key)
254     ZEND_ARG_INFO(0, member)
255     ZEND_ARG_INFO(0, value)
256 ZEND_END_ARG_INFO()
257 
258 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hIncrByFloat, 0, 0, 3)
259     ZEND_ARG_INFO(0, key)
260     ZEND_ARG_INFO(0, member)
261     ZEND_ARG_INFO(0, value)
262 ZEND_END_ARG_INFO()
263 
264 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hKeys, 0, 0, 1)
265     ZEND_ARG_INFO(0, key)
266 ZEND_END_ARG_INFO()
267 
268 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hLen, 0, 0, 1)
269     ZEND_ARG_INFO(0, key)
270 ZEND_END_ARG_INFO()
271 
272 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hMget, 0, 0, 2)
273     ZEND_ARG_INFO(0, key)
274     ZEND_ARG_INFO(0, keys)
275 ZEND_END_ARG_INFO()
276 
277 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hMset, 0, 0, 2)
278     ZEND_ARG_INFO(0, key)
279     ZEND_ARG_INFO(0, pairs)
280 ZEND_END_ARG_INFO()
281 
282 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hSet, 0, 0, 3)
283     ZEND_ARG_INFO(0, key)
284     ZEND_ARG_INFO(0, member)
285     ZEND_ARG_INFO(0, value)
286 ZEND_END_ARG_INFO()
287 
288 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hSetNx, 0, 0, 3)
289     ZEND_ARG_INFO(0, key)
290     ZEND_ARG_INFO(0, member)
291     ZEND_ARG_INFO(0, value)
292 ZEND_END_ARG_INFO()
293 
294 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_hVals, 0, 0, 1)
295     ZEND_ARG_INFO(0, key)
296 ZEND_END_ARG_INFO()
297 
298 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_incr, 0, 0, 1)
299     ZEND_ARG_INFO(0, key)
300 ZEND_END_ARG_INFO()
301 
302 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_incrBy, 0, 0, 2)
303     ZEND_ARG_INFO(0, key)
304     ZEND_ARG_INFO(0, value)
305 ZEND_END_ARG_INFO()
306 
307 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_incrByFloat, 0, 0, 2)
308     ZEND_ARG_INFO(0, key)
309     ZEND_ARG_INFO(0, value)
310 ZEND_END_ARG_INFO()
311 
312 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lGet, 0, 0, 2)
313     ZEND_ARG_INFO(0, key)
314     ZEND_ARG_INFO(0, index)
315 ZEND_END_ARG_INFO()
316 
317 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lGetRange, 0, 0, 3)
318     ZEND_ARG_INFO(0, key)
319     ZEND_ARG_INFO(0, start)
320     ZEND_ARG_INFO(0, end)
321 ZEND_END_ARG_INFO()
322 
323 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lInsert, 0, 0, 4)
324     ZEND_ARG_INFO(0, key)
325     ZEND_ARG_INFO(0, position)
326     ZEND_ARG_INFO(0, pivot)
327     ZEND_ARG_INFO(0, value)
328 ZEND_END_ARG_INFO()
329 
330 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lPop, 0, 0, 1)
331     ZEND_ARG_INFO(0, key)
332 ZEND_END_ARG_INFO()
333 
334 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lPush, 0, 0, 2)
335     ZEND_ARG_INFO(0, key)
336     ZEND_ARG_INFO(0, value)
337 ZEND_END_ARG_INFO()
338 
339 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lPushx, 0, 0, 2)
340     ZEND_ARG_INFO(0, key)
341     ZEND_ARG_INFO(0, value)
342 ZEND_END_ARG_INFO()
343 
344 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lRemove, 0, 0, 3)
345     ZEND_ARG_INFO(0, key)
346     ZEND_ARG_INFO(0, value)
347     ZEND_ARG_INFO(0, count)
348 ZEND_END_ARG_INFO()
349 
350 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lSet, 0, 0, 3)
351     ZEND_ARG_INFO(0, key)
352     ZEND_ARG_INFO(0, index)
353     ZEND_ARG_INFO(0, value)
354 ZEND_END_ARG_INFO()
355 
356 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lSize, 0, 0, 1)
357     ZEND_ARG_INFO(0, key)
358 ZEND_END_ARG_INFO()
359 
360 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lastSave, 0, 0, 0)
361 ZEND_END_ARG_INFO()
362 
363 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_listTrim, 0, 0, 3)
364     ZEND_ARG_INFO(0, key)
365     ZEND_ARG_INFO(0, start)
366     ZEND_ARG_INFO(0, stop)
367 ZEND_END_ARG_INFO()
368 
369 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_move, 0, 0, 2)
370     ZEND_ARG_INFO(0, key)
371     ZEND_ARG_INFO(0, dbindex)
372 ZEND_END_ARG_INFO()
373 
374 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_mset, 0, 0, 1)
375     ZEND_ARG_INFO(0, pairs)
376 ZEND_END_ARG_INFO()
377 
378 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_msetnx, 0, 0, 1)
379     ZEND_ARG_INFO(0, pairs)
380 ZEND_END_ARG_INFO()
381 
382 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_multi, 0, 0, 0)
383 ZEND_END_ARG_INFO()
384 
385 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_persist, 0, 0, 1)
386     ZEND_ARG_INFO(0, key)
387 ZEND_END_ARG_INFO()
388 
389 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pexpire, 0, 0, 2)
390     ZEND_ARG_INFO(0, key)
391     ZEND_ARG_INFO(0, timestamp)
392 ZEND_END_ARG_INFO()
393 
394 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pexpireAt, 0, 0, 2)
395     ZEND_ARG_INFO(0, key)
396     ZEND_ARG_INFO(0, timestamp)
397 ZEND_END_ARG_INFO()
398 
399 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pfadd, 0, 0, 2)
400     ZEND_ARG_INFO(0, key)
401     ZEND_ARG_INFO(0, elements)
402 ZEND_END_ARG_INFO()
403 
404 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pfcount, 0, 0, 1)
405     ZEND_ARG_INFO(0, key)
406 ZEND_END_ARG_INFO()
407 
408 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pfmerge, 0, 0, 2)
409     ZEND_ARG_INFO(0, dstkey)
410     ZEND_ARG_INFO(0, keys)
411 ZEND_END_ARG_INFO()
412 
413 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_ping, 0, 0, 0)
414 ZEND_END_ARG_INFO()
415 
416 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_psetex, 0, 0, 3)
417     ZEND_ARG_INFO(0, key)
418     ZEND_ARG_INFO(0, expire)
419     ZEND_ARG_INFO(0, value)
420 ZEND_END_ARG_INFO()
421 
422 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_psubscribe, 0, 0, 1)
423     ZEND_ARG_INFO(0, patterns)
424 ZEND_END_ARG_INFO()
425 
426 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_punsubscribe, 0, 0, 1)
427     ZEND_ARG_INFO(0, patterns)
428 ZEND_END_ARG_INFO()
429 
430 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_pttl, 0, 0, 1)
431     ZEND_ARG_INFO(0, key)
432 ZEND_END_ARG_INFO()
433 
434 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_publish, 0, 0, 2)
435     ZEND_ARG_INFO(0, channel)
436     ZEND_ARG_INFO(0, message)
437 ZEND_END_ARG_INFO()
438 
439 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_rPop, 0, 0, 1)
440     ZEND_ARG_INFO(0, key)
441 ZEND_END_ARG_INFO()
442 
443 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_rPush, 0, 0, 2)
444     ZEND_ARG_INFO(0, key)
445     ZEND_ARG_INFO(0, value)
446 ZEND_END_ARG_INFO()
447 
448 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_rPushx, 0, 0, 2)
449     ZEND_ARG_INFO(0, key)
450     ZEND_ARG_INFO(0, value)
451 ZEND_END_ARG_INFO()
452 
453 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_randomKey, 0, 0, 0)
454 ZEND_END_ARG_INFO()
455 
456 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_renameKey, 0, 0, 2)
457     ZEND_ARG_INFO(0, key)
458     ZEND_ARG_INFO(0, newkey)
459 ZEND_END_ARG_INFO()
460 
461 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_renameNx, 0, 0, 2)
462     ZEND_ARG_INFO(0, key)
463     ZEND_ARG_INFO(0, newkey)
464 ZEND_END_ARG_INFO()
465 
466 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_restore, 0, 0, 3)
467     ZEND_ARG_INFO(0, ttl)
468     ZEND_ARG_INFO(0, key)
469     ZEND_ARG_INFO(0, value)
470 ZEND_END_ARG_INFO()
471 
472 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_role, 0, 0, 0)
473 ZEND_END_ARG_INFO()
474 
475 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_rpoplpush, 0, 0, 2)
476     ZEND_ARG_INFO(0, src)
477     ZEND_ARG_INFO(0, dst)
478 ZEND_END_ARG_INFO()
479 
480 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sAdd, 0, 0, 2)
481     ZEND_ARG_INFO(0, key)
482     ZEND_ARG_INFO(0, value)
483 ZEND_END_ARG_INFO()
484 
485 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sContains, 0, 0, 2)
486     ZEND_ARG_INFO(0, key)
487     ZEND_ARG_INFO(0, value)
488 ZEND_END_ARG_INFO()
489 
490 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sDiff, 0, 0, 1)
491     ZEND_ARG_INFO(0, key)
492     ZEND_ARG_INFO(0, other_keys)
493 ZEND_END_ARG_INFO()
494 
495 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sDiffStore, 0, 0, 2)
496     ZEND_ARG_INFO(0, dst)
497     ZEND_ARG_INFO(0, key)
498     ZEND_ARG_INFO(0, other_keys)
499 ZEND_END_ARG_INFO()
500 
501 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sInter, 0, 0, 1)
502     ZEND_ARG_INFO(0, key)
503     ZEND_ARG_INFO(0, other_keys)
504 ZEND_END_ARG_INFO()
505 
506 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sInterStore, 0, 0, 2)
507     ZEND_ARG_INFO(0, dst)
508     ZEND_ARG_INFO(0, key)
509     ZEND_ARG_INFO(0, other_keys)
510 ZEND_END_ARG_INFO()
511 
512 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sMembers, 0, 0, 1)
513     ZEND_ARG_INFO(0, key)
514 ZEND_END_ARG_INFO()
515 
516 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sMove, 0, 0, 3)
517     ZEND_ARG_INFO(0, src)
518     ZEND_ARG_INFO(0, dst)
519     ZEND_ARG_INFO(0, value)
520 ZEND_END_ARG_INFO()
521 
522 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sPop, 0, 0, 1)
523     ZEND_ARG_INFO(0, key)
524 ZEND_END_ARG_INFO()
525 
526 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sRandMember, 0, 0, 1)
527     ZEND_ARG_INFO(0, key)
528     ZEND_ARG_INFO(0, count)
529 ZEND_END_ARG_INFO()
530 
531 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sRemove, 0, 0, 2)
532     ZEND_ARG_INFO(0, key)
533     ZEND_ARG_INFO(0, value)
534 ZEND_END_ARG_INFO()
535 
536 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sSize, 0, 0, 1)
537     ZEND_ARG_INFO(0, key)
538 ZEND_END_ARG_INFO()
539 
540 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sUnion, 0, 0, 1)
541     ZEND_ARG_INFO(0, key)
542     ZEND_ARG_INFO(0, other_keys)
543 ZEND_END_ARG_INFO()
544 
545 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_sUnionStore, 0, 0, 2)
546     ZEND_ARG_INFO(0, dst)
547     ZEND_ARG_INFO(0, key)
548     ZEND_ARG_INFO(0, other_keys)
549 ZEND_END_ARG_INFO()
550 
551 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_save, 0, 0, 0)
552 ZEND_END_ARG_INFO()
553 
554 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_script, 0, 0, 1)
555     ZEND_ARG_INFO(0, cmd)
556     ZEND_ARG_INFO(0, args)
557 ZEND_END_ARG_INFO()
558 
559 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_select, 0, 0, 1)
560     ZEND_ARG_INFO(0, dbindex)
561 ZEND_END_ARG_INFO()
562 
563 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_set, 0, 0, 2)
564     ZEND_ARG_INFO(0, key)
565     ZEND_ARG_INFO(0, value)
566     ZEND_ARG_INFO(0, timeout)
567     ZEND_ARG_INFO(0, opt)
568 ZEND_END_ARG_INFO()
569 
570 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setBit, 0, 0, 3)
571     ZEND_ARG_INFO(0, key)
572     ZEND_ARG_INFO(0, offset)
573     ZEND_ARG_INFO(0, value)
574 ZEND_END_ARG_INFO()
575 
576 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setRange, 0, 0, 3)
577     ZEND_ARG_INFO(0, key)
578     ZEND_ARG_INFO(0, offset)
579     ZEND_ARG_INFO(0, value)
580 ZEND_END_ARG_INFO()
581 
582 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setTimeout, 0, 0, 2)
583     ZEND_ARG_INFO(0, key)
584     ZEND_ARG_INFO(0, timeout)
585 ZEND_END_ARG_INFO()
586 
587 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setex, 0, 0, 3)
588     ZEND_ARG_INFO(0, key)
589     ZEND_ARG_INFO(0, expire)
590     ZEND_ARG_INFO(0, value)
591 ZEND_END_ARG_INFO()
592 
593 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_setnx, 0, 0, 2)
594     ZEND_ARG_INFO(0, key)
595     ZEND_ARG_INFO(0, value)
596 ZEND_END_ARG_INFO()
597 
598 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_strlen, 0, 0, 1)
599     ZEND_ARG_INFO(0, key)
600 ZEND_END_ARG_INFO()
601 
602 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_subscribe, 0, 0, 1)
603     ZEND_ARG_INFO(0, channels)
604 ZEND_END_ARG_INFO()
605 
606 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_unsubscribe, 0, 0, 1)
607     ZEND_ARG_INFO(0, channels)
608 ZEND_END_ARG_INFO()
609 
610 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_time, 0, 0, 0)
611 ZEND_END_ARG_INFO()
612 
613 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_ttl, 0, 0, 1)
614     ZEND_ARG_INFO(0, key)
615 ZEND_END_ARG_INFO()
616 
617 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_type, 0, 0, 1)
618     ZEND_ARG_INFO(0, key)
619 ZEND_END_ARG_INFO()
620 
621 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_unwatch, 0, 0, 0)
622 ZEND_END_ARG_INFO()
623 
624 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_watch, 0, 0, 1)
625     ZEND_ARG_INFO(0, key)
626     ZEND_ARG_INFO(0, other_keys)
627 ZEND_END_ARG_INFO()
628 
629 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zAdd, 0, 0, 3)
630     ZEND_ARG_INFO(0, key)
631     ZEND_ARG_INFO(0, score)
632     ZEND_ARG_INFO(0, value)
633 ZEND_END_ARG_INFO()
634 
635 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zPopMin, 0, 0, 2)
636     ZEND_ARG_INFO(0, key)
637     ZEND_ARG_INFO(0, count)
638 ZEND_END_ARG_INFO()
639 
640 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zPopMax, 0, 0, 2)
641     ZEND_ARG_INFO(0, key)
642     ZEND_ARG_INFO(0, count)
643 ZEND_END_ARG_INFO()
644 
645 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bzPopMin, 0, 0, 2)
646     ZEND_ARG_INFO(0, key)
647     ZEND_ARG_INFO(0, timeout_or_key)
648     ZEND_ARG_INFO(0, extra_args)
649 ZEND_END_ARG_INFO()
650 
651 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_bzPopMax, 0, 0, 2)
652     ZEND_ARG_INFO(0, key)
653     ZEND_ARG_INFO(0, timeout_or_key)
654     ZEND_ARG_INFO(0, extra_args)
655 ZEND_END_ARG_INFO()
656 
657 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zCard, 0, 0, 1)
658     ZEND_ARG_INFO(0, key)
659 ZEND_END_ARG_INFO()
660 
661 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zCount, 0, 0, 3)
662     ZEND_ARG_INFO(0, key)
663     ZEND_ARG_INFO(0, min)
664     ZEND_ARG_INFO(0, max)
665 ZEND_END_ARG_INFO()
666 
667 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zDelete, 0, 0, 2)
668     ZEND_ARG_INFO(0, key)
669     ZEND_ARG_INFO(0, member)
670     ZEND_ARG_INFO(0, other_members)
671 ZEND_END_ARG_INFO()
672 
673 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zDeleteRangeByRank, 0, 0, 3)
674     ZEND_ARG_INFO(0, key)
675     ZEND_ARG_INFO(0, start)
676     ZEND_ARG_INFO(0, end)
677 ZEND_END_ARG_INFO()
678 
679 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zDeleteRangeByScore, 0, 0, 3)
680     ZEND_ARG_INFO(0, key)
681     ZEND_ARG_INFO(0, min)
682     ZEND_ARG_INFO(0, max)
683 ZEND_END_ARG_INFO()
684 
685 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zIncrBy, 0, 0, 3)
686     ZEND_ARG_INFO(0, key)
687     ZEND_ARG_INFO(0, value)
688     ZEND_ARG_INFO(0, member)
689 ZEND_END_ARG_INFO()
690 
691 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zInter, 0, 0, 2)
692     ZEND_ARG_INFO(0, key)
693     ZEND_ARG_INFO(0, keys)
694     ZEND_ARG_INFO(0, weights)
695     ZEND_ARG_INFO(0, aggregate)
696 ZEND_END_ARG_INFO()
697 
698 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRange, 0, 0, 3)
699     ZEND_ARG_INFO(0, key)
700     ZEND_ARG_INFO(0, start)
701     ZEND_ARG_INFO(0, end)
702     ZEND_ARG_INFO(0, scores)
703 ZEND_END_ARG_INFO()
704 
705 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRangeByLex, 0, 0, 3)
706     ZEND_ARG_INFO(0, key)
707     ZEND_ARG_INFO(0, min)
708     ZEND_ARG_INFO(0, max)
709     ZEND_ARG_INFO(0, offset)
710     ZEND_ARG_INFO(0, limit)
711 ZEND_END_ARG_INFO()
712 
713 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRangeByScore, 0, 0, 3)
714     ZEND_ARG_INFO(0, key)
715     ZEND_ARG_INFO(0, start)
716     ZEND_ARG_INFO(0, end)
717     ZEND_ARG_INFO(0, options)
718 ZEND_END_ARG_INFO()
719 
720 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRank, 0, 0, 2)
721     ZEND_ARG_INFO(0, key)
722     ZEND_ARG_INFO(0, member)
723 ZEND_END_ARG_INFO()
724 
725 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRevRange, 0, 0, 3)
726     ZEND_ARG_INFO(0, key)
727     ZEND_ARG_INFO(0, start)
728     ZEND_ARG_INFO(0, end)
729     ZEND_ARG_INFO(0, scores)
730 ZEND_END_ARG_INFO()
731 
732 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRevRangeByLex, 0, 0, 3)
733     ZEND_ARG_INFO(0, key)
734     ZEND_ARG_INFO(0, min)
735     ZEND_ARG_INFO(0, max)
736     ZEND_ARG_INFO(0, offset)
737     ZEND_ARG_INFO(0, limit)
738 ZEND_END_ARG_INFO()
739 
740 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRevRangeByScore, 0, 0, 3)
741     ZEND_ARG_INFO(0, key)
742     ZEND_ARG_INFO(0, start)
743     ZEND_ARG_INFO(0, end)
744     ZEND_ARG_INFO(0, options)
745 ZEND_END_ARG_INFO()
746 
747 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRevRank, 0, 0, 2)
748     ZEND_ARG_INFO(0, key)
749     ZEND_ARG_INFO(0, member)
750 ZEND_END_ARG_INFO()
751 
752 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zScore, 0, 0, 2)
753     ZEND_ARG_INFO(0, key)
754     ZEND_ARG_INFO(0, member)
755 ZEND_END_ARG_INFO()
756 
757 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zUnion, 0, 0, 2)
758     ZEND_ARG_INFO(0, key)
759     ZEND_ARG_INFO(0, keys)
760     ZEND_ARG_INFO(0, weights)
761     ZEND_ARG_INFO(0, aggregate)
762 ZEND_END_ARG_INFO()
763 
764 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_del, 0, 0, 1)
765     ZEND_ARG_INFO(0, key)
766     ZEND_ARG_INFO(0, other_keys)
767 ZEND_END_ARG_INFO()
768 
769 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lLen, 0, 0, 1)
770     ZEND_ARG_INFO(0, key)
771 ZEND_END_ARG_INFO()
772 
773 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lrange, 0, 0, 3)
774     ZEND_ARG_INFO(0, key)
775     ZEND_ARG_INFO(0, start)
776     ZEND_ARG_INFO(0, end)
777 ZEND_END_ARG_INFO()
778 
779 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_lrem, 0, 0, 3)
780     ZEND_ARG_INFO(0, key)
781     ZEND_ARG_INFO(0, value)
782     ZEND_ARG_INFO(0, count)
783 ZEND_END_ARG_INFO()
784 
785 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_ltrim, 0, 0, 3)
786     ZEND_ARG_INFO(0, key)
787     ZEND_ARG_INFO(0, start)
788     ZEND_ARG_INFO(0, stop)
789 ZEND_END_ARG_INFO()
790 
791 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_mget, 0, 0, 1)
792     ZEND_ARG_INFO(0, keys)
793 ZEND_END_ARG_INFO()
794 
795 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_rename, 0, 0, 2)
796     ZEND_ARG_INFO(0, key)
797     ZEND_ARG_INFO(0, newkey)
798 ZEND_END_ARG_INFO()
799 
800 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_scard, 0, 0, 1)
801     ZEND_ARG_INFO(0, key)
802 ZEND_END_ARG_INFO()
803 
804 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRem, 0, 0, 2)
805     ZEND_ARG_INFO(0, key)
806     ZEND_ARG_INFO(0, member)
807     ZEND_ARG_INFO(0, other_members)
808 ZEND_END_ARG_INFO()
809 
810 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRemRangeByRank, 0, 0, 3)
811     ZEND_ARG_INFO(0, key)
812     ZEND_ARG_INFO(0, min)
813     ZEND_ARG_INFO(0, max)
814 ZEND_END_ARG_INFO()
815 
816 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRemRangeByScore, 0, 0, 3)
817     ZEND_ARG_INFO(0, key)
818     ZEND_ARG_INFO(0, min)
819     ZEND_ARG_INFO(0, max)
820 ZEND_END_ARG_INFO()
821 
822 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zRemove, 0, 0, 2)
823     ZEND_ARG_INFO(0, key)
824     ZEND_ARG_INFO(0, member)
825     ZEND_ARG_INFO(0, other_members)
826 ZEND_END_ARG_INFO()
827 
828 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zSize, 0, 0, 1)
829     ZEND_ARG_INFO(0, key)
830 ZEND_END_ARG_INFO()
831 
832 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zinterstore, 0, 0, 2)
833     ZEND_ARG_INFO(0, key)
834     ZEND_ARG_INFO(0, keys)
835     ZEND_ARG_INFO(0, weights)
836     ZEND_ARG_INFO(0, aggregate)
837 ZEND_END_ARG_INFO()
838 
839 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zunionstore, 0, 0, 2)
840     ZEND_ARG_INFO(0, key)
841     ZEND_ARG_INFO(0, keys)
842     ZEND_ARG_INFO(0, weights)
843     ZEND_ARG_INFO(0, aggregate)
844 ZEND_END_ARG_INFO()
845 
846 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xLen, 0, 0, 1)
847     ZEND_ARG_INFO(0, key)
848 ZEND_END_ARG_INFO()
849 
850 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAdd, 0, 0, 3)
851     ZEND_ARG_INFO(0, key)
852     ZEND_ARG_INFO(0, id)
853     ZEND_ARG_INFO(0, pairs)
854     ZEND_ARG_INFO(0, options)
855 ZEND_END_ARG_INFO()
856 
857 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRead, 0, 0, 1)
858     ZEND_ARG_INFO(0, streams)
859     ZEND_ARG_INFO(0, options)
860 ZEND_END_ARG_INFO()
861 
862 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xDel, 0, 0, 2)
863     ZEND_ARG_INFO(0, key)
864     ZEND_ARG_INFO(0, id)
865 ZEND_END_ARG_INFO()
866 
867 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRange, 0, 0, 3)
868     ZEND_ARG_INFO(0, key)
869     ZEND_ARG_INFO(0, start)
870     ZEND_ARG_INFO(0, end)
871     ZEND_ARG_INFO(0, count)
872 ZEND_END_ARG_INFO()
873 
874 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRevRange, 0, 0, 3)
875     ZEND_ARG_INFO(0, key)
876     ZEND_ARG_INFO(0, start)
877     ZEND_ARG_INFO(0, end)
878     ZEND_ARG_INFO(0, count)
879 ZEND_END_ARG_INFO()
880 
881 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xTrim, 0, 0, 1)
882     ZEND_ARG_INFO(0, key)
883     ZEND_ARG_INFO(0, options)
884 ZEND_END_ARG_INFO()
885 
886 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupCreate, 0, 0, 3)
887     ZEND_ARG_INFO(0, key)
888     ZEND_ARG_INFO(0, group_name)
889     ZEND_ARG_INFO(0, id)
890     ZEND_ARG_INFO(0, mkstream)
891 ZEND_END_ARG_INFO()
892 
893 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupSetId, 0, 0, 3)
894     ZEND_ARG_INFO(0, key)
895     ZEND_ARG_INFO(0, group_name)
896     ZEND_ARG_INFO(0, id)
897 ZEND_END_ARG_INFO()
898 
899 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupDestroy, 0, 0, 2)
900     ZEND_ARG_INFO(0, key)
901     ZEND_ARG_INFO(0, group_name)
902 ZEND_END_ARG_INFO()
903 
904 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupCreateConsumer, 0, 0, 3)
905     ZEND_ARG_INFO(0, key)
906     ZEND_ARG_INFO(0, group_name)
907     ZEND_ARG_INFO(0, consumer_name)
908 ZEND_END_ARG_INFO()
909 
910 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupDelConsumer, 0, 0, 3)
911     ZEND_ARG_INFO(0, key)
912     ZEND_ARG_INFO(0, group_name)
913     ZEND_ARG_INFO(0, consumer_name)
914 ZEND_END_ARG_INFO()
915 
916 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xReadGroup, 0, 0, 3)
917     ZEND_ARG_INFO(0, group_name)
918     ZEND_ARG_INFO(0, consumer_name)
919     ZEND_ARG_INFO(0, streams)
920     ZEND_ARG_INFO(0, options)
921 ZEND_END_ARG_INFO()
922 
923 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xPending, 0, 0, 2)
924     ZEND_ARG_INFO(0, key)
925     ZEND_ARG_INFO(0, group_name)
926     ZEND_ARG_INFO(0, options)
927 ZEND_END_ARG_INFO()
928 
929 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAck, 0, 0, 3)
930     ZEND_ARG_INFO(0, key)
931     ZEND_ARG_INFO(0, group_name)
932     ZEND_ARG_INFO(0, id)
933 ZEND_END_ARG_INFO()
934 
935 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xClaim, 0, 0, 5)
936     ZEND_ARG_INFO(0, key)
937     ZEND_ARG_INFO(0, group_name)
938     ZEND_ARG_INFO(0, consumer_name)
939     ZEND_ARG_INFO(0, min_idle_time)
940     ZEND_ARG_INFO(0, id)
941     ZEND_ARG_INFO(0, options)
942 ZEND_END_ARG_INFO()
943 
944 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAutoClaim, 0, 0, 5)
945     ZEND_ARG_INFO(0, key)
946     ZEND_ARG_INFO(0, group_name)
947     ZEND_ARG_INFO(0, consumer_name)
948     ZEND_ARG_INFO(0, min_idle_time)
949     ZEND_ARG_INFO(0, start)
950     ZEND_ARG_INFO(0, options)
951 ZEND_END_ARG_INFO()
952 
953 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoConsumers, 0, 0, 2)
954     ZEND_ARG_INFO(0, key)
955     ZEND_ARG_INFO(0, group_name)
956 ZEND_END_ARG_INFO()
957 
958 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoGroups, 0, 0, 1)
959     ZEND_ARG_INFO(0, key)
960 ZEND_END_ARG_INFO()
961 
962 ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoStream, 0, 0, 1)
963     ZEND_ARG_INFO(0, key)
964 ZEND_END_ARG_INFO()
965 // clang-format on
966 
967 #define IS_EX_PX_ARG(a) (IS_EX_ARG(a) || IS_PX_ARG(a))
968 #define IS_NX_XX_ARG(a) (IS_NX_ARG(a) || IS_XX_ARG(a))
969 
970 struct RedisClient {
971     redisContext *context;
972     struct {
973         bool auth;
974         long db_num;
975         bool subscribe;
976     } session;
977     double connect_timeout;
978     double timeout;
979     bool serialize;
980     bool defer;
981     uint8_t reconnect_interval;
982     uint8_t reconnected_count;
983     bool auth;
984     bool compatibility_mode;
985     long database;
986     zval *zobject;
987     zval _zobject;
988     zend_object std;
989 };
990 
991 #define SW_REDIS_COMMAND_CHECK                                                                                         \
992     Coroutine::get_current_safe();                                                                                     \
993     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
994 
995 #define SW_REDIS_COMMAND_ARGV_FILL(str, str_len)                                                                       \
996     argvlen[i] = str_len;                                                                                              \
997     argv[i] = estrndup(str, str_len);                                                                                  \
998     i++;
999 
1000 #define SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(_val)                                                                \
1001     if (redis->serialize) {                                                                                            \
1002         smart_str sstr = {};                                                                                           \
1003         php_serialize_data_t s_ht;                                                                                     \
1004         PHP_VAR_SERIALIZE_INIT(s_ht);                                                                                  \
1005         php_var_serialize(&sstr, _val, &s_ht);                                                                         \
1006         argvlen[i] = (size_t) sstr.s->len;                                                                             \
1007         argv[i] = estrndup(sstr.s->val, sstr.s->len);                                                                  \
1008         zend_string_release(sstr.s);                                                                                   \
1009         PHP_VAR_SERIALIZE_DESTROY(s_ht);                                                                               \
1010     } else {                                                                                                           \
1011         zend_string *convert_str = zval_get_string(_val);                                                              \
1012         argvlen[i] = ZSTR_LEN(convert_str);                                                                            \
1013         argv[i] = estrndup(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str));                                              \
1014         zend_string_release(convert_str);                                                                              \
1015     }                                                                                                                  \
1016     i++;
1017 
1018 #define SW_REDIS_COMMAND_ALLOC_ARGV                                                                                    \
1019     size_t stack_argvlen[SW_REDIS_COMMAND_BUFFER_SIZE];                                                                \
1020     char *stack_argv[SW_REDIS_COMMAND_BUFFER_SIZE];                                                                    \
1021     size_t *argvlen;                                                                                                   \
1022     char **argv;                                                                                                       \
1023     if (argc > SW_REDIS_COMMAND_BUFFER_SIZE) {                                                                         \
1024         argvlen = (size_t *) emalloc(sizeof(size_t) * (argc));                                                         \
1025         argv = (char **) emalloc(sizeof(char *) * (argc));                                                             \
1026     } else {                                                                                                           \
1027         argvlen = stack_argvlen;                                                                                       \
1028         argv = stack_argv;                                                                                             \
1029     }
1030 
1031 #define SW_REDIS_COMMAND_INCREASE_ARGV(_new_argc)                                                                      \
1032     if (_new_argc > SW_REDIS_COMMAND_BUFFER_SIZE && _new_argc > argc) {                                                \
1033         size_t *tmp_argvlen;                                                                                           \
1034         char **tmp_argv;                                                                                               \
1035         tmp_argvlen = (size_t *) emalloc(sizeof(size_t) * (_new_argc));                                                \
1036         tmp_argv = (char **) emalloc(sizeof(char *) * (_new_argc));                                                    \
1037         for (int argc_i = 0; argc_i < argc; argc_i++) {                                                                \
1038             tmp_argvlen[argc_i] = argvlen[argc_i];                                                                     \
1039             tmp_argv[argc_i] = argv[argc_i];                                                                           \
1040         }                                                                                                              \
1041         argvlen = tmp_argvlen;                                                                                         \
1042         argv = tmp_argv;                                                                                               \
1043     }                                                                                                                  \
1044     argc = _new_argc;
1045 
1046 #define SW_REDIS_COMMAND_FREE_ARGV                                                                                     \
1047     if (argv != stack_argv) {                                                                                          \
1048         efree(argvlen);                                                                                                \
1049         efree(argv);                                                                                                   \
1050     }
1051 
1052 enum { SW_REDIS_MODE_MULTI, SW_REDIS_MODE_PIPELINE };
1053 
1054 static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_value, redisReply *reply);
1055 
php_swoole_redis_coro_fetch_object(zend_object * obj)1056 static sw_inline RedisClient *php_swoole_redis_coro_fetch_object(zend_object *obj) {
1057     return (RedisClient *) ((char *) obj - swoole_redis_coro_handlers.offset);
1058 }
1059 
php_swoole_get_redis_client(zval * zobject)1060 static sw_inline RedisClient *php_swoole_get_redis_client(zval *zobject) {
1061     RedisClient *redis = (RedisClient *) php_swoole_redis_coro_fetch_object(Z_OBJ_P(zobject));
1062     if (UNEXPECTED(!redis)) {
1063         php_swoole_fatal_error(E_ERROR, "you must call Redis constructor first");
1064     }
1065     return redis;
1066 }
1067 
swoole_redis_coro_get_socket(redisContext * context)1068 static sw_inline Socket *swoole_redis_coro_get_socket(redisContext *context) {
1069     if (context->fd > 0 && SwooleTG.reactor) {
1070         return swoole_coroutine_get_socket_object(context->fd);
1071     }
1072     return nullptr;
1073 }
1074 
swoole_redis_coro_close(RedisClient * redis)1075 static sw_inline bool swoole_redis_coro_close(RedisClient *redis) {
1076     if (redis->context) {
1077         int sockfd = redis->context->fd;
1078         Socket *socket = swoole_redis_coro_get_socket(redis->context);
1079         swoole_trace_log(SW_TRACE_REDIS_CLIENT, "redis connection closed, fd=%d", sockfd);
1080         zend_update_property_bool(swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("connected"), 0);
1081         if (!(socket && socket->has_bound())) {
1082             redisFreeKeepFd(redis->context);
1083             redis->context = nullptr;
1084             redis->session = {false, 0, false};
1085         }
1086         if (socket) {
1087             swoole_coroutine_close(sockfd);
1088         }
1089         return true;
1090     }
1091     return false;
1092 }
1093 
php_swoole_redis_coro_free_object(zend_object * object)1094 static void php_swoole_redis_coro_free_object(zend_object *object) {
1095     RedisClient *redis = php_swoole_redis_coro_fetch_object(object);
1096 
1097     if (redis && redis->context) {
1098         swoole_redis_coro_close(redis);
1099     }
1100 
1101     zend_object_std_dtor(&redis->std);
1102 }
1103 
php_swoole_redis_coro_create_object(zend_class_entry * ce)1104 static zend_object *php_swoole_redis_coro_create_object(zend_class_entry *ce) {
1105     RedisClient *redis = (RedisClient *) zend_object_alloc(sizeof(RedisClient), ce);
1106     zend_object_std_init(&redis->std, ce);
1107     object_properties_init(&redis->std, ce);
1108     redis->std.handlers = &swoole_redis_coro_handlers;
1109     return &redis->std;
1110 }
1111 
sw_redis_convert_err(int err)1112 static sw_inline int sw_redis_convert_err(int err) {
1113     switch (err) {
1114     case SW_REDIS_ERR_IO:
1115         return errno;
1116     case SW_REDIS_ERR_EOF:
1117     case SW_REDIS_ERR_CLOSED:
1118         return ECONNRESET;
1119     case SW_REDIS_ERR_OTHER:
1120         return EINVAL;
1121     case SW_REDIS_ERR_OOM:
1122     case SW_REDIS_ERR_ALLOC:
1123         return ENOMEM;
1124     case SW_REDIS_ERR_PROTOCOL:
1125         return EPROTO;
1126     case SW_REDIS_ERR_NOAUTH:
1127         return EACCES;
1128     case 0:
1129         return 0;
1130     default:
1131         return errno;
1132     }
1133 }
1134 
swoole_redis_handle_assoc_array_result(zval * return_value,bool str2double)1135 static sw_inline void swoole_redis_handle_assoc_array_result(zval *return_value, bool str2double) {
1136     zval *zkey, *zvalue;
1137     zval zret;
1138     bool is_key = false;
1139 
1140     array_init(&zret);
1141     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(return_value), zvalue) {
1142         if ((is_key = !is_key)) {
1143             zkey = zvalue;
1144         } else {
1145             if (str2double) {
1146                 convert_to_double(zvalue);
1147             } else {
1148                 Z_ADDREF_P(zvalue);
1149             }
1150             add_assoc_zval_ex(&zret, Z_STRVAL_P(zkey), Z_STRLEN_P(zkey), zvalue);
1151         }
1152     }
1153     ZEND_HASH_FOREACH_END();
1154 
1155     zval_ptr_dtor(return_value);
1156     RETVAL_ZVAL(&zret, 1, 1);
1157 }
1158 
1159 static bool redis_auth(RedisClient *redis, char *pw, size_t pw_len);
1160 static bool redis_select_db(RedisClient *redis, long db_number);
1161 static void redis_request(
1162     RedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry = false);
1163 
swoole_redis_coro_connect(RedisClient * redis)1164 static bool swoole_redis_coro_connect(RedisClient *redis) {
1165     zval *zobject = redis->zobject;
1166     redisContext *context;
1167     Socket *socket;
1168     struct timeval tv;
1169     zval *ztmp;
1170     zval *zhost = sw_zend_read_property_ex(swoole_redis_coro_ce, zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_HOST), 0);
1171     zval *zport = sw_zend_read_property_ex(swoole_redis_coro_ce, zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_PORT), 0);
1172     zend::String host(zhost);
1173     zend_long port = zval_get_long(zport);
1174 
1175     if (host.len() == 0) {
1176         php_swoole_fatal_error(E_WARNING, "The host is empty");
1177         return false;
1178     }
1179 
1180     if (redis->context) {
1181         context = redis->context;
1182         if (context->connection_type == REDIS_CONN_TCP && strcmp(context->tcp.host, host.val()) == 0 &&
1183             context->tcp.port == port) {
1184             return true;
1185         } else if (context->connection_type == REDIS_CONN_UNIX &&
1186                    (strstr(host.val(), context->unix_sock.path) - host.val()) + strlen(context->unix_sock.path) ==
1187                        host.len()) {
1188             return true;
1189         } else {
1190             swoole_redis_coro_close(redis);
1191         }
1192     }
1193 
1194     php_swoole_check_reactor();
1195 
1196     if (redis->connect_timeout > 0) {
1197         tv.tv_sec = redis->connect_timeout;
1198         tv.tv_usec = (redis->connect_timeout - (double) tv.tv_sec) * 1000 * 1000;
1199     }
1200     if (SW_STRCASECT(host.val(), host.len(), "unix:/")) {
1201         context = redisConnectUnixWithTimeout(host.val() + 5 + strspn(host.val() + 5, "/") - 1, tv);
1202     } else {
1203         if (port <= 0 || port > SW_CLIENT_MAX_PORT) {
1204             php_swoole_fatal_error(E_WARNING, "The port " ZEND_LONG_FMT " is invalid", port);
1205             return false;
1206         }
1207         context = redisConnectWithTimeout(host.val(), (int) port, tv);
1208     }
1209 
1210     redis->context = context;
1211 
1212     if (!context) {
1213         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errType"), SW_REDIS_ERR_ALLOC);
1214         zend_update_property_long(
1215             swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), sw_redis_convert_err(SW_REDIS_ERR_ALLOC));
1216         zend_update_property_string(
1217             swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), "cannot allocate redis context");
1218         return false;
1219     }
1220     if (context->err) {
1221         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errType"), context->err);
1222         zend_update_property_long(
1223             swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), sw_redis_convert_err(context->err));
1224         zend_update_property_string(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), context->errstr);
1225         swoole_redis_coro_close(redis);
1226         return false;
1227     }
1228     if (!(socket = swoole_redis_coro_get_socket(context))) {
1229         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
1230         zend_update_property_long(
1231             swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), sw_redis_convert_err(SW_REDIS_ERR_OTHER));
1232         zend_update_property_string(
1233             swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), "Can not found the connection");
1234         swoole_redis_coro_close(redis);
1235         return false;
1236     }
1237 
1238     socket->set_timeout(redis->timeout, Socket::TIMEOUT_RDWR);
1239     redis->reconnected_count = 0;
1240     zend_update_property_bool(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("connected"), 1);
1241     zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("sock"), context->fd);
1242 
1243     // auth and select db after connected
1244     zval *zsetting =
1245         sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, redis->zobject, ZEND_STRL("setting"), 0);
1246     HashTable *vht = Z_ARRVAL_P(zsetting);
1247 
1248     if (php_swoole_array_get_value(vht, "password", ztmp)) {
1249         zend::String passowrd(ztmp);
1250         if (passowrd.len() > 0 && !redis_auth(redis, passowrd.val(), passowrd.len())) {
1251             swoole_redis_coro_close(redis);
1252             return false;
1253         }
1254     }
1255     if (php_swoole_array_get_value(vht, "database", ztmp)) {
1256         zend_long db_number = zval_get_long(ztmp);
1257         // default is 0, don't need select
1258         if (db_number > 0 && !redis_select_db(redis, db_number)) {
1259             swoole_redis_coro_close(redis);
1260             return false;
1261         }
1262     }
1263     return true;
1264 }
1265 
swoole_redis_coro_keep_liveness(RedisClient * redis)1266 static sw_inline bool swoole_redis_coro_keep_liveness(RedisClient *redis) {
1267     Socket *socket = nullptr;
1268     if (!redis->context || !(socket = swoole_redis_coro_get_socket(redis->context)) || !socket->check_liveness()) {
1269         if (socket) {
1270             zend_update_property_long(
1271                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), SW_REDIS_ERR_CLOSED);
1272             zend_update_property_long(
1273                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errCode"), socket->errCode);
1274             zend_update_property_string(
1275                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), socket->errMsg);
1276         }
1277         swoole_redis_coro_close(redis);
1278         for (; redis->reconnected_count < redis->reconnect_interval; redis->reconnected_count++) {
1279             if (swoole_redis_coro_connect(redis)) {
1280                 return true;
1281             }
1282         }
1283         zend_update_property_long(
1284             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), SW_REDIS_ERR_CLOSED);
1285         // Notice: do not update errCode
1286         zend_update_property_string(
1287             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), "connection is not available");
1288         return false;
1289     }
1290     return true;
1291 }
1292 
redis_auth(RedisClient * redis,char * pw,size_t pw_len)1293 static bool redis_auth(RedisClient *redis, char *pw, size_t pw_len) {
1294     int i = 0;
1295     size_t argvlen[2];
1296     char *argv[2];
1297     bool ret;
1298     zval retval;
1299 
1300     SW_REDIS_COMMAND_ARGV_FILL("AUTH", 4)
1301     SW_REDIS_COMMAND_ARGV_FILL(pw, pw_len)
1302     redis_request(redis, 2, argv, argvlen, &retval);
1303     ret = Z_BVAL_P(&retval);
1304     if (ret) {
1305         redis->session.auth = true;
1306     }
1307     return ret;
1308 }
1309 
redis_select_db(RedisClient * redis,long db_number)1310 static bool redis_select_db(RedisClient *redis, long db_number) {
1311     int i = 0;
1312     size_t argvlen[2];
1313     char *argv[2];
1314     char str[32];
1315     bool ret;
1316     zval retval;
1317 
1318     SW_REDIS_COMMAND_ARGV_FILL("SELECT", 6)
1319     sprintf(str, "%ld", db_number);
1320     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1321     redis_request(redis, 2, argv, argvlen, &retval);
1322     ret = Z_BVAL_P(&retval);
1323     if (ret) {
1324         redis->session.db_num = db_number;
1325     }
1326     return ret;
1327 }
1328 
redis_request(RedisClient * redis,int argc,char ** argv,size_t * argvlen,zval * return_value,bool retry)1329 static void redis_request(
1330     RedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry) {
1331     redisReply *reply = nullptr;
1332     if (!swoole_redis_coro_keep_liveness(redis)) {
1333         ZVAL_FALSE(return_value);
1334     } else {
1335         // must clear err before request
1336         redis->context->err = 0;
1337         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), 0);
1338         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errCode"), 0);
1339         zend_update_property_string(swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), "");
1340         if (redis->defer) {
1341             if (redisAppendCommandArgv(redis->context, argc, (const char **) argv, (const size_t *) argvlen) ==
1342                 REDIS_ERR) {
1343                 goto _error;
1344             } else {
1345                 ZVAL_TRUE(return_value);
1346             }
1347         } else {
1348             reply =
1349                 (redisReply *) redisCommandArgv(redis->context, argc, (const char **) argv, (const size_t *) argvlen);
1350             if (reply == nullptr) {
1351             _error:
1352                 zend_update_property_long(
1353                     swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), redis->context->err);
1354                 zend_update_property_long(swoole_redis_coro_ce,
1355                                           SW_Z8_OBJ_P(redis->zobject),
1356                                           ZEND_STRL("errCode"),
1357                                           sw_redis_convert_err(redis->context->err));
1358                 zend_update_property_string(
1359                     swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), redis->context->errstr);
1360                 ZVAL_FALSE(return_value);
1361                 swoole_redis_coro_close(redis);
1362             } else {
1363                 // Redis Cluster
1364                 if (reply->type == REDIS_REPLY_ERROR &&
1365                     (!strncmp(reply->str, "MOVED", 5) || !strcmp(reply->str, "ASK"))) {
1366                     char *p1, *p2;
1367                     // MOVED 1234 127.0.0.1:1234
1368                     p1 = strrchr(reply->str, ' ') + 1;  // MOVED 1234 [p1]27.0.0.1:1234
1369                     p2 = strrchr(p1, ':');              // MOVED 1234 [p1]27.0.0.1[p2]1234
1370                     *p2 = '\0';
1371                     int port = atoi(p2 + 1);
1372                     zend_update_property_string(
1373                         swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("host"), p1);
1374                     zend_update_property_long(
1375                         swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("port"), port);
1376 
1377                     if (swoole_redis_coro_connect(redis) > 0) {
1378                         freeReplyObject(reply);
1379                         redis_request(redis, argc, argv, argvlen, return_value, retry);
1380                         return;
1381                     } else {
1382                         ZVAL_FALSE(return_value);
1383                     }
1384                 }
1385                 // Normal Response
1386                 else {
1387                     swoole_redis_coro_parse_result(redis, return_value, reply);
1388                 }
1389                 freeReplyObject(reply);
1390             }
1391         }
1392     }
1393     SW_LOOP_N(argc) {
1394         efree(argv[i]);
1395     }
1396 }
1397 
sw_redis_command_empty(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1398 static sw_inline void sw_redis_command_empty(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1399     SW_REDIS_COMMAND_CHECK
1400     int i = 0;
1401     size_t argvlen[1];
1402     char *argv[1];
1403     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1404     redis_request(redis, 1, argv, argvlen, return_value);
1405 }
1406 
sw_redis_command_var_key(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len,int min_argc,int has_timeout)1407 static sw_inline void sw_redis_command_var_key(
1408     INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len, int min_argc, int has_timeout) {
1409     long timeout;
1410     int argc = ZEND_NUM_ARGS();
1411     if (argc < min_argc) {
1412         RETURN_FALSE;
1413     }
1414     SW_REDIS_COMMAND_CHECK
1415     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
1416     if (argc == 0 || zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
1417         efree(z_args);
1418         RETURN_FALSE;
1419     }
1420     zend_bool single_array = 0;
1421     if (has_timeout == 0) {
1422         single_array = argc == 1 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY;
1423     } else {
1424         single_array = argc == 2 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY &&
1425                        SW_REDIS_COMMAND_ARGS_TYPE(z_args[1]) == IS_LONG;
1426         timeout = SW_REDIS_COMMAND_ARGS_LVAL(z_args[1]);
1427     }
1428     if (single_array) {
1429         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0])) + 1;
1430     } else {
1431         argc++;
1432     }
1433 
1434     SW_REDIS_COMMAND_ALLOC_ARGV
1435     int i = 0;
1436     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1437     char buf[32];
1438     size_t buf_len;
1439     if (single_array) {
1440         zval *value;
1441         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
1442         zend_string *convert_str = zval_get_string(value);
1443         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
1444         zend_string_release(convert_str);
1445         SW_HASHTABLE_FOREACH_END();
1446         if (has_timeout) {
1447             buf_len = sw_snprintf(buf, sizeof(buf), "%ld", timeout);
1448             SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len);
1449         }
1450     } else {
1451         if (has_timeout && SW_REDIS_COMMAND_ARGS_TYPE(z_args[argc - 2]) != IS_LONG) {
1452             zend_update_property_long(
1453                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
1454             zend_update_property_long(swoole_redis_coro_ce,
1455                                       SW_Z8_OBJ_P(redis->zobject),
1456                                       ZEND_STRL("errCode"),
1457                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
1458             zend_update_property_string(
1459                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), "Timeout value must be a LONG");
1460             efree(z_args);
1461             RETURN_FALSE;
1462         }
1463         int j, tail;
1464         tail = has_timeout ? argc - 2 : argc - 1;
1465         for (j = 0; j < tail; ++j) {
1466             zend_string *convert_str = zval_get_string(&z_args[j]);
1467             SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
1468             zend_string_release(convert_str);
1469         }
1470         if (has_timeout) {
1471             buf_len = sw_snprintf(buf, sizeof(buf), ZEND_LONG_FMT, SW_REDIS_COMMAND_ARGS_LVAL(z_args[tail]));
1472             SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len);
1473         }
1474     }
1475     efree(z_args);
1476 
1477     redis_request(redis, argc, argv, argvlen, return_value);
1478 }
1479 
sw_redis_command_key(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1480 static inline void sw_redis_command_key(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1481     char *key;
1482     size_t key_len;
1483     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) {
1484         RETURN_FALSE;
1485     }
1486     SW_REDIS_COMMAND_CHECK
1487     int i = 0;
1488     size_t argvlen[2];
1489     char *argv[2];
1490     int argc = 2;
1491     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1492     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1493     redis_request(redis, argc, argv, argvlen, return_value);
1494 
1495     if (redis->compatibility_mode) {
1496         if (ZVAL_IS_ARRAY(return_value) && sw_mem_equal(ZEND_STRL("HGETALL"), cmd, cmd_len)) {
1497             swoole_redis_handle_assoc_array_result(return_value, false);
1498         } else if (ZVAL_IS_NULL(return_value) && sw_mem_equal(ZEND_STRL("GET"), cmd, cmd_len)) {
1499             RETURN_FALSE;
1500         }
1501     }
1502 }
1503 
sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1504 static sw_inline void sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1505     int argc = ZEND_NUM_ARGS();
1506     // We at least need a key and one value
1507     if (argc < 2) {
1508         RETURN_FALSE;
1509     }
1510     SW_REDIS_COMMAND_CHECK
1511     // Make sure we at least have a key, and we can get other args
1512     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
1513     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
1514         efree(z_args);
1515         RETURN_FALSE;
1516     }
1517 
1518     int i = 0, j;
1519     argc++;
1520     SW_REDIS_COMMAND_ALLOC_ARGV
1521     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1522     zend_string *convert_str = zval_get_string(&z_args[0]);
1523     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
1524     zend_string_release(convert_str);
1525     for (j = 1; j < argc - 1; ++j) {
1526         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(SW_REDIS_COMMAND_ARGS_REF(z_args[j]))
1527     }
1528     efree(z_args);
1529     redis_request(redis, argc, argv, argvlen, return_value);
1530 }
1531 
sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1532 static sw_inline void sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1533     char *key;
1534     size_t key_len;
1535     long l_val;
1536     zval *z_value;
1537     if (zend_parse_parameters(ZEND_NUM_ARGS(), "slz", &key, &key_len, &l_val, &z_value) == FAILURE) {
1538         RETURN_FALSE;
1539     }
1540     SW_REDIS_COMMAND_CHECK
1541     int i = 0;
1542     size_t argvlen[4];
1543     char *argv[4];
1544     int argc = 4;
1545     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1546     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1547     char str[32];
1548     sprintf(str, "%ld", l_val);
1549     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1550     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_value)
1551     redis_request(redis, argc, argv, argvlen, return_value);
1552 }
1553 
sw_redis_command_key_long_str(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1554 static sw_inline void sw_redis_command_key_long_str(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1555     char *key, *val;
1556     size_t key_len, val_len;
1557     long l_val;
1558     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sls", &key, &key_len, &l_val, &val, &val_len) == FAILURE) {
1559         return;
1560     }
1561     SW_REDIS_COMMAND_CHECK
1562     int i = 0;
1563     size_t argvlen[4];
1564     char *argv[4];
1565     int argc = 4;
1566     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1567     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1568     char str[32];
1569     sprintf(str, "%ld", l_val);
1570     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1571     SW_REDIS_COMMAND_ARGV_FILL(val, val_len)
1572     redis_request(redis, argc, argv, argvlen, return_value);
1573 }
1574 
sw_redis_command_key_long(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1575 static sw_inline void sw_redis_command_key_long(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1576     char *key;
1577     size_t key_len;
1578     long l_val;
1579     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &key, &key_len, &l_val) == FAILURE) {
1580         return;
1581     }
1582     SW_REDIS_COMMAND_CHECK
1583     int i = 0;
1584     size_t argvlen[3];
1585     char *argv[3];
1586     int argc = 3;
1587     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1588     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1589     char str[32];
1590     sprintf(str, "%ld", l_val);
1591     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1592     redis_request(redis, argc, argv, argvlen, return_value);
1593 }
1594 
sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1595 static sw_inline void sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1596     char *key;
1597     size_t key_len;
1598     long l1_val, l2_val;
1599     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll", &key, &key_len, &l1_val, &l2_val) == FAILURE) {
1600         return;
1601     }
1602     SW_REDIS_COMMAND_CHECK
1603     int i = 0;
1604     size_t argvlen[4];
1605     char *argv[4];
1606     int argc = 4;
1607     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1608     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1609     char str[32];
1610     sprintf(str, "%ld", l1_val);
1611     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1612     sprintf(str, "%ld", l2_val);
1613     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1614     redis_request(redis, argc, argv, argvlen, return_value);
1615 }
1616 
sw_redis_command_key_dbl(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1617 static sw_inline void sw_redis_command_key_dbl(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1618     char *key;
1619     size_t key_len;
1620     double d_val;
1621     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sd", &key, &key_len, &d_val) == FAILURE) {
1622         RETURN_FALSE;
1623     }
1624     SW_REDIS_COMMAND_CHECK
1625     int i = 0;
1626     size_t argvlen[3];
1627     char *argv[3];
1628     int argc = 3;
1629     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1630     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1631     char str[32];
1632     sprintf(str, "%f", d_val);
1633     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
1634     redis_request(redis, argc, argv, argvlen, return_value);
1635 }
1636 
sw_redis_command_key_key(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1637 static sw_inline void sw_redis_command_key_key(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1638     char *key1, *key2;
1639     size_t key1_len, key2_len;
1640     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key1, &key1_len, &key2, &key2_len) == FAILURE) {
1641         RETURN_FALSE;
1642     }
1643     SW_REDIS_COMMAND_CHECK
1644     int i = 0;
1645     size_t argvlen[3];
1646     char *argv[3];
1647     int argc = 3;
1648     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1649     SW_REDIS_COMMAND_ARGV_FILL(key1, key1_len)
1650     SW_REDIS_COMMAND_ARGV_FILL(key2, key2_len)
1651     redis_request(redis, argc, argv, argvlen, return_value);
1652 }
1653 
sw_redis_command_key_val(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1654 static sw_inline void sw_redis_command_key_val(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1655     char *key;
1656     size_t key_len;
1657     zval *z_value;
1658     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &key, &key_len, &z_value) == FAILURE) {
1659         RETURN_FALSE;
1660     }
1661     SW_REDIS_COMMAND_CHECK
1662     int i = 0;
1663     size_t argvlen[3];
1664     char *argv[3];
1665     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1666     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1667     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_value)
1668     redis_request(redis, 3, argv, argvlen, return_value);
1669 
1670     if (redis->compatibility_mode && ZVAL_IS_NULL(return_value) && strncmp("ZRANK", cmd, cmd_len) == 0) {
1671         RETURN_FALSE;
1672     }
1673 }
1674 
sw_redis_command_key_str(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1675 static sw_inline void sw_redis_command_key_str(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1676     char *key, *val;
1677     size_t key_len, val_len;
1678     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key, &key_len, &val, &val_len) == FAILURE) {
1679         RETURN_FALSE;
1680     }
1681     SW_REDIS_COMMAND_CHECK
1682     int i = 0;
1683     size_t argvlen[3];
1684     char *argv[3];
1685     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1686     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1687     SW_REDIS_COMMAND_ARGV_FILL(val, val_len)
1688     redis_request(redis, 3, argv, argvlen, return_value);
1689 }
1690 
sw_redis_command_key_str_str(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1691 static sw_inline void sw_redis_command_key_str_str(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1692     char *key, *val1, *val2;
1693     size_t key_len, val1_len, val2_len;
1694     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &val1, &val1_len, &val2, &val2_len) == FAILURE) {
1695         RETURN_FALSE;
1696     }
1697     SW_REDIS_COMMAND_CHECK
1698     int i = 0;
1699     size_t argvlen[4];
1700     char *argv[4];
1701     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1702     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1703     SW_REDIS_COMMAND_ARGV_FILL(val1, val1_len)
1704     SW_REDIS_COMMAND_ARGV_FILL(val2, val2_len)
1705     redis_request(redis, 4, argv, argvlen, return_value);
1706 }
1707 
sw_redis_command_xrange(INTERNAL_FUNCTION_PARAMETERS,const char * cmd,int cmd_len)1708 static sw_inline void sw_redis_command_xrange(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) {
1709     char *key, *val1, *val2;
1710     size_t key_len, val1_len, val2_len;
1711     zend_long count = 0;
1712 
1713     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|l", &key, &key_len, &val1, &val1_len, &val2, &val2_len, &count) == FAILURE) {
1714         RETURN_FALSE;
1715     }
1716     SW_REDIS_COMMAND_CHECK
1717 
1718     int i = 0, argc;
1719     argc = ZEND_NUM_ARGS() == 4 ? 6 : 4;
1720     SW_REDIS_COMMAND_ALLOC_ARGV
1721     SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len)
1722     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
1723     SW_REDIS_COMMAND_ARGV_FILL(val1, val1_len)
1724     SW_REDIS_COMMAND_ARGV_FILL(val2, val2_len)
1725     if (count > 0) {
1726         SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5)
1727         char buf[32];
1728         size_t buf_len;
1729         buf_len = sprintf(buf, ZEND_LONG_FMT, count);
1730         SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
1731     }
1732 
1733     redis_request(redis, argc, argv, argvlen, return_value);
1734 
1735     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
1736         swoole_redis_handle_assoc_array_result(return_value, true);
1737     }
1738 
1739     SW_REDIS_COMMAND_FREE_ARGV
1740 }
1741 
1742 SW_EXTERN_C_BEGIN
1743 static PHP_METHOD(swoole_redis_coro, __construct);
1744 static PHP_METHOD(swoole_redis_coro, __destruct);
1745 static PHP_METHOD(swoole_redis_coro, connect);
1746 static PHP_METHOD(swoole_redis_coro, getAuth);
1747 static PHP_METHOD(swoole_redis_coro, getDBNum);
1748 static PHP_METHOD(swoole_redis_coro, getOptions);
1749 static PHP_METHOD(swoole_redis_coro, setOptions);
1750 static PHP_METHOD(swoole_redis_coro, getDefer);
1751 static PHP_METHOD(swoole_redis_coro, setDefer);
1752 static PHP_METHOD(swoole_redis_coro, recv);
1753 static PHP_METHOD(swoole_redis_coro, request);
1754 static PHP_METHOD(swoole_redis_coro, close);
1755 /*---------------------Redis Command------------------------*/
1756 static PHP_METHOD(swoole_redis_coro, set);
1757 static PHP_METHOD(swoole_redis_coro, setBit);
1758 static PHP_METHOD(swoole_redis_coro, setEx);
1759 static PHP_METHOD(swoole_redis_coro, psetEx);
1760 static PHP_METHOD(swoole_redis_coro, lSet);
1761 static PHP_METHOD(swoole_redis_coro, get);
1762 static PHP_METHOD(swoole_redis_coro, mGet);
1763 static PHP_METHOD(swoole_redis_coro, del);
1764 static PHP_METHOD(swoole_redis_coro, hDel);
1765 static PHP_METHOD(swoole_redis_coro, hSet);
1766 static PHP_METHOD(swoole_redis_coro, hMSet);
1767 static PHP_METHOD(swoole_redis_coro, hSetNx);
1768 static PHP_METHOD(swoole_redis_coro, mSet);
1769 static PHP_METHOD(swoole_redis_coro, mSetNx);
1770 static PHP_METHOD(swoole_redis_coro, getKeys);
1771 static PHP_METHOD(swoole_redis_coro, exists);
1772 static PHP_METHOD(swoole_redis_coro, type);
1773 static PHP_METHOD(swoole_redis_coro, strLen);
1774 static PHP_METHOD(swoole_redis_coro, lPop);
1775 static PHP_METHOD(swoole_redis_coro, blPop);
1776 static PHP_METHOD(swoole_redis_coro, rPop);
1777 static PHP_METHOD(swoole_redis_coro, brPop);
1778 static PHP_METHOD(swoole_redis_coro, bRPopLPush);
1779 static PHP_METHOD(swoole_redis_coro, lSize);
1780 static PHP_METHOD(swoole_redis_coro, sSize);
1781 static PHP_METHOD(swoole_redis_coro, sPop);
1782 static PHP_METHOD(swoole_redis_coro, sMembers);
1783 static PHP_METHOD(swoole_redis_coro, sRandMember);
1784 static PHP_METHOD(swoole_redis_coro, persist);
1785 static PHP_METHOD(swoole_redis_coro, ttl);
1786 static PHP_METHOD(swoole_redis_coro, pttl);
1787 static PHP_METHOD(swoole_redis_coro, zCard);
1788 static PHP_METHOD(swoole_redis_coro, hLen);
1789 static PHP_METHOD(swoole_redis_coro, hKeys);
1790 static PHP_METHOD(swoole_redis_coro, hVals);
1791 static PHP_METHOD(swoole_redis_coro, hGetAll);
1792 static PHP_METHOD(swoole_redis_coro, restore);
1793 static PHP_METHOD(swoole_redis_coro, dump);
1794 static PHP_METHOD(swoole_redis_coro, debug);
1795 static PHP_METHOD(swoole_redis_coro, renameKey);
1796 static PHP_METHOD(swoole_redis_coro, renameNx);
1797 static PHP_METHOD(swoole_redis_coro, rpoplpush);
1798 static PHP_METHOD(swoole_redis_coro, randomKey);
1799 static PHP_METHOD(swoole_redis_coro, pfadd);
1800 static PHP_METHOD(swoole_redis_coro, pfcount);
1801 static PHP_METHOD(swoole_redis_coro, pfmerge);
1802 static PHP_METHOD(swoole_redis_coro, ping);
1803 static PHP_METHOD(swoole_redis_coro, auth);
1804 static PHP_METHOD(swoole_redis_coro, unwatch);
1805 static PHP_METHOD(swoole_redis_coro, watch);
1806 static PHP_METHOD(swoole_redis_coro, save);
1807 static PHP_METHOD(swoole_redis_coro, bgSave);
1808 static PHP_METHOD(swoole_redis_coro, lastSave);
1809 static PHP_METHOD(swoole_redis_coro, flushDB);
1810 static PHP_METHOD(swoole_redis_coro, flushAll);
1811 static PHP_METHOD(swoole_redis_coro, dbSize);
1812 static PHP_METHOD(swoole_redis_coro, bgrewriteaof);
1813 static PHP_METHOD(swoole_redis_coro, time);
1814 static PHP_METHOD(swoole_redis_coro, role);
1815 static PHP_METHOD(swoole_redis_coro, setRange);
1816 static PHP_METHOD(swoole_redis_coro, setNx);
1817 static PHP_METHOD(swoole_redis_coro, getSet);
1818 static PHP_METHOD(swoole_redis_coro, append);
1819 static PHP_METHOD(swoole_redis_coro, lPushx);
1820 static PHP_METHOD(swoole_redis_coro, lPush);
1821 static PHP_METHOD(swoole_redis_coro, rPush);
1822 static PHP_METHOD(swoole_redis_coro, rPushx);
1823 static PHP_METHOD(swoole_redis_coro, sContains);
1824 static PHP_METHOD(swoole_redis_coro, zScore);
1825 static PHP_METHOD(swoole_redis_coro, zRank);
1826 static PHP_METHOD(swoole_redis_coro, zRevRank);
1827 static PHP_METHOD(swoole_redis_coro, hGet);
1828 static PHP_METHOD(swoole_redis_coro, hMGet);
1829 static PHP_METHOD(swoole_redis_coro, hExists);
1830 static PHP_METHOD(swoole_redis_coro, publish);
1831 static PHP_METHOD(swoole_redis_coro, zIncrBy);
1832 static PHP_METHOD(swoole_redis_coro, zAdd);
1833 static PHP_METHOD(swoole_redis_coro, zPopMin);
1834 static PHP_METHOD(swoole_redis_coro, zPopMax);
1835 static PHP_METHOD(swoole_redis_coro, bzPopMin);
1836 static PHP_METHOD(swoole_redis_coro, bzPopMax);
1837 static PHP_METHOD(swoole_redis_coro, zDeleteRangeByScore);
1838 static PHP_METHOD(swoole_redis_coro, zCount);
1839 static PHP_METHOD(swoole_redis_coro, zRange);
1840 static PHP_METHOD(swoole_redis_coro, zRevRange);
1841 static PHP_METHOD(swoole_redis_coro, zRangeByScore);
1842 static PHP_METHOD(swoole_redis_coro, zRevRangeByScore);
1843 static PHP_METHOD(swoole_redis_coro, zRangeByLex);
1844 static PHP_METHOD(swoole_redis_coro, zRevRangeByLex);
1845 static PHP_METHOD(swoole_redis_coro, zInter);
1846 static PHP_METHOD(swoole_redis_coro, zUnion);
1847 static PHP_METHOD(swoole_redis_coro, incrBy);
1848 static PHP_METHOD(swoole_redis_coro, hIncrBy);
1849 static PHP_METHOD(swoole_redis_coro, incr);
1850 static PHP_METHOD(swoole_redis_coro, decrBy);
1851 static PHP_METHOD(swoole_redis_coro, decr);
1852 static PHP_METHOD(swoole_redis_coro, getBit);
1853 static PHP_METHOD(swoole_redis_coro, lGet);
1854 static PHP_METHOD(swoole_redis_coro, lInsert);
1855 static PHP_METHOD(swoole_redis_coro, setTimeout);
1856 static PHP_METHOD(swoole_redis_coro, pexpire);
1857 static PHP_METHOD(swoole_redis_coro, expireAt);
1858 static PHP_METHOD(swoole_redis_coro, pexpireAt);
1859 static PHP_METHOD(swoole_redis_coro, move);
1860 static PHP_METHOD(swoole_redis_coro, select);
1861 static PHP_METHOD(swoole_redis_coro, getRange);
1862 static PHP_METHOD(swoole_redis_coro, listTrim);
1863 static PHP_METHOD(swoole_redis_coro, lGetRange);
1864 static PHP_METHOD(swoole_redis_coro, lRem);
1865 static PHP_METHOD(swoole_redis_coro, zDeleteRangeByRank);
1866 static PHP_METHOD(swoole_redis_coro, incrByFloat);
1867 static PHP_METHOD(swoole_redis_coro, hIncrByFloat);
1868 static PHP_METHOD(swoole_redis_coro, bitCount);
1869 static PHP_METHOD(swoole_redis_coro, bitOp);
1870 static PHP_METHOD(swoole_redis_coro, sAdd);
1871 static PHP_METHOD(swoole_redis_coro, sMove);
1872 static PHP_METHOD(swoole_redis_coro, sDiff);
1873 static PHP_METHOD(swoole_redis_coro, sDiffStore);
1874 static PHP_METHOD(swoole_redis_coro, sUnion);
1875 static PHP_METHOD(swoole_redis_coro, sUnionStore);
1876 static PHP_METHOD(swoole_redis_coro, sInter);
1877 static PHP_METHOD(swoole_redis_coro, sInterStore);
1878 static PHP_METHOD(swoole_redis_coro, sRemove);
1879 static PHP_METHOD(swoole_redis_coro, zDelete);
1880 static PHP_METHOD(swoole_redis_coro, subscribe);
1881 static PHP_METHOD(swoole_redis_coro, pSubscribe);
1882 static PHP_METHOD(swoole_redis_coro, unsubscribe);
1883 static PHP_METHOD(swoole_redis_coro, pUnSubscribe);
1884 static PHP_METHOD(swoole_redis_coro, multi);
1885 static PHP_METHOD(swoole_redis_coro, exec);
1886 static PHP_METHOD(swoole_redis_coro, eval);
1887 static PHP_METHOD(swoole_redis_coro, evalSha);
1888 static PHP_METHOD(swoole_redis_coro, script);
1889 static PHP_METHOD(swoole_redis_coro, xLen);
1890 static PHP_METHOD(swoole_redis_coro, xAdd);
1891 static PHP_METHOD(swoole_redis_coro, xRead);
1892 static PHP_METHOD(swoole_redis_coro, xDel);
1893 static PHP_METHOD(swoole_redis_coro, xRange);
1894 static PHP_METHOD(swoole_redis_coro, xRevRange);
1895 static PHP_METHOD(swoole_redis_coro, xTrim);
1896 static PHP_METHOD(swoole_redis_coro, xGroupCreate);
1897 static PHP_METHOD(swoole_redis_coro, xGroupSetId);
1898 static PHP_METHOD(swoole_redis_coro, xGroupDestroy);
1899 static PHP_METHOD(swoole_redis_coro, xGroupCreateConsumer);
1900 static PHP_METHOD(swoole_redis_coro, xGroupDelConsumer);
1901 static PHP_METHOD(swoole_redis_coro, xReadGroup);
1902 static PHP_METHOD(swoole_redis_coro, xPending);
1903 static PHP_METHOD(swoole_redis_coro, xAck);
1904 static PHP_METHOD(swoole_redis_coro, xClaim);
1905 static PHP_METHOD(swoole_redis_coro, xAutoClaim);
1906 static PHP_METHOD(swoole_redis_coro, xInfoConsumers);
1907 static PHP_METHOD(swoole_redis_coro, xInfoGroups);
1908 static PHP_METHOD(swoole_redis_coro, xInfoStream);
1909 SW_EXTERN_C_END
1910 /*---------------------Redis Command End------------------------*/
1911 // clang-format off
1912 static const zend_function_entry swoole_redis_coro_methods[] =
1913 {
1914     PHP_ME(swoole_redis_coro, __construct, arginfo_swoole_redis_coro_construct, ZEND_ACC_PUBLIC)
1915     PHP_ME(swoole_redis_coro, __destruct, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1916     PHP_ME(swoole_redis_coro, connect, arginfo_swoole_redis_coro_connect, ZEND_ACC_PUBLIC)
1917     PHP_ME(swoole_redis_coro, getAuth, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1918     PHP_ME(swoole_redis_coro, getDBNum, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1919     PHP_ME(swoole_redis_coro, getOptions, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1920     PHP_ME(swoole_redis_coro, setOptions, arginfo_swoole_redis_coro_setOptions, ZEND_ACC_PUBLIC)
1921     PHP_ME(swoole_redis_coro, getDefer, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1922     PHP_ME(swoole_redis_coro, setDefer, arginfo_swoole_redis_coro_setDefer, ZEND_ACC_PUBLIC)
1923     PHP_ME(swoole_redis_coro, recv, arginfo_swoole_redis_coro_void, ZEND_ACC_PUBLIC)
1924     PHP_ME(swoole_redis_coro, request, arginfo_swoole_redis_coro_request, ZEND_ACC_PUBLIC)
1925     PHP_ME(swoole_redis_coro, close, arginfo_swoole_redis_coro_close, ZEND_ACC_PUBLIC)
1926     /*---------------------Redis Command------------------------*/
1927     PHP_ME(swoole_redis_coro, set, arginfo_swoole_redis_coro_set, ZEND_ACC_PUBLIC)
1928     PHP_ME(swoole_redis_coro, setBit, arginfo_swoole_redis_coro_setBit, ZEND_ACC_PUBLIC)
1929     PHP_ME(swoole_redis_coro, setEx, arginfo_swoole_redis_coro_setex, ZEND_ACC_PUBLIC)
1930     PHP_ME(swoole_redis_coro, psetEx, arginfo_swoole_redis_coro_psetex, ZEND_ACC_PUBLIC)
1931     PHP_ME(swoole_redis_coro, lSet, arginfo_swoole_redis_coro_lSet, ZEND_ACC_PUBLIC)
1932     PHP_ME(swoole_redis_coro, get, arginfo_swoole_redis_coro_get, ZEND_ACC_PUBLIC)
1933     PHP_ME(swoole_redis_coro, mGet, arginfo_swoole_redis_coro_mget, ZEND_ACC_PUBLIC)
1934     PHP_ME(swoole_redis_coro, del, arginfo_swoole_redis_coro_del, ZEND_ACC_PUBLIC)
1935     PHP_ME(swoole_redis_coro, hDel, arginfo_swoole_redis_coro_hDel, ZEND_ACC_PUBLIC)
1936     PHP_ME(swoole_redis_coro, hSet, arginfo_swoole_redis_coro_hSet, ZEND_ACC_PUBLIC)
1937     PHP_ME(swoole_redis_coro, hMSet, arginfo_swoole_redis_coro_hMset, ZEND_ACC_PUBLIC)
1938     PHP_ME(swoole_redis_coro, hSetNx, arginfo_swoole_redis_coro_hSetNx, ZEND_ACC_PUBLIC)
1939     PHP_MALIAS(swoole_redis_coro, delete, del, arginfo_swoole_redis_coro_del, ZEND_ACC_PUBLIC)
1940     PHP_ME(swoole_redis_coro, mSet, arginfo_swoole_redis_coro_mset, ZEND_ACC_PUBLIC)
1941     PHP_ME(swoole_redis_coro, mSetNx, arginfo_swoole_redis_coro_msetnx, ZEND_ACC_PUBLIC)
1942     PHP_ME(swoole_redis_coro, getKeys, arginfo_swoole_redis_coro_getKeys, ZEND_ACC_PUBLIC)
1943     PHP_MALIAS(swoole_redis_coro, keys, getKeys, arginfo_swoole_redis_coro_getKeys, ZEND_ACC_PUBLIC)
1944     PHP_ME(swoole_redis_coro, exists, arginfo_swoole_redis_coro_exists, ZEND_ACC_PUBLIC)
1945     PHP_ME(swoole_redis_coro, type, arginfo_swoole_redis_coro_type, ZEND_ACC_PUBLIC)
1946     PHP_ME(swoole_redis_coro, strLen, arginfo_swoole_redis_coro_strlen, ZEND_ACC_PUBLIC)
1947     PHP_ME(swoole_redis_coro, lPop, arginfo_swoole_redis_coro_lPop, ZEND_ACC_PUBLIC)
1948     PHP_ME(swoole_redis_coro, blPop, arginfo_swoole_redis_coro_blPop, ZEND_ACC_PUBLIC)
1949     PHP_ME(swoole_redis_coro, rPop, arginfo_swoole_redis_coro_rPop, ZEND_ACC_PUBLIC)
1950     PHP_ME(swoole_redis_coro, brPop, arginfo_swoole_redis_coro_brPop, ZEND_ACC_PUBLIC)
1951     PHP_ME(swoole_redis_coro, bRPopLPush, arginfo_swoole_redis_coro_brpoplpush, ZEND_ACC_PUBLIC)
1952     PHP_ME(swoole_redis_coro, lSize, arginfo_swoole_redis_coro_lSize, ZEND_ACC_PUBLIC)
1953     PHP_MALIAS(swoole_redis_coro, lLen, lSize, arginfo_swoole_redis_coro_lLen, ZEND_ACC_PUBLIC)
1954     PHP_ME(swoole_redis_coro, sSize, arginfo_swoole_redis_coro_sSize, ZEND_ACC_PUBLIC)
1955     PHP_MALIAS(swoole_redis_coro, scard, sSize, arginfo_swoole_redis_coro_scard, ZEND_ACC_PUBLIC)
1956     PHP_ME(swoole_redis_coro, sPop, arginfo_swoole_redis_coro_sPop, ZEND_ACC_PUBLIC)
1957     PHP_ME(swoole_redis_coro, sMembers, arginfo_swoole_redis_coro_sMembers, ZEND_ACC_PUBLIC)
1958     PHP_MALIAS(swoole_redis_coro, sGetMembers, sMembers, arginfo_swoole_redis_coro_key, ZEND_ACC_PUBLIC)
1959     PHP_ME(swoole_redis_coro, sRandMember, arginfo_swoole_redis_coro_sRandMember, ZEND_ACC_PUBLIC)
1960     PHP_ME(swoole_redis_coro, persist, arginfo_swoole_redis_coro_persist, ZEND_ACC_PUBLIC)
1961     PHP_ME(swoole_redis_coro, ttl, arginfo_swoole_redis_coro_ttl, ZEND_ACC_PUBLIC)
1962     PHP_ME(swoole_redis_coro, pttl, arginfo_swoole_redis_coro_pttl, ZEND_ACC_PUBLIC)
1963     PHP_ME(swoole_redis_coro, zCard, arginfo_swoole_redis_coro_zCard, ZEND_ACC_PUBLIC)
1964     PHP_MALIAS(swoole_redis_coro, zSize, zCard, arginfo_swoole_redis_coro_zSize, ZEND_ACC_PUBLIC)
1965     PHP_ME(swoole_redis_coro, hLen, arginfo_swoole_redis_coro_hLen, ZEND_ACC_PUBLIC)
1966     PHP_ME(swoole_redis_coro, hKeys, arginfo_swoole_redis_coro_hKeys, ZEND_ACC_PUBLIC)
1967     PHP_ME(swoole_redis_coro, hVals, arginfo_swoole_redis_coro_hVals, ZEND_ACC_PUBLIC)
1968     PHP_ME(swoole_redis_coro, hGetAll, arginfo_swoole_redis_coro_hGetAll, ZEND_ACC_PUBLIC)
1969     PHP_ME(swoole_redis_coro, debug, arginfo_swoole_redis_coro_debug, ZEND_ACC_PUBLIC)
1970     PHP_ME(swoole_redis_coro, restore, arginfo_swoole_redis_coro_restore, ZEND_ACC_PUBLIC)
1971     PHP_ME(swoole_redis_coro, dump, arginfo_swoole_redis_coro_dump, ZEND_ACC_PUBLIC)
1972     PHP_ME(swoole_redis_coro, renameKey, arginfo_swoole_redis_coro_renameKey, ZEND_ACC_PUBLIC)
1973     PHP_MALIAS(swoole_redis_coro, rename, renameKey, arginfo_swoole_redis_coro_rename, ZEND_ACC_PUBLIC)
1974     PHP_ME(swoole_redis_coro, renameNx, arginfo_swoole_redis_coro_renameNx, ZEND_ACC_PUBLIC)
1975     PHP_ME(swoole_redis_coro, rpoplpush, arginfo_swoole_redis_coro_rpoplpush, ZEND_ACC_PUBLIC)
1976     PHP_ME(swoole_redis_coro, randomKey, arginfo_swoole_redis_coro_randomKey, ZEND_ACC_PUBLIC)
1977     PHP_ME(swoole_redis_coro, pfadd, arginfo_swoole_redis_coro_pfadd, ZEND_ACC_PUBLIC)
1978     PHP_ME(swoole_redis_coro, pfcount, arginfo_swoole_redis_coro_pfcount, ZEND_ACC_PUBLIC)
1979     PHP_ME(swoole_redis_coro, pfmerge, arginfo_swoole_redis_coro_pfmerge, ZEND_ACC_PUBLIC)
1980     PHP_ME(swoole_redis_coro, ping, arginfo_swoole_redis_coro_ping, ZEND_ACC_PUBLIC)
1981     PHP_ME(swoole_redis_coro, auth, arginfo_swoole_redis_coro_auth, ZEND_ACC_PUBLIC)
1982     PHP_ME(swoole_redis_coro, unwatch, arginfo_swoole_redis_coro_unwatch, ZEND_ACC_PUBLIC)
1983     PHP_ME(swoole_redis_coro, watch, arginfo_swoole_redis_coro_watch, ZEND_ACC_PUBLIC)
1984     PHP_ME(swoole_redis_coro, save, arginfo_swoole_redis_coro_save, ZEND_ACC_PUBLIC)
1985     PHP_ME(swoole_redis_coro, bgSave, arginfo_swoole_redis_coro_bgSave, ZEND_ACC_PUBLIC)
1986     PHP_ME(swoole_redis_coro, lastSave, arginfo_swoole_redis_coro_lastSave, ZEND_ACC_PUBLIC)
1987     PHP_ME(swoole_redis_coro, flushDB, arginfo_swoole_redis_coro_flushDB, ZEND_ACC_PUBLIC)
1988     PHP_ME(swoole_redis_coro, flushAll, arginfo_swoole_redis_coro_flushAll, ZEND_ACC_PUBLIC)
1989     PHP_ME(swoole_redis_coro, dbSize, arginfo_swoole_redis_coro_dbSize, ZEND_ACC_PUBLIC)
1990     PHP_ME(swoole_redis_coro, bgrewriteaof, arginfo_swoole_redis_coro_bgrewriteaof, ZEND_ACC_PUBLIC)
1991     PHP_ME(swoole_redis_coro, time, arginfo_swoole_redis_coro_time, ZEND_ACC_PUBLIC)
1992     PHP_ME(swoole_redis_coro, role, arginfo_swoole_redis_coro_role, ZEND_ACC_PUBLIC)
1993     PHP_ME(swoole_redis_coro, setRange, arginfo_swoole_redis_coro_setRange, ZEND_ACC_PUBLIC)
1994     PHP_ME(swoole_redis_coro, setNx, arginfo_swoole_redis_coro_setnx, ZEND_ACC_PUBLIC)
1995     PHP_ME(swoole_redis_coro, getSet, arginfo_swoole_redis_coro_getSet, ZEND_ACC_PUBLIC)
1996     PHP_ME(swoole_redis_coro, append, arginfo_swoole_redis_coro_append, ZEND_ACC_PUBLIC)
1997     PHP_ME(swoole_redis_coro, lPushx, arginfo_swoole_redis_coro_lPushx, ZEND_ACC_PUBLIC)
1998     PHP_ME(swoole_redis_coro, lPush, arginfo_swoole_redis_coro_lPush, ZEND_ACC_PUBLIC)
1999     PHP_ME(swoole_redis_coro, rPush, arginfo_swoole_redis_coro_rPush, ZEND_ACC_PUBLIC)
2000     PHP_ME(swoole_redis_coro, rPushx, arginfo_swoole_redis_coro_rPushx, ZEND_ACC_PUBLIC)
2001     PHP_ME(swoole_redis_coro, sContains, arginfo_swoole_redis_coro_sContains, ZEND_ACC_PUBLIC)
2002     PHP_MALIAS(swoole_redis_coro, sismember, sContains, arginfo_swoole_redis_coro_key_value, ZEND_ACC_PUBLIC)
2003     PHP_ME(swoole_redis_coro, zScore, arginfo_swoole_redis_coro_zScore, ZEND_ACC_PUBLIC)
2004     PHP_ME(swoole_redis_coro, zRank, arginfo_swoole_redis_coro_zRank, ZEND_ACC_PUBLIC)
2005     PHP_ME(swoole_redis_coro, zRevRank, arginfo_swoole_redis_coro_zRevRank, ZEND_ACC_PUBLIC)
2006     PHP_ME(swoole_redis_coro, hGet, arginfo_swoole_redis_coro_hGet, ZEND_ACC_PUBLIC)
2007     PHP_ME(swoole_redis_coro, hMGet, arginfo_swoole_redis_coro_hMget, ZEND_ACC_PUBLIC)
2008     PHP_ME(swoole_redis_coro, hExists, arginfo_swoole_redis_coro_hExists, ZEND_ACC_PUBLIC)
2009     PHP_ME(swoole_redis_coro, publish, arginfo_swoole_redis_coro_publish, ZEND_ACC_PUBLIC)
2010     PHP_ME(swoole_redis_coro, zIncrBy, arginfo_swoole_redis_coro_zIncrBy, ZEND_ACC_PUBLIC)
2011     PHP_ME(swoole_redis_coro, zAdd, arginfo_swoole_redis_coro_zAdd, ZEND_ACC_PUBLIC)
2012     PHP_ME(swoole_redis_coro, zPopMin, arginfo_swoole_redis_coro_zPopMin, ZEND_ACC_PUBLIC)
2013     PHP_ME(swoole_redis_coro, zPopMax, arginfo_swoole_redis_coro_zPopMax, ZEND_ACC_PUBLIC)
2014     PHP_ME(swoole_redis_coro, bzPopMin, arginfo_swoole_redis_coro_bzPopMin, ZEND_ACC_PUBLIC)
2015     PHP_ME(swoole_redis_coro, bzPopMax, arginfo_swoole_redis_coro_bzPopMax, ZEND_ACC_PUBLIC)
2016     PHP_ME(swoole_redis_coro, zDeleteRangeByScore, arginfo_swoole_redis_coro_zDeleteRangeByScore, ZEND_ACC_PUBLIC)
2017     PHP_MALIAS(swoole_redis_coro, zRemRangeByScore, zDeleteRangeByScore, arginfo_swoole_redis_coro_zRemRangeByScore, ZEND_ACC_PUBLIC)
2018     PHP_ME(swoole_redis_coro, zCount, arginfo_swoole_redis_coro_zCount, ZEND_ACC_PUBLIC)
2019     PHP_ME(swoole_redis_coro, zRange, arginfo_swoole_redis_coro_zRange, ZEND_ACC_PUBLIC)
2020     PHP_ME(swoole_redis_coro, zRevRange, arginfo_swoole_redis_coro_zRevRange, ZEND_ACC_PUBLIC)
2021     PHP_ME(swoole_redis_coro, zRangeByScore, arginfo_swoole_redis_coro_zRangeByScore, ZEND_ACC_PUBLIC)
2022     PHP_ME(swoole_redis_coro, zRevRangeByScore, arginfo_swoole_redis_coro_zRevRangeByScore, ZEND_ACC_PUBLIC)
2023     PHP_ME(swoole_redis_coro, zRangeByLex, arginfo_swoole_redis_coro_zRangeByLex, ZEND_ACC_PUBLIC)
2024     PHP_ME(swoole_redis_coro, zRevRangeByLex, arginfo_swoole_redis_coro_zRevRangeByLex, ZEND_ACC_PUBLIC)
2025     PHP_ME(swoole_redis_coro, zInter, arginfo_swoole_redis_coro_zInter, ZEND_ACC_PUBLIC)
2026     PHP_MALIAS(swoole_redis_coro, zinterstore, zInter, arginfo_swoole_redis_coro_zinterstore, ZEND_ACC_PUBLIC)
2027     PHP_ME(swoole_redis_coro, zUnion, arginfo_swoole_redis_coro_zUnion, ZEND_ACC_PUBLIC)
2028     PHP_MALIAS(swoole_redis_coro, zunionstore, zUnion, arginfo_swoole_redis_coro_zunionstore, ZEND_ACC_PUBLIC)
2029     PHP_ME(swoole_redis_coro, incrBy, arginfo_swoole_redis_coro_incrBy, ZEND_ACC_PUBLIC)
2030     PHP_ME(swoole_redis_coro, hIncrBy, arginfo_swoole_redis_coro_hIncrBy, ZEND_ACC_PUBLIC)
2031     PHP_ME(swoole_redis_coro, incr, arginfo_swoole_redis_coro_incr, ZEND_ACC_PUBLIC)
2032     PHP_ME(swoole_redis_coro, decrBy, arginfo_swoole_redis_coro_decrBy, ZEND_ACC_PUBLIC)
2033     PHP_ME(swoole_redis_coro, decr, arginfo_swoole_redis_coro_decr, ZEND_ACC_PUBLIC)
2034     PHP_ME(swoole_redis_coro, getBit, arginfo_swoole_redis_coro_getBit, ZEND_ACC_PUBLIC)
2035     PHP_ME(swoole_redis_coro, lInsert, arginfo_swoole_redis_coro_lInsert, ZEND_ACC_PUBLIC)
2036     PHP_ME(swoole_redis_coro, lGet, arginfo_swoole_redis_coro_lGet, ZEND_ACC_PUBLIC)
2037     PHP_MALIAS(swoole_redis_coro, lIndex, lGet, arginfo_swoole_redis_coro_key_long, ZEND_ACC_PUBLIC)
2038     PHP_ME(swoole_redis_coro, setTimeout, arginfo_swoole_redis_coro_setTimeout, ZEND_ACC_PUBLIC)
2039     PHP_MALIAS(swoole_redis_coro, expire, setTimeout, arginfo_swoole_redis_coro_key_long, ZEND_ACC_PUBLIC)
2040     PHP_ME(swoole_redis_coro, pexpire, arginfo_swoole_redis_coro_pexpire, ZEND_ACC_PUBLIC)
2041     PHP_ME(swoole_redis_coro, expireAt, arginfo_swoole_redis_coro_expireAt, ZEND_ACC_PUBLIC)
2042     PHP_ME(swoole_redis_coro, pexpireAt, arginfo_swoole_redis_coro_pexpireAt, ZEND_ACC_PUBLIC)
2043     PHP_ME(swoole_redis_coro, move, arginfo_swoole_redis_coro_move, ZEND_ACC_PUBLIC)
2044     PHP_ME(swoole_redis_coro, select, arginfo_swoole_redis_coro_select, ZEND_ACC_PUBLIC)
2045     PHP_ME(swoole_redis_coro, getRange, arginfo_swoole_redis_coro_getRange, ZEND_ACC_PUBLIC)
2046     PHP_ME(swoole_redis_coro, listTrim, arginfo_swoole_redis_coro_listTrim, ZEND_ACC_PUBLIC)
2047     PHP_MALIAS(swoole_redis_coro, ltrim, listTrim, arginfo_swoole_redis_coro_ltrim, ZEND_ACC_PUBLIC)
2048     PHP_ME(swoole_redis_coro, lGetRange, arginfo_swoole_redis_coro_lGetRange, ZEND_ACC_PUBLIC)
2049     PHP_MALIAS(swoole_redis_coro, lRange, lGetRange, arginfo_swoole_redis_coro_lrange, ZEND_ACC_PUBLIC)
2050     PHP_ME(swoole_redis_coro, lRem, arginfo_swoole_redis_coro_lrem, ZEND_ACC_PUBLIC)
2051     PHP_MALIAS(swoole_redis_coro, lRemove,lRem, arginfo_swoole_redis_coro_lRemove, ZEND_ACC_PUBLIC)
2052     PHP_ME(swoole_redis_coro, zDeleteRangeByRank, arginfo_swoole_redis_coro_zDeleteRangeByRank, ZEND_ACC_PUBLIC)
2053     PHP_MALIAS(swoole_redis_coro, zRemRangeByRank, zDeleteRangeByRank, arginfo_swoole_redis_coro_zRemRangeByRank, ZEND_ACC_PUBLIC)
2054     PHP_ME(swoole_redis_coro, incrByFloat, arginfo_swoole_redis_coro_incrByFloat, ZEND_ACC_PUBLIC)
2055     PHP_ME(swoole_redis_coro, hIncrByFloat, arginfo_swoole_redis_coro_hIncrByFloat, ZEND_ACC_PUBLIC)
2056     PHP_ME(swoole_redis_coro, bitCount, arginfo_swoole_redis_coro_bitcount, ZEND_ACC_PUBLIC)
2057     PHP_ME(swoole_redis_coro, bitOp, arginfo_swoole_redis_coro_bitop, ZEND_ACC_PUBLIC)
2058     PHP_ME(swoole_redis_coro, sAdd, arginfo_swoole_redis_coro_sAdd, ZEND_ACC_PUBLIC)
2059     PHP_ME(swoole_redis_coro, sMove, arginfo_swoole_redis_coro_sMove, ZEND_ACC_PUBLIC)
2060     PHP_ME(swoole_redis_coro, sDiff, arginfo_swoole_redis_coro_sDiff, ZEND_ACC_PUBLIC)
2061     PHP_ME(swoole_redis_coro, sDiffStore, arginfo_swoole_redis_coro_sDiffStore, ZEND_ACC_PUBLIC)
2062     PHP_ME(swoole_redis_coro, sUnion, arginfo_swoole_redis_coro_sUnion, ZEND_ACC_PUBLIC)
2063     PHP_ME(swoole_redis_coro, sUnionStore, arginfo_swoole_redis_coro_sUnionStore, ZEND_ACC_PUBLIC)
2064     PHP_ME(swoole_redis_coro, sInter, arginfo_swoole_redis_coro_sInter, ZEND_ACC_PUBLIC)
2065     PHP_ME(swoole_redis_coro, sInterStore, arginfo_swoole_redis_coro_sInterStore, ZEND_ACC_PUBLIC)
2066     PHP_ME(swoole_redis_coro, sRemove, arginfo_swoole_redis_coro_sRemove, ZEND_ACC_PUBLIC)
2067     PHP_MALIAS(swoole_redis_coro, srem, sRemove, arginfo_swoole_redis_coro_key_value, ZEND_ACC_PUBLIC)
2068     PHP_ME(swoole_redis_coro, zDelete, arginfo_swoole_redis_coro_zDelete, ZEND_ACC_PUBLIC)
2069     PHP_MALIAS(swoole_redis_coro, zRemove, zDelete, arginfo_swoole_redis_coro_zRemove, ZEND_ACC_PUBLIC)
2070     PHP_MALIAS(swoole_redis_coro, zRem, zDelete, arginfo_swoole_redis_coro_zRem, ZEND_ACC_PUBLIC)
2071     PHP_ME(swoole_redis_coro, pSubscribe, arginfo_swoole_redis_coro_psubscribe, ZEND_ACC_PUBLIC)
2072     PHP_ME(swoole_redis_coro, subscribe, arginfo_swoole_redis_coro_subscribe, ZEND_ACC_PUBLIC)
2073     PHP_ME(swoole_redis_coro, unsubscribe, arginfo_swoole_redis_coro_unsubscribe, ZEND_ACC_PUBLIC)
2074     PHP_ME(swoole_redis_coro, pUnSubscribe, arginfo_swoole_redis_coro_punsubscribe, ZEND_ACC_PUBLIC)
2075     PHP_ME(swoole_redis_coro, multi, arginfo_swoole_redis_coro_multi, ZEND_ACC_PUBLIC)
2076     PHP_ME(swoole_redis_coro, exec, arginfo_swoole_redis_coro_exec, ZEND_ACC_PUBLIC)
2077     PHP_ME(swoole_redis_coro, eval, arginfo_swoole_redis_coro_eval, ZEND_ACC_PUBLIC)
2078     PHP_ME(swoole_redis_coro, evalSha, arginfo_swoole_redis_coro_evalsha, ZEND_ACC_PUBLIC)
2079     PHP_ME(swoole_redis_coro, script, arginfo_swoole_redis_coro_script, ZEND_ACC_PUBLIC)
2080     PHP_ME(swoole_redis_coro, xLen, arginfo_swoole_redis_coro_xLen, ZEND_ACC_PUBLIC)
2081     PHP_ME(swoole_redis_coro, xAdd, arginfo_swoole_redis_coro_xAdd, ZEND_ACC_PUBLIC)
2082     PHP_ME(swoole_redis_coro, xRead, arginfo_swoole_redis_coro_xRead, ZEND_ACC_PUBLIC)
2083     PHP_ME(swoole_redis_coro, xDel, arginfo_swoole_redis_coro_xDel, ZEND_ACC_PUBLIC)
2084     PHP_ME(swoole_redis_coro, xRange, arginfo_swoole_redis_coro_xRange, ZEND_ACC_PUBLIC)
2085     PHP_ME(swoole_redis_coro, xRevRange, arginfo_swoole_redis_coro_xRevRange, ZEND_ACC_PUBLIC)
2086     PHP_ME(swoole_redis_coro, xTrim, arginfo_swoole_redis_coro_xTrim, ZEND_ACC_PUBLIC)
2087     PHP_ME(swoole_redis_coro, xGroupCreate, arginfo_swoole_redis_coro_xGroupCreate, ZEND_ACC_PUBLIC)
2088     PHP_ME(swoole_redis_coro, xGroupSetId, arginfo_swoole_redis_coro_xGroupSetId, ZEND_ACC_PUBLIC)
2089     PHP_ME(swoole_redis_coro, xGroupDestroy, arginfo_swoole_redis_coro_xGroupDestroy, ZEND_ACC_PUBLIC)
2090     PHP_ME(swoole_redis_coro, xGroupCreateConsumer, arginfo_swoole_redis_coro_xGroupCreateConsumer, ZEND_ACC_PUBLIC)
2091     PHP_ME(swoole_redis_coro, xGroupDelConsumer, arginfo_swoole_redis_coro_xGroupDelConsumer, ZEND_ACC_PUBLIC)
2092     PHP_ME(swoole_redis_coro, xReadGroup, arginfo_swoole_redis_coro_xReadGroup, ZEND_ACC_PUBLIC)
2093     PHP_ME(swoole_redis_coro, xPending, arginfo_swoole_redis_coro_xPending, ZEND_ACC_PUBLIC)
2094     PHP_ME(swoole_redis_coro, xAck, arginfo_swoole_redis_coro_xAck, ZEND_ACC_PUBLIC)
2095     PHP_ME(swoole_redis_coro, xClaim, arginfo_swoole_redis_coro_xClaim, ZEND_ACC_PUBLIC)
2096     PHP_ME(swoole_redis_coro, xAutoClaim, arginfo_swoole_redis_coro_xAutoClaim, ZEND_ACC_PUBLIC)
2097     PHP_ME(swoole_redis_coro, xInfoConsumers, arginfo_swoole_redis_coro_xInfoConsumers, ZEND_ACC_PUBLIC)
2098     PHP_ME(swoole_redis_coro, xInfoGroups, arginfo_swoole_redis_coro_xInfoGroups, ZEND_ACC_PUBLIC)
2099     PHP_ME(swoole_redis_coro, xInfoStream, arginfo_swoole_redis_coro_xInfoStream, ZEND_ACC_PUBLIC)
2100     /*---------------------Redis Command End------------------------*/
2101     PHP_FE_END
2102 };
2103 // clang-format on
2104 
php_swoole_redis_coro_minit(int module_number)2105 void php_swoole_redis_coro_minit(int module_number) {
2106     SW_INIT_CLASS_ENTRY(swoole_redis_coro, "Swoole\\Coroutine\\Redis", nullptr, "Co\\Redis", swoole_redis_coro_methods);
2107     SW_SET_CLASS_NOT_SERIALIZABLE(swoole_redis_coro);
2108     SW_SET_CLASS_CLONEABLE(swoole_redis_coro, sw_zend_class_clone_deny);
2109     SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_redis_coro, sw_zend_class_unset_property_deny);
2110     SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_redis_coro);
2111     SW_SET_CLASS_CUSTOM_OBJECT(
2112         swoole_redis_coro, php_swoole_redis_coro_create_object, php_swoole_redis_coro_free_object, RedisClient, std);
2113 
2114     zend_declare_property_string(swoole_redis_coro_ce, ZEND_STRL("host"), "", ZEND_ACC_PUBLIC);
2115     zend_declare_property_long(swoole_redis_coro_ce, ZEND_STRL("port"), 0, ZEND_ACC_PUBLIC);
2116     zend_declare_property_null(swoole_redis_coro_ce, ZEND_STRL("setting"), ZEND_ACC_PUBLIC);
2117     zend_declare_property_long(swoole_redis_coro_ce, ZEND_STRL("sock"), -1, ZEND_ACC_PUBLIC);
2118     zend_declare_property_bool(swoole_redis_coro_ce, ZEND_STRL("connected"), 0, ZEND_ACC_PUBLIC);
2119     zend_declare_property_long(swoole_redis_coro_ce, ZEND_STRL("errType"), 0, ZEND_ACC_PUBLIC);
2120     zend_declare_property_long(swoole_redis_coro_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC);
2121     zend_declare_property_string(swoole_redis_coro_ce, ZEND_STRL("errMsg"), "", ZEND_ACC_PUBLIC);
2122 
2123     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_MODE_MULTI", SW_REDIS_MODE_MULTI);
2124     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_MODE_PIPELINE", SW_REDIS_MODE_PIPELINE);
2125 
2126     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_NOT_FOUND", SW_REDIS_TYPE_NOT_FOUND);
2127     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_STRING", SW_REDIS_TYPE_STRING);
2128     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_SET", SW_REDIS_TYPE_SET);
2129     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_LIST", SW_REDIS_TYPE_LIST);
2130     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_ZSET", SW_REDIS_TYPE_ZSET);
2131     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_TYPE_HASH", SW_REDIS_TYPE_HASH);
2132 
2133     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_IO", SW_REDIS_ERR_IO);
2134     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_OTHER", SW_REDIS_ERR_OTHER);
2135     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_EOF", SW_REDIS_ERR_EOF);
2136     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_PROTOCOL", SW_REDIS_ERR_PROTOCOL);
2137     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_OOM", SW_REDIS_ERR_OOM);
2138     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_CLOSED", SW_REDIS_ERR_CLOSED);
2139     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_NOAUTH", SW_REDIS_ERR_NOAUTH);
2140     SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_ALLOC", SW_REDIS_ERR_ALLOC);
2141 }
2142 
swoole_redis_coro_set_options(RedisClient * redis,zval * zoptions,bool backward_compatibility=false)2143 static void swoole_redis_coro_set_options(RedisClient *redis, zval *zoptions, bool backward_compatibility = false) {
2144     zval *zsettings =
2145         sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, redis->zobject, ZEND_STRL("setting"), 0);
2146     HashTable *vht = Z_ARRVAL_P(zoptions);
2147     zval *ztmp;
2148 
2149     php_array_merge(Z_ARRVAL_P(zsettings), vht);
2150 
2151     if (php_swoole_array_get_value(vht, "connect_timeout", ztmp)) {
2152         redis->connect_timeout = zval_get_double(ztmp);
2153         if (redis->connect_timeout <= 0) {
2154             redis->connect_timeout = SW_TIMER_MAX_SEC;
2155         }
2156     }
2157     if (php_swoole_array_get_value(vht, "timeout", ztmp)) {
2158         redis->timeout = zval_get_double(ztmp);
2159         if (backward_compatibility) {
2160             redis->connect_timeout = redis->timeout;
2161             if (redis->connect_timeout <= 0) {
2162                 redis->connect_timeout = SW_TIMER_MAX_SEC;
2163             }
2164         }
2165         if (redis->context) {
2166             Socket *socket = swoole_redis_coro_get_socket(redis->context);
2167             if (socket) {
2168                 socket->set_timeout(redis->timeout, Socket::TIMEOUT_RDWR);
2169             }
2170         }
2171     }
2172     if (php_swoole_array_get_value(vht, "serialize", ztmp)) {
2173         redis->serialize = zval_is_true(ztmp);
2174     }
2175     if (php_swoole_array_get_value(vht, "reconnect", ztmp)) {
2176         redis->reconnect_interval = (uint8_t) SW_MIN(zval_get_long(ztmp), UINT8_MAX);
2177     }
2178     if (php_swoole_array_get_value(vht, "compatibility_mode", ztmp)) {
2179         redis->compatibility_mode = zval_is_true(ztmp);
2180     }
2181 }
2182 
PHP_METHOD(swoole_redis_coro,__construct)2183 static PHP_METHOD(swoole_redis_coro, __construct) {
2184     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2185     zval *zsettings = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0);
2186     zval *zset = nullptr;
2187 
2188     ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 0, 1)
2189     Z_PARAM_OPTIONAL
2190     Z_PARAM_ARRAY(zset)
2191     ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2192 
2193     if (redis->zobject) {
2194         php_swoole_fatal_error(E_ERROR, "Constructor of %s can only be called once", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS));
2195         RETURN_FALSE;
2196     }
2197 
2198     redis->zobject = &redis->_zobject;
2199     redis->_zobject = *ZEND_THIS;
2200 
2201     redis->connect_timeout = network::Socket::default_connect_timeout;
2202     redis->timeout = network::Socket::default_read_timeout;
2203     redis->reconnect_interval = 1;
2204 
2205     // settings init
2206     add_assoc_double(zsettings, "connect_timeout", redis->connect_timeout);
2207     add_assoc_double(zsettings, "timeout", redis->timeout);
2208     add_assoc_bool(zsettings, "serialize", redis->serialize);
2209     add_assoc_long(zsettings, "reconnect", redis->reconnect_interval);
2210     // after connected
2211     add_assoc_string(zsettings, "password", (char *) "");
2212     add_assoc_long(zsettings, "database", 0);
2213 
2214     if (zset) {
2215         swoole_redis_coro_set_options(redis, zset, true);
2216     }
2217 }
2218 
PHP_METHOD(swoole_redis_coro,connect)2219 static PHP_METHOD(swoole_redis_coro, connect) {
2220     zval *zobject = ZEND_THIS;
2221     char *host = nullptr;
2222     size_t host_len = 0;
2223     zend_long port = 0;
2224     zend_bool serialize = 0;
2225 
2226     SW_REDIS_COMMAND_CHECK
2227 
2228     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lb", &host, &host_len, &port, &serialize) == FAILURE) {
2229         RETURN_FALSE;
2230     }
2231 
2232     zend_update_property_string(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("host"), host);
2233     zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("port"), port);
2234     redis->serialize = serialize;
2235 
2236     if (swoole_redis_coro_connect(redis) > 0) {
2237         // clear the error code only when the developer manually tries to connect successfully
2238         // if the kernel retries automatically, keep silent.
2239         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errType"), 0);
2240         zend_update_property_long(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), 0);
2241         zend_update_property_string(swoole_redis_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), "");
2242         RETURN_TRUE;
2243     } else {
2244         RETURN_FALSE;
2245     }
2246 }
2247 
PHP_METHOD(swoole_redis_coro,getAuth)2248 static PHP_METHOD(swoole_redis_coro, getAuth) {
2249     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2250     if (redis->session.auth) {
2251         zval *ztmp = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0);
2252         if (php_swoole_array_get_value(Z_ARRVAL_P(ztmp), "password", ztmp)) {
2253             RETURN_ZVAL(ztmp, 1, 0);
2254         }
2255         RETURN_EMPTY_STRING();
2256     }
2257     RETURN_FALSE;
2258 }
2259 
PHP_METHOD(swoole_redis_coro,getDBNum)2260 static PHP_METHOD(swoole_redis_coro, getDBNum) {
2261     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2262     if (!redis->context) {
2263         RETURN_FALSE;
2264     }
2265     RETURN_LONG(redis->session.db_num);
2266 }
2267 
PHP_METHOD(swoole_redis_coro,getOptions)2268 static PHP_METHOD(swoole_redis_coro, getOptions) {
2269     RETURN_ZVAL(
2270         sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0), 1, 0);
2271 }
2272 
PHP_METHOD(swoole_redis_coro,setOptions)2273 static PHP_METHOD(swoole_redis_coro, setOptions) {
2274     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2275     zval *zoptions;
2276 
2277     ZEND_PARSE_PARAMETERS_START(1, 1)
2278     Z_PARAM_ARRAY(zoptions)
2279     ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2280 
2281     swoole_redis_coro_set_options(redis, zoptions);
2282 
2283     RETURN_TRUE;
2284 }
2285 
PHP_METHOD(swoole_redis_coro,getDefer)2286 static PHP_METHOD(swoole_redis_coro, getDefer) {
2287     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2288 
2289     RETURN_BOOL(redis->defer);
2290 }
2291 
PHP_METHOD(swoole_redis_coro,setDefer)2292 static PHP_METHOD(swoole_redis_coro, setDefer) {
2293     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2294     zend_bool defer = 1;
2295 
2296     if (redis->session.subscribe) {
2297         php_swoole_fatal_error(E_WARNING, "you should not use setDefer after subscribe");
2298         RETURN_FALSE;
2299     }
2300     if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &defer) == FAILURE) {
2301         RETURN_FALSE;
2302     }
2303     redis->defer = defer;
2304 
2305     RETURN_TRUE;
2306 }
2307 
PHP_METHOD(swoole_redis_coro,recv)2308 static PHP_METHOD(swoole_redis_coro, recv) {
2309     SW_REDIS_COMMAND_CHECK
2310 
2311     if (UNEXPECTED(!redis->context)) {
2312         RETURN_FALSE;
2313     }
2314     if (UNEXPECTED(!redis->defer && !redis->session.subscribe)) {
2315         php_swoole_fatal_error(E_WARNING, "you should not use recv without defer or subscribe");
2316         RETURN_FALSE;
2317     }
2318 
2319     redisReply *reply;
2320 _recv:
2321     if (redisGetReply(redis->context, (void **) &reply) == REDIS_OK) {
2322         swoole_redis_coro_parse_result(redis, return_value, reply);
2323         freeReplyObject(reply);
2324 
2325         if (redis->session.subscribe) {
2326             zval *ztype;
2327 
2328             if (!ZVAL_IS_ARRAY(return_value)) {
2329                 zval_ptr_dtor(return_value);
2330                 goto _error;
2331             }
2332 
2333             ztype = zend_hash_index_find(Z_ARRVAL_P(return_value), 0);
2334             if (Z_TYPE_P(ztype) == IS_STRING) {
2335                 char *type = Z_STRVAL_P(ztype);
2336 
2337                 if (!strcmp(type, "unsubscribe") || !strcmp(type, "punsubscribe")) {
2338                     zval *znum = zend_hash_index_find(Z_ARRVAL_P(return_value), 2);
2339                     if (Z_LVAL_P(znum) == 0) {
2340                         redis->session.subscribe = false;
2341                     }
2342 
2343                     return;
2344                 } else if (!strcmp(type, "message") || !strcmp(type, "pmessage") || !strcmp(type, "subscribe") ||
2345                            !strcmp(type, "psubscribe")) {
2346                     return;
2347                 }
2348             }
2349 
2350             zval_ptr_dtor(return_value);
2351             goto _recv;
2352         }
2353     } else {
2354     _error:
2355         zend_update_property_long(
2356             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), redis->context->err);
2357         zend_update_property_long(swoole_redis_coro_ce,
2358                                   SW_Z8_OBJ_P(redis->zobject),
2359                                   ZEND_STRL("errCode"),
2360                                   sw_redis_convert_err(redis->context->err));
2361         zend_update_property_string(
2362             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), redis->context->errstr);
2363 
2364         swoole_redis_coro_close(redis);
2365         RETURN_FALSE;
2366     }
2367 }
2368 
PHP_METHOD(swoole_redis_coro,close)2369 static PHP_METHOD(swoole_redis_coro, close) {
2370     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
2371     RETURN_BOOL(swoole_redis_coro_close(redis));
2372 }
2373 
PHP_METHOD(swoole_redis_coro,__destruct)2374 static PHP_METHOD(swoole_redis_coro, __destruct) {
2375     SW_PREVENT_USER_DESTRUCT();
2376 }
2377 
PHP_METHOD(swoole_redis_coro,set)2378 static PHP_METHOD(swoole_redis_coro, set) {
2379     char *key, *exp_type = nullptr, *set_type = nullptr;
2380     size_t key_len, argc = 3;
2381     zval *z_value, *z_opts = nullptr;
2382     zend_long expire = -1;
2383 
2384     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|z", &key, &key_len, &z_value, &z_opts) == FAILURE) {
2385         RETURN_FALSE;
2386     }
2387 
2388     SW_REDIS_COMMAND_CHECK
2389 
2390     if (z_opts && Z_TYPE_P(z_opts) != IS_LONG && Z_TYPE_P(z_opts) != IS_ARRAY && Z_TYPE_P(z_opts) != IS_NULL) {
2391         RETURN_FALSE;
2392     }
2393 
2394     if (z_opts && ZVAL_IS_ARRAY(z_opts)) {
2395         HashTable *kt = Z_ARRVAL_P(z_opts);
2396 
2397         zend_string *zkey;
2398         zend_ulong idx;
2399         zval *zv;
2400 
2401         /* Iterate our option array */
2402         ZEND_HASH_FOREACH_KEY_VAL(kt, idx, zkey, zv) {
2403             /* Detect PX or EX argument and validate timeout */
2404             if (!exp_type && zkey && IS_EX_PX_ARG(ZSTR_VAL(zkey))) {
2405                 /* Set expire type */
2406                 exp_type = ZSTR_VAL(zkey);
2407 
2408                 /* Try to extract timeout */
2409                 if (Z_TYPE_P(zv) == IS_LONG) {
2410                     expire = Z_LVAL_P(zv);
2411                 } else if (Z_TYPE_P(zv) == IS_STRING) {
2412                     expire = atol(Z_STRVAL_P(zv));
2413                 }
2414 
2415                 /* Expiry can't be set < 1 */
2416                 if (expire < 1) {
2417                     RETURN_FALSE;
2418                 }
2419                 argc += 2;
2420             } else if (!set_type && Z_TYPE_P(zv) == IS_STRING && IS_NX_XX_ARG(Z_STRVAL_P(zv))) {
2421                 argc += 1;
2422                 set_type = Z_STRVAL_P(zv);
2423             }
2424             (void) idx;
2425         }
2426         ZEND_HASH_FOREACH_END();
2427     } else if (z_opts && Z_TYPE_P(z_opts) == IS_LONG) {
2428         /* Grab expiry and fail if it's < 1 */
2429         expire = Z_LVAL_P(z_opts);
2430         /* Expiry can't be set < 1 */
2431         if (expire < 1) {
2432             RETURN_FALSE;
2433         }
2434         argc += 1;
2435     }
2436 
2437     SW_REDIS_COMMAND_ALLOC_ARGV
2438 
2439     int i = 0;
2440     if (exp_type || set_type) {
2441         SW_REDIS_COMMAND_ARGV_FILL("SET", 3)
2442         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2443         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_value)
2444 
2445         if (set_type) {
2446             SW_REDIS_COMMAND_ARGV_FILL(set_type, (size_t) strlen(set_type))
2447         }
2448 
2449         if (exp_type) {
2450             SW_REDIS_COMMAND_ARGV_FILL(exp_type, (size_t) strlen(exp_type))
2451 
2452             char str[32];
2453             sprintf(str, ZEND_LONG_FMT, expire);
2454             SW_REDIS_COMMAND_ARGV_FILL(str, (size_t) strlen(str))
2455         }
2456     } else if (expire > 0) {
2457         SW_REDIS_COMMAND_ARGV_FILL("SETEX", 5)
2458         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2459 
2460         char str[32];
2461         sprintf(str, ZEND_LONG_FMT, expire);
2462         SW_REDIS_COMMAND_ARGV_FILL(str, (size_t) strlen(str))
2463 
2464         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_value)
2465     } else {
2466         SW_REDIS_COMMAND_ARGV_FILL("SET", 3)
2467         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2468         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_value)
2469     }
2470 
2471     redis_request(redis, argc, argv, argvlen, return_value);
2472 
2473     SW_REDIS_COMMAND_FREE_ARGV
2474 }
2475 
PHP_METHOD(swoole_redis_coro,setBit)2476 static PHP_METHOD(swoole_redis_coro, setBit) {
2477     char *key;
2478     size_t key_len;
2479     long offset;
2480     zend_bool val;
2481 
2482     if (zend_parse_parameters(ZEND_NUM_ARGS(), "slb", &key, &key_len, &offset, &val) == FAILURE) {
2483         return;
2484     }
2485 
2486     // Validate our offset
2487     if (offset < SW_BITOP_MIN_OFFSET || offset > SW_BITOP_MAX_OFFSET) {
2488         zend_update_property_long(
2489             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
2490         zend_update_property_long(swoole_redis_coro_ce,
2491                                   SW_Z8_OBJ_P(ZEND_THIS),
2492                                   ZEND_STRL("errCode"),
2493                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
2494         zend_update_property_string(swoole_redis_coro_ce,
2495                                     SW_Z8_OBJ_P(ZEND_THIS),
2496                                     ZEND_STRL("errMsg"),
2497                                     "Invalid OFFSET for bitop command (must be between 0-2^32-1)");
2498         RETURN_FALSE;
2499     }
2500 
2501     SW_REDIS_COMMAND_CHECK
2502 
2503     int i = 0;
2504     size_t argvlen[4];
2505     char *argv[4];
2506 
2507     SW_REDIS_COMMAND_ARGV_FILL("SETBIT", 6)
2508     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2509 
2510     char str[32];
2511     sprintf(str, "%ld", offset);
2512     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
2513 
2514     SW_REDIS_COMMAND_ARGV_FILL(val ? "1" : "0", 1)
2515     redis_request(redis, 4, argv, argvlen, return_value);
2516 }
2517 
PHP_METHOD(swoole_redis_coro,setEx)2518 static PHP_METHOD(swoole_redis_coro, setEx) {
2519     sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SETEX"));
2520 }
2521 
PHP_METHOD(swoole_redis_coro,psetEx)2522 static PHP_METHOD(swoole_redis_coro, psetEx) {
2523     sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PSETEX"));
2524 }
2525 
PHP_METHOD(swoole_redis_coro,lSet)2526 static PHP_METHOD(swoole_redis_coro, lSet) {
2527     sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LSET"));
2528 }
2529 
PHP_METHOD(swoole_redis_coro,restore)2530 static PHP_METHOD(swoole_redis_coro, restore) {
2531     sw_redis_command_key_long_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RESTORE"));
2532 }
2533 
PHP_METHOD(swoole_redis_coro,dump)2534 static PHP_METHOD(swoole_redis_coro, dump) {
2535     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DUMP"));
2536 }
2537 
PHP_METHOD(swoole_redis_coro,debug)2538 static PHP_METHOD(swoole_redis_coro, debug) {
2539     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DEBUG"));
2540 }
2541 
PHP_METHOD(swoole_redis_coro,get)2542 static PHP_METHOD(swoole_redis_coro, get) {
2543     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("GET"));
2544 }
2545 
PHP_METHOD(swoole_redis_coro,mGet)2546 static PHP_METHOD(swoole_redis_coro, mGet) {
2547     zval *z_args;
2548     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &z_args) == FAILURE) {
2549         RETURN_FALSE;
2550     }
2551     int argc;
2552     argc = zend_hash_num_elements(Z_ARRVAL_P(z_args));
2553     if (argc == 0) {
2554         RETURN_FALSE;
2555     }
2556     SW_REDIS_COMMAND_CHECK
2557     argc++;
2558     SW_REDIS_COMMAND_ALLOC_ARGV
2559     int i = 0;
2560     zval *value;
2561     SW_REDIS_COMMAND_ARGV_FILL("MGET", 4)
2562     SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(z_args), value)
2563     zend_string *convert_str = zval_get_string(value);
2564     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2565     zend_string_release(convert_str);
2566     SW_HASHTABLE_FOREACH_END();
2567 
2568     redis_request(redis, argc, argv, argvlen, return_value);
2569     SW_REDIS_COMMAND_FREE_ARGV
2570 }
2571 
PHP_METHOD(swoole_redis_coro,hSet)2572 static PHP_METHOD(swoole_redis_coro, hSet) {
2573     char *key, *field;
2574     size_t key_len, field_len;
2575     zval *z_val;
2576 
2577     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssz", &key, &key_len, &field, &field_len, &z_val) == FAILURE) {
2578         return;
2579     }
2580     SW_REDIS_COMMAND_CHECK
2581     int i = 0;
2582     size_t argvlen[4];
2583     char *argv[4];
2584     SW_REDIS_COMMAND_ARGV_FILL("HSET", 4)
2585     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2586     SW_REDIS_COMMAND_ARGV_FILL(field, field_len)
2587     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_val)
2588 
2589     redis_request(redis, 4, argv, argvlen, return_value);
2590 }
2591 
PHP_METHOD(swoole_redis_coro,hMSet)2592 static PHP_METHOD(swoole_redis_coro, hMSet) {
2593     char *key;
2594     size_t key_len, argc;
2595     zval *z_arr;
2596 
2597     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &key, &key_len, &z_arr) == FAILURE) {
2598         return;
2599     }
2600     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_arr))) == 0) {
2601         RETURN_FALSE;
2602     }
2603     SW_REDIS_COMMAND_CHECK
2604     int i = 0;
2605     argc = argc * 2 + 2;
2606     zval *value;
2607     char buf[32];
2608     SW_REDIS_COMMAND_ALLOC_ARGV
2609     SW_REDIS_COMMAND_ARGV_FILL("HMSET", 5)
2610     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2611     zend_ulong idx;
2612     zend_string *_key;
2613     ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(z_arr), idx, _key, value) {
2614         if (_key == nullptr) {
2615             key_len = sw_snprintf(buf, sizeof(buf), "%ld", (long) idx);
2616             key = (char *) buf;
2617         } else {
2618             key_len = ZSTR_LEN(_key);
2619             key = ZSTR_VAL(_key);
2620         }
2621         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2622         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(value)
2623     }
2624     ZEND_HASH_FOREACH_END();
2625 
2626     redis_request(redis, argc, argv, argvlen, return_value);
2627     SW_REDIS_COMMAND_FREE_ARGV
2628 }
2629 
PHP_METHOD(swoole_redis_coro,hSetNx)2630 static PHP_METHOD(swoole_redis_coro, hSetNx) {
2631     char *key, *field;
2632     size_t key_len, field_len;
2633     zval *z_val;
2634 
2635     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssz", &key, &key_len, &field, &field_len, &z_val) == FAILURE) {
2636         return;
2637     }
2638     SW_REDIS_COMMAND_CHECK
2639     int i = 0;
2640     size_t argvlen[4];
2641     char *argv[4];
2642     convert_to_string(z_val);
2643     SW_REDIS_COMMAND_ARGV_FILL("HSETNX", 6)
2644     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2645     SW_REDIS_COMMAND_ARGV_FILL(field, field_len)
2646     SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_val), Z_STRLEN_P(z_val))
2647 
2648     redis_request(redis, 4, argv, argvlen, return_value);
2649 }
2650 
PHP_METHOD(swoole_redis_coro,hDel)2651 static PHP_METHOD(swoole_redis_coro, hDel) {
2652     int argc = ZEND_NUM_ARGS();
2653     SW_REDIS_COMMAND_CHECK
2654     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
2655     if (argc < 2 || zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
2656         efree(z_args);
2657         RETURN_FALSE;
2658     }
2659     argc++;
2660     int i = 0, j;
2661     SW_REDIS_COMMAND_ALLOC_ARGV
2662     SW_REDIS_COMMAND_ARGV_FILL("HDEL", 4)
2663     for (j = 0; j < argc - 1; ++j) {
2664         zend_string *convert_str = zval_get_string(&z_args[j]);
2665         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2666         zend_string_release(convert_str);
2667     }
2668     efree(z_args);
2669     redis_request(redis, argc, argv, argvlen, return_value);
2670     SW_REDIS_COMMAND_FREE_ARGV
2671 }
2672 
PHP_METHOD(swoole_redis_coro,watch)2673 static PHP_METHOD(swoole_redis_coro, watch) {
2674     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("WATCH"), 1, 0);
2675 }
2676 
PHP_METHOD(swoole_redis_coro,del)2677 static PHP_METHOD(swoole_redis_coro, del) {
2678     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DEL"), 1, 0);
2679 }
2680 
PHP_METHOD(swoole_redis_coro,sDiff)2681 static PHP_METHOD(swoole_redis_coro, sDiff) {
2682     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SDIFF"), 1, 0);
2683 }
2684 
PHP_METHOD(swoole_redis_coro,sDiffStore)2685 static PHP_METHOD(swoole_redis_coro, sDiffStore) {
2686     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SDIFFSTORE"), 1, 0);
2687 }
2688 
PHP_METHOD(swoole_redis_coro,sUnion)2689 static PHP_METHOD(swoole_redis_coro, sUnion) {
2690     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SUNION"), 1, 0);
2691 }
2692 
PHP_METHOD(swoole_redis_coro,sUnionStore)2693 static PHP_METHOD(swoole_redis_coro, sUnionStore) {
2694     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SUNIONSTORE"), 1, 0);
2695 }
2696 
PHP_METHOD(swoole_redis_coro,sInter)2697 static PHP_METHOD(swoole_redis_coro, sInter) {
2698     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SINTER"), 1, 0);
2699 }
2700 
PHP_METHOD(swoole_redis_coro,sInterStore)2701 static PHP_METHOD(swoole_redis_coro, sInterStore) {
2702     sw_redis_command_var_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SINTERSTORE"), 1, 0);
2703 }
2704 
PHP_METHOD(swoole_redis_coro,mSet)2705 static PHP_METHOD(swoole_redis_coro, mSet) {
2706     zval *z_args;
2707     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &z_args) == FAILURE) {
2708         RETURN_FALSE;
2709     }
2710     int argc;
2711     argc = zend_hash_num_elements(Z_ARRVAL_P(z_args));
2712     if (argc == 0) {
2713         RETURN_FALSE;
2714     }
2715     SW_REDIS_COMMAND_CHECK
2716     argc *= 2;
2717     argc++;
2718     SW_REDIS_COMMAND_ALLOC_ARGV
2719     int i = 0;
2720     SW_REDIS_COMMAND_ARGV_FILL("MSET", 4)
2721     zval *value;
2722     char buf[32];
2723     char *key;
2724     uint32_t key_len;
2725     zend_ulong idx;
2726     zend_string *_key;
2727     ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(z_args), idx, _key, value) {
2728         if (_key == nullptr) {
2729             key_len = sw_snprintf(buf, sizeof(buf), "%ld", (long) idx);
2730             key = (char *) buf;
2731         } else {
2732             key_len = ZSTR_LEN(_key);
2733             key = ZSTR_VAL(_key);
2734         }
2735         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2736         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(value)
2737     }
2738     ZEND_HASH_FOREACH_END();
2739 
2740     redis_request(redis, argc, argv, argvlen, return_value);
2741     SW_REDIS_COMMAND_FREE_ARGV
2742 }
2743 
PHP_METHOD(swoole_redis_coro,mSetNx)2744 static PHP_METHOD(swoole_redis_coro, mSetNx) {
2745     zval *z_args;
2746     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &z_args) == FAILURE) {
2747         return;
2748     }
2749     int argc;
2750     argc = zend_hash_num_elements(Z_ARRVAL_P(z_args));
2751     if (argc == 0) {
2752         RETURN_FALSE;
2753     }
2754     SW_REDIS_COMMAND_CHECK
2755     argc *= 2;
2756     argc++;
2757     SW_REDIS_COMMAND_ALLOC_ARGV
2758     int i = 0;
2759     SW_REDIS_COMMAND_ARGV_FILL("MSETNX", 6)
2760     zval *value;
2761     char buf[32];
2762     char *key;
2763     uint32_t key_len;
2764     zend_ulong idx;
2765     zend_string *_key;
2766     ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(z_args), idx, _key, value) {
2767         if (_key == nullptr) {
2768             key_len = sw_snprintf(buf, sizeof(buf), "%ld", (long) idx);
2769             key = (char *) buf;
2770         } else {
2771             key_len = ZSTR_LEN(_key);
2772             key = ZSTR_VAL(_key);
2773         }
2774         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
2775         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(value)
2776     }
2777     ZEND_HASH_FOREACH_END();
2778 
2779     redis_request(redis, argc, argv, argvlen, return_value);
2780     SW_REDIS_COMMAND_FREE_ARGV
2781 }
2782 
PHP_METHOD(swoole_redis_coro,getKeys)2783 static PHP_METHOD(swoole_redis_coro, getKeys) {
2784     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("KEYS"));
2785 }
2786 
PHP_METHOD(swoole_redis_coro,exists)2787 static PHP_METHOD(swoole_redis_coro, exists) {
2788     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("EXISTS"));
2789 }
2790 
PHP_METHOD(swoole_redis_coro,type)2791 static PHP_METHOD(swoole_redis_coro, type) {
2792     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("TYPE"));
2793 }
2794 
PHP_METHOD(swoole_redis_coro,strLen)2795 static PHP_METHOD(swoole_redis_coro, strLen) {
2796     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("STRLEN"));
2797 }
2798 
PHP_METHOD(swoole_redis_coro,lPop)2799 static PHP_METHOD(swoole_redis_coro, lPop) {
2800     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LPOP"));
2801 }
2802 
PHP_METHOD(swoole_redis_coro,bRPopLPush)2803 static PHP_METHOD(swoole_redis_coro, bRPopLPush) {
2804     char *key1, *key2;
2805     size_t key1_len, key2_len;
2806     long timeout;
2807 
2808     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl", &key1, &key1_len, &key2, &key2_len, &timeout) == FAILURE) {
2809         return;
2810     }
2811     SW_REDIS_COMMAND_CHECK
2812     int argc, i = 0;
2813     argc = timeout < 0 ? 3 : 4;
2814     SW_REDIS_COMMAND_ALLOC_ARGV
2815     if (timeout < 0) {
2816         SW_REDIS_COMMAND_ARGV_FILL("RPOPLPUSH", 9)
2817         SW_REDIS_COMMAND_ARGV_FILL(key1, key1_len)
2818         SW_REDIS_COMMAND_ARGV_FILL(key2, key2_len)
2819     } else {
2820         SW_REDIS_COMMAND_ARGV_FILL("BRPOPLPUSH", 10)
2821         SW_REDIS_COMMAND_ARGV_FILL(key1, key1_len)
2822         SW_REDIS_COMMAND_ARGV_FILL(key2, key2_len)
2823         char str[32];
2824         sprintf(str, "%ld", timeout);
2825         SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
2826     }
2827 
2828     redis_request(redis, argc, argv, argvlen, return_value);
2829     SW_REDIS_COMMAND_FREE_ARGV
2830 }
2831 
PHP_METHOD(swoole_redis_coro,blPop)2832 static PHP_METHOD(swoole_redis_coro, blPop) {
2833     int argc = ZEND_NUM_ARGS();
2834     SW_REDIS_COMMAND_CHECK
2835     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
2836     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc < 1) {
2837         efree(z_args);
2838         return;
2839     }
2840 
2841     zend_bool single_array = 0;
2842     if (argc == 2 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY) {
2843         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0])) + 2;
2844         single_array = 1;
2845     } else {
2846         argc += 1;
2847     }
2848     int i = 0;
2849     SW_REDIS_COMMAND_ALLOC_ARGV
2850     SW_REDIS_COMMAND_ARGV_FILL("BLPOP", 5)
2851     if (single_array) {
2852         zval *value;
2853         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
2854         zend_string *convert_str = zval_get_string(value);
2855         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2856         zend_string_release(convert_str);
2857         SW_HASHTABLE_FOREACH_END();
2858         zend_string *convert_str = zval_get_string(&z_args[1]);
2859         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2860         zend_string_release(convert_str);
2861     } else {
2862         int j;
2863         for (j = 0; j < argc - 1; ++j) {
2864             zend_string *convert_str = zval_get_string(&z_args[j]);
2865             SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2866             zend_string_release(convert_str);
2867         }
2868     }
2869     efree(z_args);
2870 
2871     redis_request(redis, argc, argv, argvlen, return_value);
2872     SW_REDIS_COMMAND_FREE_ARGV
2873 }
2874 
PHP_METHOD(swoole_redis_coro,brPop)2875 static PHP_METHOD(swoole_redis_coro, brPop) {
2876     int argc = ZEND_NUM_ARGS();
2877     SW_REDIS_COMMAND_CHECK
2878     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
2879     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc < 1) {
2880         efree(z_args);
2881         return;
2882     }
2883 
2884     zend_bool single_array = 0;
2885     if (argc == 2 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY) {
2886         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0])) + 2;
2887         single_array = 1;
2888     } else {
2889         argc += 1;
2890     }
2891     int i = 0;
2892     SW_REDIS_COMMAND_ALLOC_ARGV
2893     SW_REDIS_COMMAND_ARGV_FILL("BRPOP", 5)
2894     if (single_array) {
2895         zval *value;
2896         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
2897         zend_string *convert_str = zval_get_string(value);
2898         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2899         zend_string_release(convert_str);
2900         SW_HASHTABLE_FOREACH_END();
2901         zend_string *convert_str = zval_get_string(&z_args[1]);
2902         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2903         zend_string_release(convert_str);
2904     } else {
2905         int j;
2906         for (j = 0; j < argc - 1; ++j) {
2907             zend_string *convert_str = zval_get_string(&z_args[j]);
2908             SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
2909             zend_string_release(convert_str);
2910         }
2911     }
2912     efree(z_args);
2913 
2914     redis_request(redis, argc, argv, argvlen, return_value);
2915     SW_REDIS_COMMAND_FREE_ARGV
2916 }
2917 
PHP_METHOD(swoole_redis_coro,rPop)2918 static PHP_METHOD(swoole_redis_coro, rPop) {
2919     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RPOP"));
2920 }
2921 
PHP_METHOD(swoole_redis_coro,lSize)2922 static PHP_METHOD(swoole_redis_coro, lSize) {
2923     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LLEN"));
2924 }
2925 
PHP_METHOD(swoole_redis_coro,sSize)2926 static PHP_METHOD(swoole_redis_coro, sSize) {
2927     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SCARD"));
2928 }
2929 
PHP_METHOD(swoole_redis_coro,sPop)2930 static PHP_METHOD(swoole_redis_coro, sPop) {
2931     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SPOP"));
2932 }
2933 
PHP_METHOD(swoole_redis_coro,sMembers)2934 static PHP_METHOD(swoole_redis_coro, sMembers) {
2935     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SMEMBERS"));
2936 }
2937 
PHP_METHOD(swoole_redis_coro,sRandMember)2938 static PHP_METHOD(swoole_redis_coro, sRandMember) {
2939     char *key;
2940     size_t key_len;
2941     zend_long count = 0;
2942 
2943     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &key, &key_len, &count) == FAILURE) {
2944         RETURN_FALSE;
2945     }
2946     SW_REDIS_COMMAND_CHECK
2947 
2948     int i = 0, argc, buf_len;
2949     char buf[32];
2950     argc = ZEND_NUM_ARGS() == 2 ? 3 : 2;
2951     SW_REDIS_COMMAND_ALLOC_ARGV
2952     SW_REDIS_COMMAND_ARGV_FILL("SRANDMEMBER", 11);
2953     SW_REDIS_COMMAND_ARGV_FILL(key, key_len);
2954     if (argc == 3) {
2955         buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", count);
2956         SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len);
2957     }
2958     redis_request(redis, argc, argv, argvlen, return_value);
2959     SW_REDIS_COMMAND_FREE_ARGV
2960 }
2961 
PHP_METHOD(swoole_redis_coro,persist)2962 static PHP_METHOD(swoole_redis_coro, persist) {
2963     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PERSIST"));
2964 }
2965 
PHP_METHOD(swoole_redis_coro,ttl)2966 static PHP_METHOD(swoole_redis_coro, ttl) {
2967     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("TTL"));
2968 }
2969 
PHP_METHOD(swoole_redis_coro,pttl)2970 static PHP_METHOD(swoole_redis_coro, pttl) {
2971     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PTTL"));
2972 }
2973 
PHP_METHOD(swoole_redis_coro,zCard)2974 static PHP_METHOD(swoole_redis_coro, zCard) {
2975     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZCARD"));
2976 }
2977 
PHP_METHOD(swoole_redis_coro,hLen)2978 static PHP_METHOD(swoole_redis_coro, hLen) {
2979     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HLEN"));
2980 }
2981 
PHP_METHOD(swoole_redis_coro,hKeys)2982 static PHP_METHOD(swoole_redis_coro, hKeys) {
2983     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HKEYS"));
2984 }
2985 
PHP_METHOD(swoole_redis_coro,hVals)2986 static PHP_METHOD(swoole_redis_coro, hVals) {
2987     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HVALS"));
2988 }
2989 
PHP_METHOD(swoole_redis_coro,hGetAll)2990 static PHP_METHOD(swoole_redis_coro, hGetAll) {
2991     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HGETALL"));
2992 }
2993 
PHP_METHOD(swoole_redis_coro,renameKey)2994 static PHP_METHOD(swoole_redis_coro, renameKey) {
2995     sw_redis_command_key_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RENAME"));
2996 }
2997 
PHP_METHOD(swoole_redis_coro,renameNx)2998 static PHP_METHOD(swoole_redis_coro, renameNx) {
2999     sw_redis_command_key_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RENAMENX"));
3000 }
3001 
PHP_METHOD(swoole_redis_coro,rpoplpush)3002 static PHP_METHOD(swoole_redis_coro, rpoplpush) {
3003     sw_redis_command_key_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RPOPLPUSH"));
3004 }
3005 
PHP_METHOD(swoole_redis_coro,randomKey)3006 static PHP_METHOD(swoole_redis_coro, randomKey) {
3007     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RANDOMKEY"));
3008 }
3009 
PHP_METHOD(swoole_redis_coro,unwatch)3010 static PHP_METHOD(swoole_redis_coro, unwatch) {
3011     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("UNWATCH"));
3012 }
3013 
PHP_METHOD(swoole_redis_coro,pfadd)3014 static PHP_METHOD(swoole_redis_coro, pfadd) {
3015     char *key;
3016     size_t key_len, argc;
3017     zval *z_arr;
3018 
3019     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &key, &key_len, &z_arr) == FAILURE) {
3020         return;
3021     }
3022     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_arr))) == 0) {
3023         RETURN_FALSE;
3024     }
3025     SW_REDIS_COMMAND_CHECK
3026     int i = 0;
3027     argc = argc + 2;
3028     zval *value;
3029     SW_REDIS_COMMAND_ALLOC_ARGV
3030     SW_REDIS_COMMAND_ARGV_FILL("PFADD", 5)
3031     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3032     SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(z_arr), value) {
3033         zend_string *convert_str = zval_get_string(value);
3034         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str));
3035         zend_string_release(convert_str);
3036     }
3037     SW_HASHTABLE_FOREACH_END()
3038 
3039     redis_request(redis, argc, argv, argvlen, return_value);
3040     SW_REDIS_COMMAND_FREE_ARGV
3041 }
3042 
PHP_METHOD(swoole_redis_coro,pfcount)3043 static PHP_METHOD(swoole_redis_coro, pfcount) {
3044     int argc = ZEND_NUM_ARGS();
3045     SW_REDIS_COMMAND_CHECK
3046     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
3047     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc != 1) {
3048         efree(z_args);
3049         RETURN_FALSE;
3050     }
3051 
3052     zend_bool single_array = 0;
3053     if (SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY) {
3054         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]));
3055         single_array = 1;
3056     }
3057 
3058     argc += 1;
3059     int i = 0;
3060     SW_REDIS_COMMAND_ALLOC_ARGV
3061     SW_REDIS_COMMAND_ARGV_FILL("PFCOUNT", 7)
3062     if (single_array) {
3063         zval *value;
3064         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
3065         zend_string *convert_str = zval_get_string(value);
3066         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3067         zend_string_release(convert_str);
3068         SW_HASHTABLE_FOREACH_END()
3069     } else {
3070         zend_string *convert_str = zval_get_string(&z_args[0]);
3071         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3072         zend_string_release(convert_str);
3073     }
3074     efree(z_args);
3075 
3076     redis_request(redis, argc, argv, argvlen, return_value);
3077     SW_REDIS_COMMAND_FREE_ARGV
3078 }
3079 
PHP_METHOD(swoole_redis_coro,pfmerge)3080 static PHP_METHOD(swoole_redis_coro, pfmerge) {
3081     char *key;
3082     size_t key_len, argc;
3083     zval *z_arr;
3084 
3085     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &key, &key_len, &z_arr) == FAILURE) {
3086         RETURN_FALSE;
3087     }
3088     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_arr))) == 0) {
3089         RETURN_FALSE;
3090     }
3091     SW_REDIS_COMMAND_CHECK
3092     int i = 0;
3093     argc = argc + 2;
3094     zval *value;
3095     SW_REDIS_COMMAND_ALLOC_ARGV
3096     SW_REDIS_COMMAND_ARGV_FILL("PFMERGE", 7)
3097     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3098     SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(z_arr), value) {
3099         zend_string *convert_str = zval_get_string(value);
3100         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str));
3101         zend_string_release(convert_str);
3102     }
3103     SW_HASHTABLE_FOREACH_END()
3104 
3105     redis_request(redis, argc, argv, argvlen, return_value);
3106     SW_REDIS_COMMAND_FREE_ARGV
3107 }
3108 
PHP_METHOD(swoole_redis_coro,ping)3109 static PHP_METHOD(swoole_redis_coro, ping) {
3110     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PING"));
3111 }
3112 
PHP_METHOD(swoole_redis_coro,auth)3113 static PHP_METHOD(swoole_redis_coro, auth) {
3114     char *pw;
3115     size_t pw_len;
3116     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &pw, &pw_len) == FAILURE) {
3117         RETURN_FALSE;
3118     }
3119 
3120     SW_REDIS_COMMAND_CHECK
3121     zval *zsetting = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0);
3122     add_assoc_stringl(zsetting, "password", pw, pw_len);
3123     RETURN_BOOL(redis_auth(redis, pw, pw_len));
3124 }
3125 
PHP_METHOD(swoole_redis_coro,save)3126 static PHP_METHOD(swoole_redis_coro, save) {
3127     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SAVE"));
3128 }
3129 
PHP_METHOD(swoole_redis_coro,bgSave)3130 static PHP_METHOD(swoole_redis_coro, bgSave) {
3131     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("BGSAVE"));
3132 }
3133 
PHP_METHOD(swoole_redis_coro,lastSave)3134 static PHP_METHOD(swoole_redis_coro, lastSave) {
3135     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LASTSAVE"));
3136 }
3137 
PHP_METHOD(swoole_redis_coro,flushDB)3138 static PHP_METHOD(swoole_redis_coro, flushDB) {
3139     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("FLUSHDB"));
3140 }
3141 
PHP_METHOD(swoole_redis_coro,flushAll)3142 static PHP_METHOD(swoole_redis_coro, flushAll) {
3143     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("FLUSHALL"));
3144 }
3145 
PHP_METHOD(swoole_redis_coro,dbSize)3146 static PHP_METHOD(swoole_redis_coro, dbSize) {
3147     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DBSIZE"));
3148 }
3149 
PHP_METHOD(swoole_redis_coro,bgrewriteaof)3150 static PHP_METHOD(swoole_redis_coro, bgrewriteaof) {
3151     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("BGREWRITEAOF"));
3152 }
3153 
PHP_METHOD(swoole_redis_coro,time)3154 static PHP_METHOD(swoole_redis_coro, time) {
3155     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("TIME"));
3156 }
3157 
PHP_METHOD(swoole_redis_coro,role)3158 static PHP_METHOD(swoole_redis_coro, role) {
3159     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ROLE"));
3160 }
3161 
PHP_METHOD(swoole_redis_coro,setRange)3162 static PHP_METHOD(swoole_redis_coro, setRange) {
3163     sw_redis_command_key_long_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SETRANGE"));
3164 }
3165 
PHP_METHOD(swoole_redis_coro,setNx)3166 static PHP_METHOD(swoole_redis_coro, setNx) {
3167     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SETNX"));
3168 }
3169 
PHP_METHOD(swoole_redis_coro,getSet)3170 static PHP_METHOD(swoole_redis_coro, getSet) {
3171     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("GETSET"));
3172 }
3173 
PHP_METHOD(swoole_redis_coro,append)3174 static PHP_METHOD(swoole_redis_coro, append) {
3175     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("APPEND"));
3176 }
3177 
PHP_METHOD(swoole_redis_coro,lPushx)3178 static PHP_METHOD(swoole_redis_coro, lPushx) {
3179     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LPUSHX"));
3180 }
3181 
PHP_METHOD(swoole_redis_coro,lPush)3182 static PHP_METHOD(swoole_redis_coro, lPush) {
3183     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LPUSH"));
3184 }
3185 
PHP_METHOD(swoole_redis_coro,rPush)3186 static PHP_METHOD(swoole_redis_coro, rPush) {
3187     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RPUSH"));
3188 }
3189 
PHP_METHOD(swoole_redis_coro,rPushx)3190 static PHP_METHOD(swoole_redis_coro, rPushx) {
3191     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("RPUSHX"));
3192 }
3193 
PHP_METHOD(swoole_redis_coro,sContains)3194 static PHP_METHOD(swoole_redis_coro, sContains) {
3195     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SISMEMBER"));
3196 }
3197 
PHP_METHOD(swoole_redis_coro,zRange)3198 static PHP_METHOD(swoole_redis_coro, zRange) {
3199     char *key;
3200     size_t key_len;
3201     zend_long start, end;
3202     zend_bool ws = 0;
3203 
3204     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|b", &key, &key_len, &start, &end, &ws) == FAILURE) {
3205         RETURN_FALSE;
3206     }
3207     SW_REDIS_COMMAND_CHECK
3208 
3209     int i = 0, argc;
3210     argc = ZEND_NUM_ARGS() + 1;
3211     SW_REDIS_COMMAND_ALLOC_ARGV
3212     SW_REDIS_COMMAND_ARGV_FILL("ZRANGE", 6)
3213     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3214     char buf[32];
3215     size_t buf_len;
3216     buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", start);
3217     SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
3218     buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", end);
3219     SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
3220     if (ws) {
3221         SW_REDIS_COMMAND_ARGV_FILL("WITHSCORES", 10)
3222     } else {
3223         argc = 4;
3224     }
3225 
3226     redis_request(redis, argc, argv, argvlen, return_value);
3227 
3228     if (ws && redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
3229         swoole_redis_handle_assoc_array_result(return_value, true);
3230     }
3231 
3232     SW_REDIS_COMMAND_FREE_ARGV
3233 }
3234 
PHP_METHOD(swoole_redis_coro,zRevRange)3235 static PHP_METHOD(swoole_redis_coro, zRevRange) {
3236     char *key;
3237     size_t key_len;
3238     zend_long start, end;
3239     zend_bool ws = 0;
3240 
3241     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|b", &key, &key_len, &start, &end, &ws) == FAILURE) {
3242         RETURN_FALSE;
3243     }
3244     SW_REDIS_COMMAND_CHECK
3245 
3246     int i = 0, argc;
3247     argc = ZEND_NUM_ARGS() + 1;
3248     SW_REDIS_COMMAND_ALLOC_ARGV
3249     SW_REDIS_COMMAND_ARGV_FILL("ZREVRANGE", 9)
3250     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3251     char buf[32];
3252     size_t buf_len;
3253     buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", start);
3254     SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
3255     buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", end);
3256     SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
3257     if (ws) {
3258         SW_REDIS_COMMAND_ARGV_FILL("WITHSCORES", 10)
3259     } else {
3260         argc = 4;
3261     }
3262 
3263     redis_request(redis, argc, argv, argvlen, return_value);
3264 
3265     if (ws && redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
3266         swoole_redis_handle_assoc_array_result(return_value, true);
3267     }
3268 
3269     SW_REDIS_COMMAND_FREE_ARGV
3270 }
3271 
PHP_METHOD(swoole_redis_coro,zUnion)3272 static PHP_METHOD(swoole_redis_coro, zUnion) {
3273     char *key, *agg_op;
3274     size_t key_len;
3275     zval *z_keys, *z_weights = nullptr;
3276     HashTable *ht_keys, *ht_weights = nullptr;
3277     size_t argc = 2, agg_op_len = 0, keys_count;
3278 
3279     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|a!s", &key, &key_len, &z_keys, &z_weights, &agg_op, &agg_op_len) ==
3280         FAILURE) {
3281         RETURN_FALSE;
3282     }
3283 
3284     ht_keys = Z_ARRVAL_P(z_keys);
3285 
3286     if ((keys_count = zend_hash_num_elements(ht_keys)) == 0) {
3287         RETURN_FALSE;
3288     } else {
3289         argc += keys_count + 1;
3290     }
3291 
3292     if (z_weights != nullptr) {
3293         ht_weights = Z_ARRVAL_P(z_weights);
3294         if (zend_hash_num_elements(ht_weights) != keys_count) {
3295             zend_update_property_long(
3296                 swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3297             zend_update_property_long(swoole_redis_coro_ce,
3298                                       SW_Z8_OBJ_P(ZEND_THIS),
3299                                       ZEND_STRL("errCode"),
3300                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3301             zend_update_property_string(swoole_redis_coro_ce,
3302                                         SW_Z8_OBJ_P(ZEND_THIS),
3303                                         ZEND_STRL("errMsg"),
3304                                         "WEIGHTS and keys array should be the same size!");
3305             RETURN_FALSE;
3306         }
3307         argc += keys_count + 1;
3308     }
3309 
3310     // AGGREGATE option
3311     if (agg_op_len != 0) {
3312         if (strncasecmp(agg_op, "SUM", sizeof("SUM")) && strncasecmp(agg_op, "MIN", sizeof("MIN")) &&
3313             strncasecmp(agg_op, "MAX", sizeof("MAX"))) {
3314             zend_update_property_long(
3315                 swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3316             zend_update_property_long(swoole_redis_coro_ce,
3317                                       SW_Z8_OBJ_P(ZEND_THIS),
3318                                       ZEND_STRL("errCode"),
3319                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3320             zend_update_property_string(swoole_redis_coro_ce,
3321                                         SW_Z8_OBJ_P(ZEND_THIS),
3322                                         ZEND_STRL("errMsg"),
3323                                         "Invalid AGGREGATE option provided!");
3324             RETURN_FALSE;
3325         }
3326 
3327         // "AGGREGATE" + type
3328         argc += 2;
3329     }
3330     SW_REDIS_COMMAND_CHECK
3331 
3332     int i = 0, j;
3333     SW_REDIS_COMMAND_ALLOC_ARGV
3334     SW_REDIS_COMMAND_ARGV_FILL("ZUNIONSTORE", 11)
3335     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3336     char buf[32];
3337     size_t buf_len;
3338     buf_len = sprintf(buf, "%zu", keys_count);
3339     SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3340 
3341     // Process input keys
3342     zval *value;
3343     SW_HASHTABLE_FOREACH_START(ht_keys, value)
3344     zend_string *convert_str = zval_get_string(value);
3345     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3346     zend_string_release(convert_str);
3347     SW_HASHTABLE_FOREACH_END();
3348 
3349     // Weights
3350     if (ht_weights != nullptr) {
3351         SW_REDIS_COMMAND_ARGV_FILL("WEIGHTS", 7)
3352 
3353         SW_HASHTABLE_FOREACH_START(ht_weights, value)
3354         if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_DOUBLE &&
3355             strncasecmp(Z_STRVAL_P(value), "inf", sizeof("inf")) != 0 &&
3356             strncasecmp(Z_STRVAL_P(value), "-inf", sizeof("-inf")) != 0 &&
3357             strncasecmp(Z_STRVAL_P(value), "+inf", sizeof("+inf")) != 0) {
3358             zend_update_property_long(
3359                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3360             zend_update_property_long(swoole_redis_coro_ce,
3361                                       SW_Z8_OBJ_P(redis->zobject),
3362                                       ZEND_STRL("errCode"),
3363                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3364             zend_update_property_string(swoole_redis_coro_ce,
3365                                         SW_Z8_OBJ_P(redis->zobject),
3366                                         ZEND_STRL("errMsg"),
3367                                         "Weights must be numeric or '-inf','inf','+inf'");
3368             for (j = 0; j < i; j++) {
3369                 efree((void *) argv[j]);
3370             }
3371             SW_REDIS_COMMAND_FREE_ARGV
3372             RETURN_FALSE;
3373         }
3374         switch (Z_TYPE_P(value)) {
3375         case IS_LONG:
3376             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(value));
3377             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3378             break;
3379         case IS_DOUBLE:
3380             buf_len = sprintf(buf, "%f", Z_DVAL_P(value));
3381             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3382             break;
3383         case IS_STRING:
3384             SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(value), Z_STRLEN_P(value))
3385             break;
3386         }
3387         SW_HASHTABLE_FOREACH_END();
3388     }
3389 
3390     // AGGREGATE
3391     if (agg_op_len != 0) {
3392         SW_REDIS_COMMAND_ARGV_FILL("AGGREGATE", 9)
3393         SW_REDIS_COMMAND_ARGV_FILL(agg_op, agg_op_len)
3394     }
3395 
3396     redis_request(redis, argc, argv, argvlen, return_value);
3397     SW_REDIS_COMMAND_FREE_ARGV
3398 }
3399 
PHP_METHOD(swoole_redis_coro,zInter)3400 static PHP_METHOD(swoole_redis_coro, zInter) {
3401     char *key, *agg_op;
3402     size_t key_len;
3403     zval *z_keys, *z_weights = nullptr;
3404     HashTable *ht_keys, *ht_weights = nullptr;
3405     size_t argc = 2, agg_op_len = 0, keys_count;
3406 
3407     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|a!s", &key, &key_len, &z_keys, &z_weights, &agg_op, &agg_op_len) ==
3408         FAILURE) {
3409         RETURN_FALSE;
3410     }
3411 
3412     ht_keys = Z_ARRVAL_P(z_keys);
3413 
3414     if ((keys_count = zend_hash_num_elements(ht_keys)) == 0) {
3415         RETURN_FALSE;
3416     } else {
3417         argc += keys_count + 1;
3418     }
3419 
3420     if (z_weights != nullptr) {
3421         ht_weights = Z_ARRVAL_P(z_weights);
3422         if (zend_hash_num_elements(ht_weights) != keys_count) {
3423             zend_update_property_long(
3424                 swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3425             zend_update_property_long(swoole_redis_coro_ce,
3426                                       SW_Z8_OBJ_P(ZEND_THIS),
3427                                       ZEND_STRL("errCode"),
3428                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3429             zend_update_property_string(swoole_redis_coro_ce,
3430                                         SW_Z8_OBJ_P(ZEND_THIS),
3431                                         ZEND_STRL("errMsg"),
3432                                         "WEIGHTS and keys array should be the same size!");
3433             RETURN_FALSE;
3434         }
3435 
3436         argc += keys_count + 1;
3437     }
3438 
3439     // AGGREGATE option
3440     if (agg_op_len != 0) {
3441         if (strncasecmp(agg_op, "SUM", sizeof("SUM")) && strncasecmp(agg_op, "MIN", sizeof("MIN")) &&
3442             strncasecmp(agg_op, "MAX", sizeof("MAX"))) {
3443             zend_update_property_long(
3444                 swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3445             zend_update_property_long(swoole_redis_coro_ce,
3446                                       SW_Z8_OBJ_P(ZEND_THIS),
3447                                       ZEND_STRL("errCode"),
3448                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3449             zend_update_property_string(swoole_redis_coro_ce,
3450                                         SW_Z8_OBJ_P(ZEND_THIS),
3451                                         ZEND_STRL("errMsg"),
3452                                         "Invalid AGGREGATE option provided!");
3453             RETURN_FALSE;
3454         }
3455 
3456         // "AGGREGATE" + type
3457         argc += 2;
3458     }
3459     SW_REDIS_COMMAND_CHECK
3460 
3461     int i = 0, j;
3462     SW_REDIS_COMMAND_ALLOC_ARGV
3463     SW_REDIS_COMMAND_ARGV_FILL("ZINTERSTORE", 11)
3464     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3465     char buf[32];
3466     size_t buf_len;
3467     buf_len = sprintf(buf, "%zu", keys_count);
3468     SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3469 
3470     // Process input keys
3471     zval *value;
3472     SW_HASHTABLE_FOREACH_START(ht_keys, value)
3473     zend_string *convert_str = zval_get_string(value);
3474     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3475     zend_string_release(convert_str);
3476     SW_HASHTABLE_FOREACH_END();
3477 
3478     // Weights
3479     if (ht_weights != nullptr) {
3480         SW_REDIS_COMMAND_ARGV_FILL("WEIGHTS", 7)
3481 
3482         SW_HASHTABLE_FOREACH_START(ht_weights, value)
3483         if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_DOUBLE &&
3484             strncasecmp(Z_STRVAL_P(value), "inf", sizeof("inf")) != 0 &&
3485             strncasecmp(Z_STRVAL_P(value), "-inf", sizeof("-inf")) != 0 &&
3486             strncasecmp(Z_STRVAL_P(value), "+inf", sizeof("+inf")) != 0) {
3487             zend_update_property_long(
3488                 swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3489             zend_update_property_long(swoole_redis_coro_ce,
3490                                       SW_Z8_OBJ_P(ZEND_THIS),
3491                                       ZEND_STRL("errCode"),
3492                                       sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3493             zend_update_property_string(swoole_redis_coro_ce,
3494                                         SW_Z8_OBJ_P(ZEND_THIS),
3495                                         ZEND_STRL("errMsg"),
3496                                         "Weights must be numeric or '-inf','inf','+inf'");
3497             for (j = 0; j < i; j++) {
3498                 efree((void *) argv[j]);
3499             }
3500             SW_REDIS_COMMAND_FREE_ARGV
3501             RETURN_FALSE;
3502         }
3503         switch (Z_TYPE_P(value)) {
3504         case IS_LONG:
3505             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(value));
3506             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3507             break;
3508         case IS_DOUBLE:
3509             buf_len = sprintf(buf, "%f", Z_DVAL_P(value));
3510             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3511             break;
3512         case IS_STRING:
3513             SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(value), Z_STRLEN_P(value))
3514             break;
3515         }
3516         SW_HASHTABLE_FOREACH_END();
3517     }
3518 
3519     // AGGREGATE
3520     if (agg_op_len != 0) {
3521         SW_REDIS_COMMAND_ARGV_FILL("AGGREGATE", 9)
3522         SW_REDIS_COMMAND_ARGV_FILL(agg_op, agg_op_len)
3523     }
3524 
3525     redis_request(redis, argc, argv, argvlen, return_value);
3526     SW_REDIS_COMMAND_FREE_ARGV
3527 }
3528 
PHP_METHOD(swoole_redis_coro,zRangeByLex)3529 static PHP_METHOD(swoole_redis_coro, zRangeByLex) {
3530     char *key, *min, *max;
3531     size_t key_len, min_len, max_len;
3532     zend_long offset = 0, count = 0;
3533     size_t argc = ZEND_NUM_ARGS();
3534 
3535     /* We need either 3 or 5 arguments for this to be valid */
3536     if (argc != 3 && argc != 5) {
3537         zend_update_property_long(
3538             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3539         zend_update_property_long(swoole_redis_coro_ce,
3540                                   SW_Z8_OBJ_P(ZEND_THIS),
3541                                   ZEND_STRL("errCode"),
3542                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3543         zend_update_property_string(
3544             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errMsg"), "Must pass either 3 or 5 arguments");
3545         RETURN_FALSE;
3546     }
3547 
3548     if (zend_parse_parameters(argc, "sss|ll", &key, &key_len, &min, &min_len, &max, &max_len, &offset, &count) ==
3549         FAILURE) {
3550         RETURN_FALSE;
3551     }
3552 
3553     /* min and max must start with '(' or '[', or be either '-' or '+' */
3554     if (min_len < 1 || max_len < 1 ||
3555         (min[0] != '(' && min[0] != '[' && (min[0] != '-' || min_len > 1) && (min[0] != '+' || min_len > 1)) ||
3556         (max[0] != '(' && max[0] != '[' && (max[0] != '-' || max_len > 1) && (max[0] != '+' || max_len > 1))) {
3557         zend_update_property_long(
3558             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3559         zend_update_property_long(swoole_redis_coro_ce,
3560                                   SW_Z8_OBJ_P(ZEND_THIS),
3561                                   ZEND_STRL("errCode"),
3562                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3563         zend_update_property_string(swoole_redis_coro_ce,
3564                                     SW_Z8_OBJ_P(ZEND_THIS),
3565                                     ZEND_STRL("errMsg"),
3566                                     "min and max arguments must start with '[' or '('");
3567         RETURN_FALSE;
3568     }
3569     SW_REDIS_COMMAND_CHECK
3570 
3571     argc = argc == 3 ? 4 : 7;
3572     int i = 0;
3573     SW_REDIS_COMMAND_ALLOC_ARGV
3574     SW_REDIS_COMMAND_ARGV_FILL("ZRANGEBYLEX", 11)
3575     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3576     SW_REDIS_COMMAND_ARGV_FILL(min, min_len)
3577     SW_REDIS_COMMAND_ARGV_FILL(max, max_len)
3578     if (argc == 7) {
3579         SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
3580         char buf[32];
3581         size_t buf_len;
3582         buf_len = sprintf(buf, ZEND_LONG_FMT, offset);
3583         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3584         buf_len = sprintf(buf, ZEND_LONG_FMT, count);
3585         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3586     }
3587 
3588     redis_request(redis, argc, argv, argvlen, return_value);
3589     SW_REDIS_COMMAND_FREE_ARGV
3590 }
3591 
PHP_METHOD(swoole_redis_coro,zRevRangeByLex)3592 static PHP_METHOD(swoole_redis_coro, zRevRangeByLex) {
3593     char *key, *min, *max;
3594     size_t key_len, min_len, max_len;
3595     zend_long offset = 0, count = 0;
3596     int argc = ZEND_NUM_ARGS();
3597 
3598     /* We need either 3 or 5 arguments for this to be valid */
3599     if (argc != 3 && argc != 5) {
3600         zend_update_property_long(
3601             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3602         zend_update_property_long(swoole_redis_coro_ce,
3603                                   SW_Z8_OBJ_P(ZEND_THIS),
3604                                   ZEND_STRL("errCode"),
3605                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3606         zend_update_property_string(
3607             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errMsg"), "Must pass either 3 or 5 arguments");
3608         RETURN_FALSE;
3609     }
3610 
3611     if (zend_parse_parameters(argc, "sss|ll", &key, &key_len, &min, &min_len, &max, &max_len, &offset, &count) ==
3612         FAILURE) {
3613         RETURN_FALSE;
3614     }
3615 
3616     /* min and max must start with '(' or '[', or be either '-' or '+' */
3617     if (min_len < 1 || max_len < 1 ||
3618         (min[0] != '(' && min[0] != '[' && (min[0] != '-' || min_len > 1) && (min[0] != '+' || min_len > 1)) ||
3619         (max[0] != '(' && max[0] != '[' && (max[0] != '-' || max_len > 1) && (max[0] != '+' || max_len > 1))) {
3620         zend_update_property_long(
3621             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
3622         zend_update_property_long(swoole_redis_coro_ce,
3623                                   SW_Z8_OBJ_P(ZEND_THIS),
3624                                   ZEND_STRL("errCode"),
3625                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
3626         zend_update_property_string(swoole_redis_coro_ce,
3627                                     SW_Z8_OBJ_P(ZEND_THIS),
3628                                     ZEND_STRL("errMsg"),
3629                                     "min and max arguments must start with '[' or '('");
3630         RETURN_FALSE;
3631     }
3632     SW_REDIS_COMMAND_CHECK
3633 
3634     argc = argc == 3 ? 4 : 7;
3635     int i = 0;
3636     SW_REDIS_COMMAND_ALLOC_ARGV
3637     SW_REDIS_COMMAND_ARGV_FILL("ZREVRANGEBYLEX", 14)
3638     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3639     SW_REDIS_COMMAND_ARGV_FILL(min, min_len)
3640     SW_REDIS_COMMAND_ARGV_FILL(max, max_len)
3641     if (argc == 7) {
3642         SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
3643         char buf[32];
3644         size_t buf_len;
3645         buf_len = sprintf(buf, ZEND_LONG_FMT, offset);
3646         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3647         buf_len = sprintf(buf, ZEND_LONG_FMT, count);
3648         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3649     }
3650 
3651     redis_request(redis, argc, argv, argvlen, return_value);
3652     SW_REDIS_COMMAND_FREE_ARGV
3653 }
3654 
PHP_METHOD(swoole_redis_coro,zRangeByScore)3655 static PHP_METHOD(swoole_redis_coro, zRangeByScore) {
3656     char *key;
3657     size_t key_len;
3658     char *start, *end;
3659     size_t start_len, end_len;
3660     long limit_low, limit_high;
3661     zval *z_opt = nullptr, *z_ele;
3662     zend_bool withscores = 0, has_limit = 0;
3663     HashTable *ht_opt;
3664 
3665     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|a", &key, &key_len, &start, &start_len, &end, &end_len, &z_opt) ==
3666         FAILURE) {
3667         RETURN_FALSE;
3668     }
3669     SW_REDIS_COMMAND_CHECK
3670 
3671     int argc = 4, i = 0;
3672     // Check for an options array
3673     if (z_opt && ZVAL_IS_ARRAY(z_opt)) {
3674         ht_opt = Z_ARRVAL_P(z_opt);
3675 
3676         // Check for WITHSCORES
3677         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("withscores"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
3678             withscores = 1;
3679             argc++;
3680         }
3681 
3682         // LIMIT
3683         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit")))) {
3684             HashTable *ht_limit = Z_ARRVAL_P(z_ele);
3685             zval *z_off, *z_cnt;
3686             z_off = zend_hash_index_find(ht_limit, 0);
3687             z_cnt = zend_hash_index_find(ht_limit, 1);
3688             if (z_off && z_cnt && Z_TYPE_P(z_off) == IS_LONG && Z_TYPE_P(z_cnt) == IS_LONG) {
3689                 has_limit = 1;
3690                 limit_low = Z_LVAL_P(z_off);
3691                 limit_high = Z_LVAL_P(z_cnt);
3692                 argc += 3;
3693             }
3694         }
3695     }
3696     SW_REDIS_COMMAND_ALLOC_ARGV
3697     SW_REDIS_COMMAND_ARGV_FILL("ZRANGEBYSCORE", 13)
3698     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3699     SW_REDIS_COMMAND_ARGV_FILL(start, start_len)
3700     SW_REDIS_COMMAND_ARGV_FILL(end, end_len)
3701 
3702     if (withscores) {
3703         SW_REDIS_COMMAND_ARGV_FILL("WITHSCORES", 10)
3704     }
3705     if (has_limit) {
3706         SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
3707         char buf[32];
3708         size_t buf_len;
3709         buf_len = sprintf(buf, "%ld", limit_low);
3710         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3711         buf_len = sprintf(buf, "%ld", limit_high);
3712         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3713     }
3714 
3715     redis_request(redis, argc, argv, argvlen, return_value);
3716 
3717     if (withscores && redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
3718         swoole_redis_handle_assoc_array_result(return_value, true);
3719     }
3720 
3721     SW_REDIS_COMMAND_FREE_ARGV
3722 }
3723 
PHP_METHOD(swoole_redis_coro,zRevRangeByScore)3724 static PHP_METHOD(swoole_redis_coro, zRevRangeByScore) {
3725     char *key;
3726     size_t key_len;
3727     char *start, *end;
3728     size_t start_len, end_len;
3729     long limit_low, limit_high;
3730     zval *z_opt = nullptr, *z_ele;
3731     zend_bool withscores = 0, has_limit = 0;
3732     HashTable *ht_opt;
3733 
3734     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|a", &key, &key_len, &start, &start_len, &end, &end_len, &z_opt) ==
3735         FAILURE) {
3736         RETURN_FALSE;
3737     }
3738     SW_REDIS_COMMAND_CHECK
3739 
3740     int argc = 4, i = 0;
3741     // Check for an options array
3742     if (z_opt && ZVAL_IS_ARRAY(z_opt)) {
3743         ht_opt = Z_ARRVAL_P(z_opt);
3744 
3745         // Check for WITHSCORES
3746         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("withscores"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
3747             withscores = 1;
3748             argc++;
3749         }
3750 
3751         // LIMIT
3752         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit")))) {
3753             HashTable *ht_limit = Z_ARRVAL_P(z_ele);
3754             zval *z_off, *z_cnt;
3755             z_off = zend_hash_index_find(ht_limit, 0);
3756             z_cnt = zend_hash_index_find(ht_limit, 1);
3757             if (z_off && z_cnt && Z_TYPE_P(z_off) == IS_LONG && Z_TYPE_P(z_cnt) == IS_LONG) {
3758                 has_limit = 1;
3759                 limit_low = Z_LVAL_P(z_off);
3760                 limit_high = Z_LVAL_P(z_cnt);
3761                 argc += 3;
3762             }
3763         }
3764     }
3765     SW_REDIS_COMMAND_ALLOC_ARGV
3766     SW_REDIS_COMMAND_ARGV_FILL("ZREVRANGEBYSCORE", 16)
3767     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3768     SW_REDIS_COMMAND_ARGV_FILL(start, start_len)
3769     SW_REDIS_COMMAND_ARGV_FILL(end, end_len)
3770 
3771     if (withscores) {
3772         SW_REDIS_COMMAND_ARGV_FILL("WITHSCORES", 10)
3773     }
3774     if (has_limit) {
3775         SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
3776         char buf[32];
3777         size_t buf_len;
3778         buf_len = sprintf(buf, "%ld", limit_low);
3779         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3780         buf_len = sprintf(buf, "%ld", limit_high);
3781         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3782     }
3783 
3784     redis_request(redis, argc, argv, argvlen, return_value);
3785 
3786     if (withscores && redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
3787         swoole_redis_handle_assoc_array_result(return_value, true);
3788     }
3789 
3790     SW_REDIS_COMMAND_FREE_ARGV
3791 }
3792 
PHP_METHOD(swoole_redis_coro,zIncrBy)3793 static PHP_METHOD(swoole_redis_coro, zIncrBy) {
3794     char *key;
3795     size_t key_len;
3796     double incrby;
3797     zval *z_val;
3798 
3799     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sdz", &key, &key_len, &incrby, &z_val) == FAILURE) {
3800         RETURN_FALSE;
3801     }
3802 
3803     SW_REDIS_COMMAND_CHECK;
3804 
3805     int i = 0;
3806     size_t argvlen[4];
3807     char *argv[4];
3808     SW_REDIS_COMMAND_ARGV_FILL("ZINCRBY", 7)
3809     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
3810     char buf[32];
3811     size_t buf_len;
3812     buf_len = sprintf(buf, "%f", incrby);
3813     SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
3814     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_val)
3815     redis_request(redis, 4, argv, argvlen, return_value);
3816 }
3817 
PHP_METHOD(swoole_redis_coro,zAdd)3818 static PHP_METHOD(swoole_redis_coro, zAdd) {
3819     int argc = ZEND_NUM_ARGS();
3820     SW_REDIS_COMMAND_CHECK
3821     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
3822 
3823     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE) {
3824         efree(z_args);
3825         RETURN_FALSE;
3826     }
3827 
3828     if (argc > 0) {
3829         convert_to_string(&z_args[0]);
3830     }
3831     if (argc < 3 || SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) != IS_STRING) {
3832         efree(z_args);
3833         RETURN_FALSE;
3834     }
3835 
3836     int i = 0, j, k, valid_params;
3837     valid_params = argc - 1;
3838     argc++;
3839     SW_REDIS_COMMAND_ALLOC_ARGV
3840     SW_REDIS_COMMAND_ARGV_FILL("ZADD", 4)
3841     SW_REDIS_COMMAND_ARGV_FILL(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]),
3842                                (size_t) SW_REDIS_COMMAND_ARGS_STRLEN(z_args[0]))
3843     k = 1;
3844 
3845     if (SW_REDIS_COMMAND_ARGS_TYPE(z_args[k]) == IS_STRING && IS_NX_XX_ARG(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[k]))) {
3846         SW_REDIS_COMMAND_ARGV_FILL(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[k]),
3847                                    (size_t) SW_REDIS_COMMAND_ARGS_STRLEN(z_args[k]))
3848         k++;
3849         valid_params--;
3850     }
3851 
3852     if (SW_REDIS_COMMAND_ARGS_TYPE(z_args[k]) == IS_STRING &&
3853         strncasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[k]), "CH", 2) == 0) {
3854         SW_REDIS_COMMAND_ARGV_FILL("CH", 2)
3855         k++;
3856         valid_params--;
3857     }
3858 
3859     if (SW_REDIS_COMMAND_ARGS_TYPE(z_args[k]) == IS_STRING &&
3860         strncasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[k]), "INCR", 4) == 0) {
3861         SW_REDIS_COMMAND_ARGV_FILL("INCR", 4)
3862         k++;
3863         valid_params--;
3864     }
3865 
3866     if (valid_params % 2 != 0) {
3867         for (i = 0; i < 1 + k; i++) {
3868             efree((void *) argv[i]);
3869         }
3870         SW_REDIS_COMMAND_FREE_ARGV
3871         efree(z_args);
3872         RETURN_FALSE;
3873     }
3874 
3875     char buf[32];
3876     size_t buf_len;
3877     for (j = k; j < argc - 1; j += 2) {
3878         buf_len = sw_snprintf(buf, sizeof(buf), "%f", zval_get_double(&z_args[j]));
3879         SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len)
3880         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(SW_REDIS_COMMAND_ARGS_REF(z_args[j + 1]))
3881     }
3882     efree(z_args);
3883 
3884     redis_request(redis, argc, argv, argvlen, return_value);
3885     SW_REDIS_COMMAND_FREE_ARGV
3886 }
3887 
PHP_METHOD(swoole_redis_coro,zPopMin)3888 static PHP_METHOD(swoole_redis_coro, zPopMin) {
3889     char *key;
3890     size_t key_len;
3891     zend_long count = 0;
3892 
3893     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &key, &key_len, &count) == FAILURE) {
3894         RETURN_FALSE;
3895     }
3896     SW_REDIS_COMMAND_CHECK
3897 
3898     int i = 0, argc, buf_len;
3899     char buf[32];
3900     argc = ZEND_NUM_ARGS() == 2 ? 3 : 2;
3901     SW_REDIS_COMMAND_ALLOC_ARGV
3902     SW_REDIS_COMMAND_ARGV_FILL("ZPOPMIN", 7);
3903     SW_REDIS_COMMAND_ARGV_FILL(key, key_len);
3904     if (argc == 3) {
3905         buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", count);
3906         SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len);
3907     }
3908     redis_request(redis, argc, argv, argvlen, return_value);
3909     SW_REDIS_COMMAND_FREE_ARGV
3910 }
3911 
PHP_METHOD(swoole_redis_coro,zPopMax)3912 static PHP_METHOD(swoole_redis_coro, zPopMax) {
3913     char *key;
3914     size_t key_len;
3915     zend_long count = 0;
3916 
3917     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &key, &key_len, &count) == FAILURE) {
3918         RETURN_FALSE;
3919     }
3920     SW_REDIS_COMMAND_CHECK
3921 
3922     int i = 0, argc, buf_len;
3923     char buf[32];
3924     argc = ZEND_NUM_ARGS() == 2 ? 3 : 2;
3925     SW_REDIS_COMMAND_ALLOC_ARGV
3926     SW_REDIS_COMMAND_ARGV_FILL("ZPOPMAX", 7);
3927     SW_REDIS_COMMAND_ARGV_FILL(key, key_len);
3928     if (argc == 3) {
3929         buf_len = sw_snprintf(buf, sizeof(buf), "%" PRId64 "", count);
3930         SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len);
3931     }
3932     redis_request(redis, argc, argv, argvlen, return_value);
3933     SW_REDIS_COMMAND_FREE_ARGV
3934 }
3935 
PHP_METHOD(swoole_redis_coro,bzPopMin)3936 static PHP_METHOD(swoole_redis_coro, bzPopMin) {
3937     int argc = ZEND_NUM_ARGS();
3938     SW_REDIS_COMMAND_CHECK
3939     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
3940     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc < 1) {
3941         efree(z_args);
3942         return;
3943     }
3944 
3945     zend_bool single_array = 0;
3946     if (argc == 2 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY) {
3947         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0])) + 2;
3948         single_array = 1;
3949     } else {
3950         argc += 1;
3951     }
3952     int i = 0;
3953     SW_REDIS_COMMAND_ALLOC_ARGV
3954     SW_REDIS_COMMAND_ARGV_FILL("BZPOPMIN", 8)
3955     if (single_array) {
3956         zval *value;
3957         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
3958         zend_string *convert_str = zval_get_string(value);
3959         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3960         zend_string_release(convert_str);
3961         SW_HASHTABLE_FOREACH_END();
3962         zend_string *convert_str = zval_get_string(&z_args[1]);
3963         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3964         zend_string_release(convert_str);
3965     } else {
3966         int j;
3967         for (j = 0; j < argc - 1; ++j) {
3968             zend_string *convert_str = zval_get_string(&z_args[j]);
3969             SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
3970             zend_string_release(convert_str);
3971         }
3972     }
3973     efree(z_args);
3974 
3975     redis_request(redis, argc, argv, argvlen, return_value);
3976     SW_REDIS_COMMAND_FREE_ARGV
3977 }
3978 
PHP_METHOD(swoole_redis_coro,bzPopMax)3979 static PHP_METHOD(swoole_redis_coro, bzPopMax) {
3980     int argc = ZEND_NUM_ARGS();
3981     SW_REDIS_COMMAND_CHECK
3982     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
3983     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc < 1) {
3984         efree(z_args);
3985         return;
3986     }
3987 
3988     zend_bool single_array = 0;
3989     if (argc == 2 && SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) == IS_ARRAY) {
3990         argc = zend_hash_num_elements(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0])) + 2;
3991         single_array = 1;
3992     } else {
3993         argc += 1;
3994     }
3995     int i = 0;
3996     SW_REDIS_COMMAND_ALLOC_ARGV
3997     SW_REDIS_COMMAND_ARGV_FILL("BZPOPMAX", 8)
3998     if (single_array) {
3999         zval *value;
4000         SW_HASHTABLE_FOREACH_START(SW_REDIS_COMMAND_ARGS_ARRVAL(z_args[0]), value)
4001         zend_string *convert_str = zval_get_string(value);
4002         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4003         zend_string_release(convert_str);
4004         SW_HASHTABLE_FOREACH_END();
4005         zend_string *convert_str = zval_get_string(&z_args[1]);
4006         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4007         zend_string_release(convert_str);
4008     } else {
4009         int j;
4010         for (j = 0; j < argc - 1; ++j) {
4011             zend_string *convert_str = zval_get_string(&z_args[j]);
4012             SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4013             zend_string_release(convert_str);
4014         }
4015     }
4016     efree(z_args);
4017 
4018     redis_request(redis, argc, argv, argvlen, return_value);
4019     SW_REDIS_COMMAND_FREE_ARGV
4020 }
4021 
PHP_METHOD(swoole_redis_coro,zScore)4022 static PHP_METHOD(swoole_redis_coro, zScore) {
4023     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZSCORE"));
4024 }
4025 
PHP_METHOD(swoole_redis_coro,zRank)4026 static PHP_METHOD(swoole_redis_coro, zRank) {
4027     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZRANK"));
4028 }
4029 
PHP_METHOD(swoole_redis_coro,zRevRank)4030 static PHP_METHOD(swoole_redis_coro, zRevRank) {
4031     sw_redis_command_key_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZREVRANK"));
4032 }
4033 
PHP_METHOD(swoole_redis_coro,hGet)4034 static PHP_METHOD(swoole_redis_coro, hGet) {
4035     sw_redis_command_key_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HGET"));
4036 }
4037 
PHP_METHOD(swoole_redis_coro,hMGet)4038 static PHP_METHOD(swoole_redis_coro, hMGet) {
4039     char *key;
4040     zval *z_arr;
4041     size_t argc, key_len;
4042     HashTable *ht_chan;
4043 
4044     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa", &key, &key_len, &z_arr) == FAILURE) {
4045         return;
4046     }
4047 
4048     ht_chan = Z_ARRVAL_P(z_arr);
4049 
4050     if ((argc = zend_hash_num_elements(ht_chan)) == 0) {
4051         RETURN_FALSE;
4052     }
4053     SW_REDIS_COMMAND_CHECK
4054 
4055     zval *value;
4056     int i = 0;
4057     argc = argc + 2;
4058     SW_REDIS_COMMAND_ALLOC_ARGV
4059     SW_REDIS_COMMAND_ARGV_FILL("HMGET", 5)
4060     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4061     SW_HASHTABLE_FOREACH_START(ht_chan, value)
4062     zend_string *convert_str = zval_get_string(value);
4063     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4064     zend_string_release(convert_str);
4065     SW_HASHTABLE_FOREACH_END();
4066     redis_request(redis, argc, argv, argvlen, return_value);
4067     SW_REDIS_COMMAND_FREE_ARGV
4068 
4069     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
4070         size_t index = 0;
4071         zval *zkey, *zvalue;
4072         zval zret;
4073         array_init(&zret);
4074 
4075         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_arr), zkey) {
4076             zend::String zkey_str(zkey);
4077 
4078             zvalue = zend_hash_index_find(Z_ARRVAL_P(return_value), index++);
4079             if (ZVAL_IS_NULL(zvalue)) {
4080                 add_assoc_bool_ex(&zret, zkey_str.val(), zkey_str.len(), 0);
4081             } else {
4082                 Z_ADDREF_P(zvalue);
4083                 add_assoc_zval_ex(&zret, zkey_str.val(), zkey_str.len(), zvalue);
4084             }
4085         }
4086         ZEND_HASH_FOREACH_END();
4087 
4088         zval_ptr_dtor(return_value);
4089         RETVAL_ZVAL(&zret, 1, 1);
4090     }
4091 }
4092 
PHP_METHOD(swoole_redis_coro,hExists)4093 static PHP_METHOD(swoole_redis_coro, hExists) {
4094     sw_redis_command_key_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HEXISTS"));
4095 
4096     RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS);
4097     if (redis->compatibility_mode && ZVAL_IS_LONG(return_value)) {
4098         RETURN_BOOL(zval_get_long(return_value));
4099     }
4100 }
4101 
PHP_METHOD(swoole_redis_coro,publish)4102 static PHP_METHOD(swoole_redis_coro, publish) {
4103     sw_redis_command_key_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PUBLISH"));
4104 }
4105 
PHP_METHOD(swoole_redis_coro,zDeleteRangeByScore)4106 static PHP_METHOD(swoole_redis_coro, zDeleteRangeByScore) {
4107     sw_redis_command_key_str_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZREMRANGEBYSCORE"));
4108 }
4109 
PHP_METHOD(swoole_redis_coro,zCount)4110 static PHP_METHOD(swoole_redis_coro, zCount) {
4111     sw_redis_command_key_str_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZCOUNT"));
4112 }
4113 
PHP_METHOD(swoole_redis_coro,incrBy)4114 static PHP_METHOD(swoole_redis_coro, incrBy) {
4115     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("INCRBY"));
4116 }
4117 
PHP_METHOD(swoole_redis_coro,hIncrBy)4118 static PHP_METHOD(swoole_redis_coro, hIncrBy) {
4119     char *key, *mem;
4120     size_t key_len, mem_len;
4121     long byval;
4122 
4123     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl", &key, &key_len, &mem, &mem_len, &byval) == FAILURE) {
4124         return;
4125     }
4126     SW_REDIS_COMMAND_CHECK
4127 
4128     int i = 0;
4129     size_t argvlen[4];
4130     char *argv[4];
4131     SW_REDIS_COMMAND_ARGV_FILL("HINCRBY", 7)
4132     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4133     SW_REDIS_COMMAND_ARGV_FILL(mem, mem_len)
4134     char str[32];
4135     sprintf(str, "%ld", byval);
4136     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
4137 
4138     redis_request(redis, 4, argv, argvlen, return_value);
4139 }
4140 
PHP_METHOD(swoole_redis_coro,hIncrByFloat)4141 static PHP_METHOD(swoole_redis_coro, hIncrByFloat) {
4142     char *key, *mem;
4143     size_t key_len, mem_len;
4144     double byval;
4145 
4146     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssd", &key, &key_len, &mem, &mem_len, &byval) == FAILURE) {
4147         return;
4148     }
4149     SW_REDIS_COMMAND_CHECK
4150 
4151     int i = 0;
4152     size_t argvlen[4];
4153     char *argv[4];
4154     SW_REDIS_COMMAND_ARGV_FILL("HINCRBYFLOAT", 12)
4155     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4156     SW_REDIS_COMMAND_ARGV_FILL(mem, mem_len)
4157     char str[32];
4158     sprintf(str, "%f", byval);
4159     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
4160 
4161     redis_request(redis, 4, argv, argvlen, return_value);
4162 }
4163 
PHP_METHOD(swoole_redis_coro,incr)4164 static PHP_METHOD(swoole_redis_coro, incr) {
4165     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("INCR"));
4166 }
4167 
PHP_METHOD(swoole_redis_coro,decrBy)4168 static PHP_METHOD(swoole_redis_coro, decrBy) {
4169     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DECRBY"));
4170 }
4171 
PHP_METHOD(swoole_redis_coro,decr)4172 static PHP_METHOD(swoole_redis_coro, decr) {
4173     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("DECR"));
4174 }
4175 
PHP_METHOD(swoole_redis_coro,getBit)4176 static PHP_METHOD(swoole_redis_coro, getBit) {
4177     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("GETBIT"));
4178 }
4179 
PHP_METHOD(swoole_redis_coro,lInsert)4180 static PHP_METHOD(swoole_redis_coro, lInsert) {
4181     char *key, *pos;
4182     size_t key_len, pos_len;
4183     zval *z_val, *z_pivot;
4184 
4185     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sszz", &key, &key_len, &pos, &pos_len, &z_pivot, &z_val) == FAILURE) {
4186         return;
4187     }
4188 
4189     if (strncasecmp(pos, "after", 5) && strncasecmp(pos, "before", 6)) {
4190         php_swoole_error(E_WARNING, "Position must be either 'BEFORE' or 'AFTER'");
4191         RETURN_FALSE;
4192     }
4193 
4194     SW_REDIS_COMMAND_CHECK
4195 
4196     int i = 0;
4197     size_t argvlen[5];
4198     char *argv[5];
4199 
4200     SW_REDIS_COMMAND_ARGV_FILL("LINSERT", 7)
4201     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4202     SW_REDIS_COMMAND_ARGV_FILL(pos, pos_len)
4203     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_pivot)
4204     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_val)
4205     redis_request(redis, 5, argv, argvlen, return_value);
4206 }
4207 
PHP_METHOD(swoole_redis_coro,lGet)4208 static PHP_METHOD(swoole_redis_coro, lGet) {
4209     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LINDEX"));
4210 }
4211 
PHP_METHOD(swoole_redis_coro,setTimeout)4212 static PHP_METHOD(swoole_redis_coro, setTimeout) {
4213     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("EXPIRE"));
4214 }
4215 
PHP_METHOD(swoole_redis_coro,pexpire)4216 static PHP_METHOD(swoole_redis_coro, pexpire) {
4217     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PEXPIRE"));
4218 }
4219 
PHP_METHOD(swoole_redis_coro,expireAt)4220 static PHP_METHOD(swoole_redis_coro, expireAt) {
4221     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("EXPIREAT"));
4222 }
4223 
PHP_METHOD(swoole_redis_coro,pexpireAt)4224 static PHP_METHOD(swoole_redis_coro, pexpireAt) {
4225     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("PEXPIREAT"));
4226 }
4227 
PHP_METHOD(swoole_redis_coro,move)4228 static PHP_METHOD(swoole_redis_coro, move) {
4229     sw_redis_command_key_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("MOVE"));
4230 }
4231 
PHP_METHOD(swoole_redis_coro,select)4232 static PHP_METHOD(swoole_redis_coro, select) {
4233     zend_long db_number;
4234 
4235     ZEND_PARSE_PARAMETERS_START(1, 1)
4236     Z_PARAM_LONG(db_number)
4237     ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
4238 
4239     SW_REDIS_COMMAND_CHECK
4240     zval *zsetting = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0);
4241     add_assoc_long(zsetting, "database", db_number);
4242     RETURN_BOOL(redis_select_db(redis, db_number));
4243 }
4244 
PHP_METHOD(swoole_redis_coro,getRange)4245 static PHP_METHOD(swoole_redis_coro, getRange) {
4246     sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("GETRANGE"));
4247 }
4248 
PHP_METHOD(swoole_redis_coro,listTrim)4249 static PHP_METHOD(swoole_redis_coro, listTrim) {
4250     sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LTRIM"));
4251 }
4252 
PHP_METHOD(swoole_redis_coro,lGetRange)4253 static PHP_METHOD(swoole_redis_coro, lGetRange) {
4254     sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("LRANGE"));
4255 }
4256 
PHP_METHOD(swoole_redis_coro,lRem)4257 static PHP_METHOD(swoole_redis_coro, lRem) {
4258     char *key;
4259     size_t key_len;
4260     zend_long count = 0;
4261     zval *z_val;
4262 
4263     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|l", &key, &key_len, &z_val, &count) == FAILURE) {
4264         RETURN_FALSE;
4265     }
4266     SW_REDIS_COMMAND_CHECK
4267 
4268     int i = 0;
4269     size_t argvlen[4];
4270     char *argv[4];
4271     SW_REDIS_COMMAND_ARGV_FILL("LREM", 4)
4272     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4273     char str[32];
4274     sprintf(str, "%d", (int) count);
4275     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
4276     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_val)
4277 
4278     redis_request(redis, 4, argv, argvlen, return_value);
4279 }
4280 
PHP_METHOD(swoole_redis_coro,zDeleteRangeByRank)4281 static PHP_METHOD(swoole_redis_coro, zDeleteRangeByRank) {
4282     sw_redis_command_key_long_long(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZREMRANGEBYRANK"));
4283 }
4284 
PHP_METHOD(swoole_redis_coro,incrByFloat)4285 static PHP_METHOD(swoole_redis_coro, incrByFloat) {
4286     sw_redis_command_key_dbl(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("INCRBYFLOAT"));
4287 }
4288 
PHP_METHOD(swoole_redis_coro,bitCount)4289 static PHP_METHOD(swoole_redis_coro, bitCount) {
4290     char *key;
4291     size_t key_len;
4292     zend_long start = 0, end = -1;
4293 
4294     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &key, &key_len, &start, &end) == FAILURE) {
4295         return;
4296     }
4297 
4298     SW_REDIS_COMMAND_CHECK
4299 
4300     int i = 0;
4301     size_t argvlen[4];
4302     char *argv[4];
4303     SW_REDIS_COMMAND_ARGV_FILL("BITCOUNT", 8)
4304     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4305     char str[32];
4306     sprintf(str, "%d", (int) start);
4307     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
4308     sprintf(str, "%d", (int) end);
4309     SW_REDIS_COMMAND_ARGV_FILL(str, strlen(str))
4310 
4311     redis_request(redis, 4, argv, argvlen, return_value);
4312 }
4313 
PHP_METHOD(swoole_redis_coro,bitOp)4314 static PHP_METHOD(swoole_redis_coro, bitOp) {
4315     int argc = ZEND_NUM_ARGS();
4316     SW_REDIS_COMMAND_CHECK
4317     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
4318     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || argc < 3 ||
4319         SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) != IS_STRING) {
4320         efree(z_args);
4321         return;
4322     }
4323 
4324     int j, i = 0;
4325     argc++;
4326     SW_REDIS_COMMAND_ALLOC_ARGV
4327     SW_REDIS_COMMAND_ARGV_FILL("BITOP", 5)
4328     SW_REDIS_COMMAND_ARGV_FILL(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), SW_REDIS_COMMAND_ARGS_STRLEN(z_args[0]))
4329     for (j = 1; j < argc - 1; j++) {
4330         zend_string *convert_str = zval_get_string(&z_args[j]);
4331         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4332         zend_string_release(convert_str);
4333     }
4334 
4335     redis_request(redis, argc, argv, argvlen, return_value);
4336     SW_REDIS_COMMAND_FREE_ARGV
4337     efree(z_args);
4338 }
4339 
PHP_METHOD(swoole_redis_coro,sMove)4340 static PHP_METHOD(swoole_redis_coro, sMove) {
4341     char *src, *dst;
4342     size_t src_len, dst_len;
4343     zval *z_val;
4344 
4345     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssz", &src, &src_len, &dst, &dst_len, &z_val) == FAILURE) {
4346         return;
4347     }
4348     SW_REDIS_COMMAND_CHECK
4349 
4350     int i = 0;
4351     size_t argvlen[4];
4352     char *argv[4];
4353     SW_REDIS_COMMAND_ARGV_FILL("SMOVE", 5)
4354     SW_REDIS_COMMAND_ARGV_FILL(src, src_len)
4355     SW_REDIS_COMMAND_ARGV_FILL(dst, dst_len)
4356     SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(z_val)
4357     redis_request(redis, 4, argv, argvlen, return_value);
4358 }
4359 
PHP_METHOD(swoole_redis_coro,sAdd)4360 static PHP_METHOD(swoole_redis_coro, sAdd) {
4361     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SADD"));
4362 }
4363 
PHP_METHOD(swoole_redis_coro,sRemove)4364 static PHP_METHOD(swoole_redis_coro, sRemove) {
4365     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("SREM"));
4366 }
4367 
PHP_METHOD(swoole_redis_coro,zDelete)4368 static PHP_METHOD(swoole_redis_coro, zDelete) {
4369     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("ZREM"));
4370 }
4371 
redis_subscribe(INTERNAL_FUNCTION_PARAMETERS,const char * cmd)4372 static sw_inline void redis_subscribe(INTERNAL_FUNCTION_PARAMETERS, const char *cmd) {
4373     zval *z_arr;
4374     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &z_arr) == FAILURE) {
4375         RETURN_FALSE;
4376     }
4377 
4378     SW_REDIS_COMMAND_CHECK
4379     if (redis->defer) {
4380         zend_update_property_long(
4381             swoole_redis_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errType"), SW_REDIS_ERR_OTHER);
4382         zend_update_property_long(swoole_redis_coro_ce,
4383                                   SW_Z8_OBJ_P(ZEND_THIS),
4384                                   ZEND_STRL("errCode"),
4385                                   sw_redis_convert_err(SW_REDIS_ERR_OTHER));
4386         zend_update_property_string(swoole_redis_coro_ce,
4387                                     SW_Z8_OBJ_P(ZEND_THIS),
4388                                     ZEND_STRL("errMsg"),
4389                                     "subscribe cannot be used with defer enabled");
4390         RETURN_FALSE;
4391     }
4392 
4393     HashTable *ht_chan = Z_ARRVAL_P(z_arr);
4394     size_t chan_num = zend_hash_num_elements(ht_chan);
4395     int argc = 1 + chan_num, i = 0;
4396     SW_REDIS_COMMAND_ALLOC_ARGV
4397 
4398     SW_REDIS_COMMAND_ARGV_FILL(cmd, strlen(cmd));
4399 
4400     zval *value;
4401     SW_HASHTABLE_FOREACH_START(ht_chan, value)
4402     zend_string *convert_str = zval_get_string(value);
4403     SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str))
4404     zend_string_release(convert_str);
4405     SW_HASHTABLE_FOREACH_END();
4406 
4407     redis->defer = true;
4408     redis_request(redis, argc, argv, argvlen, return_value);
4409     redis->defer = false;
4410     SW_REDIS_COMMAND_FREE_ARGV
4411 
4412     if (Z_TYPE_P(return_value) == IS_TRUE) {
4413         redis->session.subscribe = true;
4414     }
4415 }
4416 
PHP_METHOD(swoole_redis_coro,subscribe)4417 static PHP_METHOD(swoole_redis_coro, subscribe) {
4418     redis_subscribe(INTERNAL_FUNCTION_PARAM_PASSTHRU, "SUBSCRIBE");
4419 }
4420 
PHP_METHOD(swoole_redis_coro,pSubscribe)4421 static PHP_METHOD(swoole_redis_coro, pSubscribe) {
4422     redis_subscribe(INTERNAL_FUNCTION_PARAM_PASSTHRU, "PSUBSCRIBE");
4423 }
4424 
PHP_METHOD(swoole_redis_coro,unsubscribe)4425 static PHP_METHOD(swoole_redis_coro, unsubscribe) {
4426     redis_subscribe(INTERNAL_FUNCTION_PARAM_PASSTHRU, "UNSUBSCRIBE");
4427 }
4428 
PHP_METHOD(swoole_redis_coro,pUnSubscribe)4429 static PHP_METHOD(swoole_redis_coro, pUnSubscribe) {
4430     redis_subscribe(INTERNAL_FUNCTION_PARAM_PASSTHRU, "PUNSUBSCRIBE");
4431 }
4432 
PHP_METHOD(swoole_redis_coro,multi)4433 static PHP_METHOD(swoole_redis_coro, multi) {
4434     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("MULTI"));
4435 }
4436 
PHP_METHOD(swoole_redis_coro,exec)4437 static PHP_METHOD(swoole_redis_coro, exec) {
4438     sw_redis_command_empty(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("EXEC"));
4439 }
4440 
PHP_METHOD(swoole_redis_coro,request)4441 static PHP_METHOD(swoole_redis_coro, request) {
4442     SW_REDIS_COMMAND_CHECK
4443 
4444     zval *params = nullptr;
4445     if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &params) == FAILURE) {
4446         RETURN_FALSE;
4447     }
4448 
4449     int argc = zend_hash_num_elements(Z_ARRVAL_P(params));
4450     int i = 0;
4451     zval *value;
4452 
4453     SW_REDIS_COMMAND_ALLOC_ARGV
4454 
4455     SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value)
4456     if (i == argc) {
4457         break;
4458     }
4459     zend_string *convert_str = zval_get_string(value);
4460     argvlen[i] = ZSTR_LEN(convert_str);
4461     argv[i] = estrndup(ZSTR_VAL(convert_str), ZSTR_LEN(convert_str));
4462     zend_string_release(convert_str);
4463     i++;
4464     SW_HASHTABLE_FOREACH_END();
4465 
4466     redis_request(redis, argc, argv, argvlen, return_value);
4467     SW_REDIS_COMMAND_FREE_ARGV
4468 }
4469 
PHP_METHOD(swoole_redis_coro,eval)4470 static PHP_METHOD(swoole_redis_coro, eval) {
4471     char *script;
4472     size_t script_len;
4473     zval *params = nullptr;
4474     zend_long keys_num = 0;
4475 
4476     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|al", &script, &script_len, &params, &keys_num) == FAILURE) {
4477         RETURN_FALSE;
4478     }
4479 
4480     HashTable *params_ht = nullptr;
4481     uint32_t params_num = 0;
4482     if (params) {
4483         params_ht = Z_ARRVAL_P(params);
4484         params_num = zend_hash_num_elements(params_ht);
4485     }
4486 
4487     SW_REDIS_COMMAND_CHECK
4488     int i = 0;
4489     size_t *argvlen = (size_t *) emalloc(sizeof(size_t) * (params_num + 3));
4490     char **argv = (char **) emalloc(sizeof(char *) * (params_num + 3));
4491 
4492     SW_REDIS_COMMAND_ARGV_FILL("EVAL", 4)
4493     SW_REDIS_COMMAND_ARGV_FILL(script, script_len)
4494 
4495     char keys_num_str[32] = {};
4496     sprintf(keys_num_str, ZEND_LONG_FMT, keys_num);
4497     SW_REDIS_COMMAND_ARGV_FILL(keys_num_str, strlen(keys_num_str));
4498 
4499     if (params_ht) {
4500         zval *param;
4501         SW_HASHTABLE_FOREACH_START(params_ht, param)
4502         zend_string *param_str = zval_get_string(param);
4503         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(param_str), ZSTR_LEN(param_str))
4504         zend_string_release(param_str);
4505         SW_HASHTABLE_FOREACH_END();
4506     }
4507 
4508     redis_request(redis, params_num + 3, argv, argvlen, return_value);
4509     efree(argvlen);
4510     efree(argv);
4511 }
4512 
PHP_METHOD(swoole_redis_coro,evalSha)4513 static PHP_METHOD(swoole_redis_coro, evalSha) {
4514     char *sha;
4515     size_t sha_len;
4516     zval *params = nullptr;
4517     long keys_num = 0;
4518     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|al", &sha, &sha_len, &params, &keys_num) == FAILURE) {
4519         RETURN_FALSE;
4520     }
4521 
4522     HashTable *params_ht = nullptr;
4523     uint32_t params_num = 0;
4524     if (params) {
4525         params_ht = Z_ARRVAL_P(params);
4526         params_num = zend_hash_num_elements(params_ht);
4527     }
4528 
4529     SW_REDIS_COMMAND_CHECK
4530     int i = 0;
4531     size_t *argvlen = (size_t *) emalloc(sizeof(size_t) * (params_num + 3));
4532     char **argv = (char **) emalloc(sizeof(char *) * (params_num + 3));
4533 
4534     SW_REDIS_COMMAND_ARGV_FILL("EVALSHA", 7)
4535     SW_REDIS_COMMAND_ARGV_FILL(sha, sha_len)
4536 
4537     char keys_num_str[32] = {};
4538     sprintf(keys_num_str, "%ld", keys_num);
4539     SW_REDIS_COMMAND_ARGV_FILL(keys_num_str, strlen(keys_num_str));
4540 
4541     if (params) {
4542         zval *param;
4543         SW_HASHTABLE_FOREACH_START(params_ht, param)
4544         zend_string *param_str = zval_get_string(param);
4545         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(param_str), ZSTR_LEN(param_str))
4546         zend_string_release(param_str);
4547         SW_HASHTABLE_FOREACH_END();
4548     }
4549 
4550     redis_request(redis, params_num + 3, argv, argvlen, return_value);
4551     efree(argvlen);
4552     efree(argv);
4553 }
4554 
PHP_METHOD(swoole_redis_coro,script)4555 static PHP_METHOD(swoole_redis_coro, script) {
4556     int argc = ZEND_NUM_ARGS();
4557     if (argc < 1) {
4558         RETURN_FALSE;
4559     }
4560     SW_REDIS_COMMAND_CHECK
4561     SW_REDIS_COMMAND_ALLOC_ARGS_ARR
4562     if (zend_get_parameters_array(ht, argc, z_args) == FAILURE || SW_REDIS_COMMAND_ARGS_TYPE(z_args[0]) != IS_STRING) {
4563         efree(z_args);
4564         RETURN_FALSE;
4565     }
4566 
4567     int i = 0;
4568     if (!strcasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), "flush") ||
4569         !strcasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), "kill")) {
4570         size_t argvlen[2];
4571         char *argv[2];
4572         SW_REDIS_COMMAND_ARGV_FILL("SCRIPT", 6)
4573         SW_REDIS_COMMAND_ARGV_FILL(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), SW_REDIS_COMMAND_ARGS_STRLEN(z_args[0]))
4574         redis_request(redis, 2, argv, argvlen, return_value);
4575         efree(z_args);
4576     } else if (!strcasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), "exists")) {
4577         if (argc < 2) {
4578             efree(z_args);
4579             RETURN_FALSE;
4580         } else {
4581             size_t *argvlen = (size_t *) emalloc(sizeof(size_t) * (argc + 1));
4582             char **argv = (char **) emalloc(sizeof(char *) * (argc + 1));
4583             SW_REDIS_COMMAND_ARGV_FILL("SCRIPT", 6)
4584             SW_REDIS_COMMAND_ARGV_FILL("EXISTS", 6)
4585             int j = 1;
4586             for (; j < argc; j++) {
4587                 zend_string *z_arg_str = zval_get_string(&z_args[j]);
4588                 SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(z_arg_str), ZSTR_LEN(z_arg_str))
4589                 zend_string_release(z_arg_str);
4590             }
4591 
4592             redis_request(redis, argc + 1, argv, argvlen, return_value);
4593             efree(argvlen);
4594             efree(argv);
4595             efree(z_args);
4596         }
4597     } else if (!strcasecmp(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[0]), "load")) {
4598         if (argc < 2 || SW_REDIS_COMMAND_ARGS_TYPE(z_args[1]) != IS_STRING) {
4599             efree(z_args);
4600             RETURN_FALSE;
4601         } else {
4602             size_t argvlen[3];
4603             char *argv[3];
4604             SW_REDIS_COMMAND_ARGV_FILL("SCRIPT", 6)
4605             SW_REDIS_COMMAND_ARGV_FILL("LOAD", 4)
4606             SW_REDIS_COMMAND_ARGV_FILL(SW_REDIS_COMMAND_ARGS_STRVAL(z_args[1]), SW_REDIS_COMMAND_ARGS_STRLEN(z_args[1]))
4607             redis_request(redis, 3, argv, argvlen, return_value);
4608             efree(z_args);
4609         }
4610     } else {
4611         efree(z_args);
4612         RETURN_FALSE;
4613     }
4614 }
4615 
PHP_METHOD(swoole_redis_coro,xLen)4616 static PHP_METHOD(swoole_redis_coro, xLen) {
4617     sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XLEN"));
4618 }
4619 
PHP_METHOD(swoole_redis_coro,xAdd)4620 static PHP_METHOD(swoole_redis_coro, xAdd) {
4621     zval *z_options = nullptr, *z_ele;
4622     HashTable *ht_opt, *ht_ele;
4623     char *key, *id;
4624     size_t key_len, id_len;
4625     zval *z_arr;
4626     int argc, options_argc = 0;
4627 
4628     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa|a", &key, &key_len, &id, &id_len, &z_arr, &z_options) == FAILURE) {
4629         return;
4630     }
4631     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_arr))) == 0) {
4632         RETURN_FALSE;
4633     }
4634     SW_REDIS_COMMAND_CHECK
4635     int i = 0;
4636     argc = argc * 2 + 3;
4637     zval *value;
4638     char buf[32];
4639     size_t buf_len;
4640     SW_REDIS_COMMAND_ALLOC_ARGV
4641     SW_REDIS_COMMAND_ARGV_FILL("XADD", 4)
4642     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4643 
4644     // options
4645     if (z_options && ZVAL_IS_ARRAY(z_options)) {
4646         ht_opt = Z_ARRVAL_P(z_options);
4647         int has_maxlen_minid = 0;
4648         int can_limit = 0;
4649         // NOMKSTREAM
4650         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("nomkstream"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
4651             SW_REDIS_COMMAND_ARGV_FILL("NOMKSTREAM", 10)
4652             options_argc++;
4653         }
4654         // MAXLEN
4655         if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("maxlen")))) {
4656             has_maxlen_minid = 1;
4657             if (Z_TYPE_P(z_ele) == IS_LONG) {
4658                 SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6)
4659                 buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4660                 SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4661                 options_argc += 2;
4662             } else if (Z_TYPE_P(z_ele) == IS_ARRAY) {
4663                 ht_ele = Z_ARRVAL_P(z_ele);
4664                 zval *z_maxlen_p1 = zend_hash_index_find(ht_ele, 0);
4665                 zval *z_maxlen_p2 = zend_hash_index_find(ht_ele, 1);
4666                 if (Z_TYPE_P(z_maxlen_p1) == IS_STRING && Z_TYPE_P(z_maxlen_p2) == IS_LONG) {
4667                     char *maxlen_p1 = Z_STRVAL_P(z_maxlen_p1);
4668                     zend_long maxlen_p2 = Z_LVAL_P(z_maxlen_p2);
4669                     if ((strcmp(maxlen_p1, "=") == 0 || strcmp(maxlen_p1, "~") == 0) && maxlen_p2 >= 0) {
4670                         if ((strcmp(maxlen_p1, "~") == 0)) {
4671                             can_limit = 1;
4672                         }
4673                         SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6)
4674                         SW_REDIS_COMMAND_ARGV_FILL(maxlen_p1, 1)
4675                         buf_len = sprintf(buf, ZEND_LONG_FMT, maxlen_p2);
4676                         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4677                         options_argc += 3;
4678                     }
4679                 }
4680             }
4681         }
4682         // MINID
4683         if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("minid")))) {
4684             has_maxlen_minid = 1;
4685             if (Z_TYPE_P(z_ele) == IS_STRING && Z_STRLEN_P(z_ele) > 0) {
4686                 SW_REDIS_COMMAND_ARGV_FILL("MINID", 5)
4687                 SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele))
4688                 options_argc += 2;
4689             } else if (Z_TYPE_P(z_ele) == IS_ARRAY) {
4690                 ht_ele = Z_ARRVAL_P(z_ele);
4691                 zval *z_minid_p1 = zend_hash_index_find(ht_ele, 0);
4692                 zval *z_minid_p2 = zend_hash_index_find(ht_ele, 1);
4693                 if (Z_TYPE_P(z_minid_p1) == IS_STRING && Z_TYPE_P(z_minid_p2) == IS_STRING) {
4694                     char *minid_p1 = Z_STRVAL_P(z_minid_p1);
4695                     char *minid_p2 = Z_STRVAL_P(z_minid_p2);
4696                     if ((strcmp(minid_p1, "=") == 0 || strcmp(minid_p1, "~") == 0) && strlen(minid_p2) > 0) {
4697                         if ((strcmp(minid_p1, "~") == 0)) {
4698                             can_limit = 1;
4699                         }
4700                         SW_REDIS_COMMAND_ARGV_FILL("MINID", 5)
4701                         SW_REDIS_COMMAND_ARGV_FILL(minid_p1, 1)
4702                         SW_REDIS_COMMAND_ARGV_FILL(minid_p2, strlen(minid_p2))
4703                         options_argc += 3;
4704                     }
4705                 }
4706             }
4707         }
4708         // LIMIT
4709         if (can_limit == 1 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit"))) && Z_TYPE_P(z_ele) == IS_LONG) {
4710             SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
4711             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4712             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4713             options_argc += 2;
4714         }
4715     }
4716 
4717     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
4718 
4719     // id
4720     SW_REDIS_COMMAND_ARGV_FILL(id, id_len)
4721 
4722     // k-v
4723     zend_ulong idx;
4724     zend_string *_key;
4725     ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(z_arr), idx, _key, value) {
4726         if (_key == nullptr) {
4727             key_len = sw_snprintf(buf, sizeof(buf), ZEND_LONG_FMT, idx);
4728             key = (char *) buf;
4729         } else {
4730             key_len = ZSTR_LEN(_key);
4731             key = ZSTR_VAL(_key);
4732         }
4733         SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4734         SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(value)
4735     }
4736     ZEND_HASH_FOREACH_END();
4737 
4738     redis_request(redis, argc, argv, argvlen, return_value);
4739     SW_REDIS_COMMAND_FREE_ARGV
4740 }
4741 
PHP_METHOD(swoole_redis_coro,xRead)4742 static PHP_METHOD(swoole_redis_coro, xRead) {
4743     zval *z_streams = nullptr, *z_options = nullptr, *z_ele;
4744     HashTable *ht_opt;
4745     int i = 0, argc = 0, options_argc = 0;
4746 
4747     if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|a", &z_streams, &z_options) == FAILURE) {
4748         RETURN_FALSE;
4749     }
4750     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_streams))) == 0) {
4751         RETURN_FALSE;
4752     }
4753     SW_REDIS_COMMAND_CHECK
4754 
4755     argc = argc * 2 + 2;
4756     char buf[32];
4757     size_t buf_len;
4758     SW_REDIS_COMMAND_ALLOC_ARGV
4759     SW_REDIS_COMMAND_ARGV_FILL("XREAD", 5)
4760 
4761     // options
4762     if (z_options && ZVAL_IS_ARRAY(z_options)) {
4763         ht_opt = Z_ARRVAL_P(z_options);
4764         // COUNT
4765         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) {
4766             SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5)
4767             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4768             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4769             options_argc += 2;
4770         }
4771         // BLOCK
4772         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("block"))) && Z_TYPE_P(z_ele) == IS_LONG) {
4773             SW_REDIS_COMMAND_ARGV_FILL("BLOCK", 5)
4774             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4775             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4776             options_argc += 2;
4777         }
4778     }
4779 
4780     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
4781 
4782     // streams
4783     SW_REDIS_COMMAND_ARGV_FILL("STREAMS", 7)
4784     zend_long _num_key;
4785     zend_string *_str_key;
4786     zval *_val;
4787     ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(z_streams), _num_key, _str_key) {
4788         if (_str_key == NULL) {
4789             _str_key = zend_long_to_str(_num_key);
4790         }
4791         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(_str_key), ZSTR_LEN(_str_key))
4792     }
4793     ZEND_HASH_FOREACH_END();
4794     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_streams), _val) {
4795         convert_to_string(_val);
4796         SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_val), Z_STRLEN_P(_val))
4797     }
4798     ZEND_HASH_FOREACH_END();
4799 
4800     redis_request(redis, argc, argv, argvlen, return_value);
4801 
4802     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
4803         swoole_redis_handle_assoc_array_result(return_value, true);
4804     }
4805 
4806     SW_REDIS_COMMAND_FREE_ARGV
4807 }
4808 
PHP_METHOD(swoole_redis_coro,xRange)4809 static PHP_METHOD(swoole_redis_coro, xRange) {
4810     sw_redis_command_xrange(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XRANGE"));
4811 }
4812 
PHP_METHOD(swoole_redis_coro,xRevRange)4813 static PHP_METHOD(swoole_redis_coro, xRevRange) {
4814     sw_redis_command_xrange(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XREVRANGE"));
4815 }
4816 
PHP_METHOD(swoole_redis_coro,xTrim)4817 static PHP_METHOD(swoole_redis_coro, xTrim) {
4818     zval *z_options = nullptr, *z_ele;
4819     HashTable *ht_opt, *ht_ele;
4820     int i = 0, argc = 2, options_argc = 0;
4821     char buf[32], *key;
4822     size_t buf_len, key_len;
4823 
4824     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &key, &key_len, &z_options) == FAILURE) {
4825         RETURN_FALSE;
4826     }
4827     if (php_swoole_array_length_safe(z_options) < 1) {
4828         RETURN_FALSE;
4829     }
4830 
4831     SW_REDIS_COMMAND_CHECK
4832     SW_REDIS_COMMAND_ALLOC_ARGV
4833     SW_REDIS_COMMAND_ARGV_FILL("XTRIM", 5)
4834     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4835 
4836     // options
4837     if (z_options && ZVAL_IS_ARRAY(z_options)) {
4838         ht_opt = Z_ARRVAL_P(z_options);
4839         int has_maxlen_minid = 0;
4840         int can_limit = 0;
4841         // MAXLEN
4842         if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("maxlen")))) {
4843             has_maxlen_minid = 1;
4844             if (Z_TYPE_P(z_ele) == IS_LONG) {
4845                 SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6)
4846                 buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4847                 SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4848                 options_argc += 2;
4849             } else if (Z_TYPE_P(z_ele) == IS_ARRAY) {
4850                 ht_ele = Z_ARRVAL_P(z_ele);
4851                 zval *z_maxlen_p1 = zend_hash_index_find(ht_ele, 0);
4852                 zval *z_maxlen_p2 = zend_hash_index_find(ht_ele, 1);
4853                 if (Z_TYPE_P(z_maxlen_p1) == IS_STRING && Z_TYPE_P(z_maxlen_p2) == IS_LONG) {
4854                     char *maxlen_p1 = Z_STRVAL_P(z_maxlen_p1);
4855                     zend_long maxlen_p2 = Z_LVAL_P(z_maxlen_p2);
4856                     if ((strcmp(maxlen_p1, "=") == 0 || strcmp(maxlen_p1, "~") == 0) && maxlen_p2 >= 0) {
4857                         if ((strcmp(maxlen_p1, "~") == 0)) {
4858                             can_limit = 1;
4859                         }
4860                         SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6)
4861                         SW_REDIS_COMMAND_ARGV_FILL(maxlen_p1, 1)
4862                         buf_len = sprintf(buf, ZEND_LONG_FMT, maxlen_p2);
4863                         SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4864                         options_argc += 3;
4865                     }
4866                 }
4867             }
4868         }
4869         // MINID
4870         if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("minid")))) {
4871             has_maxlen_minid = 1;
4872             if (Z_TYPE_P(z_ele) == IS_STRING && Z_STRLEN_P(z_ele) > 0) {
4873                 SW_REDIS_COMMAND_ARGV_FILL("MINID", 5)
4874                 SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele))
4875                 options_argc += 2;
4876             } else if (Z_TYPE_P(z_ele) == IS_ARRAY) {
4877                 ht_ele = Z_ARRVAL_P(z_ele);
4878                 zval *z_minid_p1 = zend_hash_index_find(ht_ele, 0);
4879                 zval *z_minid_p2 = zend_hash_index_find(ht_ele, 1);
4880                 if (Z_TYPE_P(z_minid_p1) == IS_STRING && Z_TYPE_P(z_minid_p2) == IS_STRING) {
4881                     char *minid_p1 = Z_STRVAL_P(z_minid_p1);
4882                     char *minid_p2 = Z_STRVAL_P(z_minid_p2);
4883                     if ((strcmp(minid_p1, "=") == 0 || strcmp(minid_p1, "~") == 0) && strlen(minid_p2) > 0) {
4884                         if ((strcmp(minid_p1, "~") == 0)) {
4885                             can_limit = 1;
4886                         }
4887                         SW_REDIS_COMMAND_ARGV_FILL("MINID", 5)
4888                         SW_REDIS_COMMAND_ARGV_FILL(minid_p1, 1)
4889                         SW_REDIS_COMMAND_ARGV_FILL(minid_p2, strlen(minid_p2))
4890                         options_argc += 3;
4891                     }
4892                 }
4893             }
4894         }
4895         // LIMIT
4896         if (can_limit == 1 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit"))) && Z_TYPE_P(z_ele) == IS_LONG) {
4897             SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5)
4898             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
4899             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
4900             options_argc += 2;
4901         }
4902     }
4903 
4904     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
4905 
4906     redis_request(redis, argc, argv, argvlen, return_value);
4907 
4908     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
4909         swoole_redis_handle_assoc_array_result(return_value, true);
4910     }
4911 
4912     SW_REDIS_COMMAND_FREE_ARGV
4913 }
4914 
PHP_METHOD(swoole_redis_coro,xDel)4915 static PHP_METHOD(swoole_redis_coro, xDel) {
4916     sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XDEL"));
4917 }
4918 
PHP_METHOD(swoole_redis_coro,xGroupCreate)4919 static PHP_METHOD(swoole_redis_coro, xGroupCreate) {
4920     char *key, *group_name, *id;
4921     size_t key_len, group_name_len, id_len;
4922     zend_bool mkstream = 0;
4923 
4924     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|b", &key, &key_len, &group_name, &group_name_len, &id, &id_len, &mkstream) == FAILURE) {
4925         return;
4926     }
4927     SW_REDIS_COMMAND_CHECK
4928     int i = 0, argc = 5;
4929     size_t argvlen[6];
4930     char *argv[6];
4931     SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6)
4932     SW_REDIS_COMMAND_ARGV_FILL("CREATE", 6)
4933     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4934     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
4935     SW_REDIS_COMMAND_ARGV_FILL(id, id_len)
4936     if (mkstream) {
4937         SW_REDIS_COMMAND_ARGV_FILL("MKSTREAM", 8)
4938         argc = 6;
4939     }
4940 
4941     redis_request(redis, argc, argv, argvlen, return_value);
4942 }
4943 
PHP_METHOD(swoole_redis_coro,xGroupSetId)4944 static PHP_METHOD(swoole_redis_coro, xGroupSetId) {
4945     char *key, *group_name, *id;
4946     size_t key_len, group_name_len, id_len;
4947 
4948     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &id, &id_len) == FAILURE) {
4949         return;
4950     }
4951     SW_REDIS_COMMAND_CHECK
4952     int i = 0, argc = 5;
4953     size_t argvlen[5];
4954     char *argv[5];
4955     SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6)
4956     SW_REDIS_COMMAND_ARGV_FILL("CREATECONSUMER", 14)
4957     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4958     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
4959     SW_REDIS_COMMAND_ARGV_FILL(id, id_len)
4960 
4961     redis_request(redis, argc, argv, argvlen, return_value);
4962 }
4963 
PHP_METHOD(swoole_redis_coro,xGroupDestroy)4964 static PHP_METHOD(swoole_redis_coro, xGroupDestroy) {
4965     char *key, *group_name;
4966     size_t key_len, group_name_len;
4967 
4968     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key, &key_len, &group_name, &group_name_len) == FAILURE) {
4969         return;
4970     }
4971     SW_REDIS_COMMAND_CHECK
4972     int i = 0, argc = 4;
4973     size_t argvlen[4];
4974     char *argv[4];
4975     SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6)
4976     SW_REDIS_COMMAND_ARGV_FILL("DESTROY", 7)
4977     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4978     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
4979 
4980     redis_request(redis, argc, argv, argvlen, return_value);
4981 }
4982 
PHP_METHOD(swoole_redis_coro,xGroupCreateConsumer)4983 static PHP_METHOD(swoole_redis_coro, xGroupCreateConsumer) {
4984     char *key, *group_name, *consumer_name;
4985     size_t key_len, group_name_len, consumer_name_len;
4986 
4987     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len) == FAILURE) {
4988         return;
4989     }
4990     SW_REDIS_COMMAND_CHECK
4991     int i = 0, argc = 5;
4992     size_t argvlen[5];
4993     char *argv[5];
4994     SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6)
4995     SW_REDIS_COMMAND_ARGV_FILL("CREATECONSUMER", 14)
4996     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
4997     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
4998     SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len)
4999 
5000     redis_request(redis, argc, argv, argvlen, return_value);
5001 }
5002 
PHP_METHOD(swoole_redis_coro,xGroupDelConsumer)5003 static PHP_METHOD(swoole_redis_coro, xGroupDelConsumer) {
5004     char *key, *group_name, *consumer_name;
5005     size_t key_len, group_name_len, consumer_name_len;
5006 
5007     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len) == FAILURE) {
5008         return;
5009     }
5010     SW_REDIS_COMMAND_CHECK
5011     int i = 0, argc = 5;
5012     size_t argvlen[5];
5013     char *argv[5];
5014     SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6)
5015     SW_REDIS_COMMAND_ARGV_FILL("DELCONSUMER", 11)
5016     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5017     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5018     SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len)
5019 
5020     redis_request(redis, argc, argv, argvlen, return_value);
5021 }
5022 
PHP_METHOD(swoole_redis_coro,xReadGroup)5023 static PHP_METHOD(swoole_redis_coro, xReadGroup) {
5024     char *group_name, *consumer_name;
5025     size_t group_name_len, consumer_name_len;
5026     zval *z_streams = nullptr, *z_options = nullptr, *z_ele;
5027     HashTable *ht_opt;
5028     int i = 0, argc = 0, options_argc = 0;
5029     char buf[32];
5030     size_t buf_len;
5031 
5032     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa|a", &group_name, &group_name_len, &consumer_name, &consumer_name_len, &z_streams, &z_options) == FAILURE) {
5033         RETURN_FALSE;
5034     }
5035     if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_streams))) == 0) {
5036         RETURN_FALSE;
5037     }
5038     SW_REDIS_COMMAND_CHECK
5039     argc = argc * 2 + 5;
5040     SW_REDIS_COMMAND_ALLOC_ARGV
5041     SW_REDIS_COMMAND_ARGV_FILL("XREADGROUP", 10)
5042     SW_REDIS_COMMAND_ARGV_FILL("GROUP", 5)
5043     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5044     SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len)
5045 
5046     // options
5047     if (z_options && ZVAL_IS_ARRAY(z_options)) {
5048         ht_opt = Z_ARRVAL_P(z_options);
5049         // COUNT
5050         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5051             SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5)
5052             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5053             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5054             options_argc += 2;
5055         }
5056         // BLOCK
5057         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("block"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5058             SW_REDIS_COMMAND_ARGV_FILL("BLOCK", 5)
5059             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5060             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5061             options_argc += 2;
5062         }
5063         // NOACK
5064         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("noack"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
5065             SW_REDIS_COMMAND_ARGV_FILL("NOACK", 5)
5066             options_argc++;
5067         }
5068     }
5069 
5070     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
5071 
5072     // streams
5073     SW_REDIS_COMMAND_ARGV_FILL("STREAMS", 7)
5074     zend_long _num_key;
5075     zend_string *_str_key;
5076     zval *_val;
5077     ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(z_streams), _num_key, _str_key) {
5078         if (_str_key == NULL) {
5079             _str_key = zend_long_to_str(_num_key);
5080         }
5081         SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(_str_key), ZSTR_LEN(_str_key))
5082     }
5083     ZEND_HASH_FOREACH_END();
5084     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_streams), _val) {
5085         convert_to_string(_val);
5086         SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_val), Z_STRLEN_P(_val))
5087     }
5088     ZEND_HASH_FOREACH_END();
5089 
5090     redis_request(redis, argc, argv, argvlen, return_value);
5091 
5092     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5093         swoole_redis_handle_assoc_array_result(return_value, true);
5094     }
5095 
5096     SW_REDIS_COMMAND_FREE_ARGV
5097 }
5098 
PHP_METHOD(swoole_redis_coro,xPending)5099 static PHP_METHOD(swoole_redis_coro, xPending) {
5100     char *key, *group_name;
5101     size_t key_len, group_name_len;
5102     zval *z_options = nullptr, *z_ele;
5103     HashTable *ht_opt;
5104     int i = 0, argc = 3, options_argc = 0;
5105 
5106     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a", &key, &key_len, &group_name, &group_name_len, &z_options) == FAILURE) {
5107         RETURN_FALSE;
5108     }
5109 
5110     char buf[32];
5111     size_t buf_len;
5112     SW_REDIS_COMMAND_CHECK
5113     SW_REDIS_COMMAND_ALLOC_ARGV
5114     SW_REDIS_COMMAND_ARGV_FILL("XPENDING", 8)
5115     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5116     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5117 
5118     // options
5119     if (z_options && ZVAL_IS_ARRAY(z_options)) {
5120         ht_opt = Z_ARRVAL_P(z_options);
5121         // IDLE
5122         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("idle"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5123             SW_REDIS_COMMAND_ARGV_FILL("IDLE", 4)
5124             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5125             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5126             options_argc += 2;
5127         }
5128         // START
5129         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("start"))) && Z_TYPE_P(z_ele) == IS_STRING) {
5130             SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele))
5131             options_argc++;
5132         }
5133         // END
5134         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("end"))) && Z_TYPE_P(z_ele) == IS_STRING) {
5135             SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele))
5136             options_argc++;
5137         }
5138         // COUNT
5139         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5140             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5141             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5142             options_argc++;
5143         }
5144         // CONSUMER
5145         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("consumer"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
5146             SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele))
5147             options_argc++;
5148         }
5149     }
5150 
5151     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
5152 
5153     redis_request(redis, argc, argv, argvlen, return_value);
5154 
5155     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5156         swoole_redis_handle_assoc_array_result(return_value, true);
5157     }
5158 
5159     SW_REDIS_COMMAND_FREE_ARGV
5160 }
5161 
PHP_METHOD(swoole_redis_coro,xAck)5162 static PHP_METHOD(swoole_redis_coro, xAck) {
5163     char *key, *group_name;
5164     size_t key_len, group_name_len;
5165     zval *z_id = nullptr;
5166     int i = 0, argc = 3, id_argc = 0;
5167 
5168     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa", &key, &key_len, &group_name, &group_name_len, &z_id) == FAILURE) {
5169         RETURN_FALSE;
5170     }
5171     if ((id_argc = zend_hash_num_elements(Z_ARRVAL_P(z_id))) == 0) {
5172         RETURN_FALSE;
5173     }
5174     argc += id_argc;
5175     SW_REDIS_COMMAND_CHECK
5176     SW_REDIS_COMMAND_ALLOC_ARGV
5177     SW_REDIS_COMMAND_ARGV_FILL("XACK", 4)
5178     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5179     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5180 
5181     // id
5182     zval *_id;
5183     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_id), _id) {
5184         convert_to_string(_id);
5185         SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_id), Z_STRLEN_P(_id))
5186     }
5187     ZEND_HASH_FOREACH_END();
5188 
5189     redis_request(redis, argc, argv, argvlen, return_value);
5190 
5191     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5192         swoole_redis_handle_assoc_array_result(return_value, true);
5193     }
5194 
5195     SW_REDIS_COMMAND_FREE_ARGV
5196 }
5197 
PHP_METHOD(swoole_redis_coro,xClaim)5198 static PHP_METHOD(swoole_redis_coro, xClaim) {
5199     char *key, *group_name, *consumer_name;
5200     size_t key_len, group_name_len, consumer_name_len;
5201     zend_long min_idle_time = 0;
5202     zval *z_id = nullptr, *z_options = nullptr, *z_ele;
5203     HashTable *ht_opt;
5204     int i = 0, argc = 5, id_argc = 0, options_argc = 0;
5205 
5206     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssla|a", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len, &min_idle_time, &z_id, &z_options) == FAILURE) {
5207         RETURN_FALSE;
5208     }
5209 
5210     SW_REDIS_COMMAND_CHECK
5211     id_argc = zend_hash_num_elements(Z_ARRVAL_P(z_id));
5212     argc += id_argc;
5213     char buf[32];
5214     size_t buf_len;
5215     SW_REDIS_COMMAND_ALLOC_ARGV
5216     SW_REDIS_COMMAND_ARGV_FILL("XCLAIM", 6)
5217     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5218     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5219     SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len)
5220     buf_len = sprintf(buf, ZEND_LONG_FMT, min_idle_time);
5221     SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5222 
5223     // id
5224     zval *_id;
5225     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_id), _id) {
5226         convert_to_string(_id);
5227         SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_id), Z_STRLEN_P(_id))
5228     }
5229     ZEND_HASH_FOREACH_END();
5230 
5231     // options
5232     if (z_options && ZVAL_IS_ARRAY(z_options)) {
5233         ht_opt = Z_ARRVAL_P(z_options);
5234         // IDLE
5235         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("idle"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5236             SW_REDIS_COMMAND_ARGV_FILL("IDLE", 4)
5237             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5238             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5239             options_argc += 2;
5240         }
5241         // TIME
5242         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("time"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5243             SW_REDIS_COMMAND_ARGV_FILL("TIME", 4)
5244             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5245             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5246             options_argc += 2;
5247         }
5248         // RETRYCOUNT
5249         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("retrycount"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5250             SW_REDIS_COMMAND_ARGV_FILL("RETRYCOUNT", 10)
5251             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5252             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5253             options_argc += 2;
5254         }
5255         // FORCE
5256         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("force"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
5257             SW_REDIS_COMMAND_ARGV_FILL("FORCE", 5)
5258             options_argc++;
5259         }
5260         // JUSTID
5261         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("justid"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
5262             SW_REDIS_COMMAND_ARGV_FILL("JUSTID", 6)
5263             options_argc++;
5264         }
5265     }
5266 
5267     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
5268 
5269     redis_request(redis, argc, argv, argvlen, return_value);
5270 
5271     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5272         swoole_redis_handle_assoc_array_result(return_value, true);
5273     }
5274 
5275     SW_REDIS_COMMAND_FREE_ARGV
5276 }
5277 
PHP_METHOD(swoole_redis_coro,xAutoClaim)5278 static PHP_METHOD(swoole_redis_coro, xAutoClaim) {
5279     char *key, *group_name, *consumer_name, *start;
5280     size_t key_len, group_name_len, consumer_name_len, start_len;
5281     zend_long min_idle_time = 0;
5282     zval *z_options = nullptr, *z_ele;
5283     HashTable *ht_opt;
5284     int i = 0, argc = 6, options_argc = 0;
5285 
5286     if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssls|a", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len, &min_idle_time, &start, &start_len, &z_options) == FAILURE) {
5287         RETURN_FALSE;
5288     }
5289 
5290     SW_REDIS_COMMAND_CHECK
5291     char buf[32];
5292     size_t buf_len;
5293     SW_REDIS_COMMAND_ALLOC_ARGV
5294     SW_REDIS_COMMAND_ARGV_FILL("XAUTOCLAIM", 10)
5295     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5296     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5297     SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len)
5298     buf_len = sprintf(buf, ZEND_LONG_FMT, min_idle_time);
5299     SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5300     SW_REDIS_COMMAND_ARGV_FILL(start, start_len)
5301 
5302     // options
5303     if (z_options && ZVAL_IS_ARRAY(z_options)) {
5304         ht_opt = Z_ARRVAL_P(z_options);
5305         // COUNT
5306         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) {
5307             SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5)
5308             buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele));
5309             SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len)
5310             options_argc += 2;
5311         }
5312         // JUSTID
5313         if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("justid"))) && Z_TYPE_P(z_ele) == IS_TRUE) {
5314             SW_REDIS_COMMAND_ARGV_FILL("JUSTID", 6)
5315             options_argc++;
5316         }
5317     }
5318 
5319     SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc)
5320 
5321     redis_request(redis, argc, argv, argvlen, return_value);
5322 
5323     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5324         swoole_redis_handle_assoc_array_result(return_value, true);
5325     }
5326 
5327     SW_REDIS_COMMAND_FREE_ARGV
5328 }
5329 
PHP_METHOD(swoole_redis_coro,xInfoConsumers)5330 static PHP_METHOD(swoole_redis_coro, xInfoConsumers) {
5331     char *key, *group_name;
5332     size_t key_len, group_name_len;
5333 
5334     if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key, &key_len, &group_name, &group_name_len) == FAILURE) {
5335         return;
5336     }
5337 
5338     SW_REDIS_COMMAND_CHECK
5339     int i = 0, argc = 4;
5340     size_t argvlen[4];
5341     char *argv[4];
5342     SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5)
5343     SW_REDIS_COMMAND_ARGV_FILL("CONSUMERS", 9)
5344     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5345     SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len)
5346 
5347     redis_request(redis, argc, argv, argvlen, return_value);
5348 
5349     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5350         swoole_redis_handle_assoc_array_result(return_value, true);
5351     }
5352 }
5353 
PHP_METHOD(swoole_redis_coro,xInfoGroups)5354 static PHP_METHOD(swoole_redis_coro, xInfoGroups) {
5355     char *key;
5356     size_t key_len;
5357 
5358     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) {
5359         return;
5360     }
5361 
5362     SW_REDIS_COMMAND_CHECK
5363     int i = 0, argc = 3;
5364     size_t argvlen[3];
5365     char *argv[3];
5366     SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5)
5367     SW_REDIS_COMMAND_ARGV_FILL("GROUPS", 6)
5368     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5369 
5370     redis_request(redis, argc, argv, argvlen, return_value);
5371 
5372     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5373         swoole_redis_handle_assoc_array_result(return_value, true);
5374     }
5375 }
5376 
PHP_METHOD(swoole_redis_coro,xInfoStream)5377 static PHP_METHOD(swoole_redis_coro, xInfoStream) {
5378     char *key;
5379     size_t key_len;
5380 
5381     if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) {
5382         return;
5383     }
5384     SW_REDIS_COMMAND_CHECK
5385     int i = 0, argc = 3;
5386     size_t argvlen[3];
5387     char *argv[3];
5388     SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5)
5389     SW_REDIS_COMMAND_ARGV_FILL("STREAM", 6)
5390     SW_REDIS_COMMAND_ARGV_FILL(key, key_len)
5391 
5392     redis_request(redis, argc, argv, argvlen, return_value);
5393 
5394     if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) {
5395         swoole_redis_handle_assoc_array_result(return_value, true);
5396     }
5397 }
5398 
swoole_redis_coro_parse_result(RedisClient * redis,zval * return_value,redisReply * reply)5399 static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_value, redisReply *reply) {
5400     int j;
5401     zval _val, *val = &_val;
5402 
5403     switch (reply->type) {
5404     case REDIS_REPLY_INTEGER:
5405         ZVAL_LONG(return_value, reply->integer);
5406         break;
5407 
5408     case REDIS_REPLY_DOUBLE:
5409         ZVAL_DOUBLE(return_value, reply->dval);
5410         break;
5411 
5412     case REDIS_REPLY_BOOL:
5413         ZVAL_BOOL(return_value, reply->integer);
5414         break;
5415 
5416     case REDIS_REPLY_ERROR:
5417         ZVAL_FALSE(return_value);
5418         if (redis->context->err == 0) {
5419             if (strncmp(reply->str, "NOAUTH", 6) == 0) {
5420                 redis->context->err = SW_REDIS_ERR_NOAUTH;
5421             } else {
5422                 redis->context->err = SW_REDIS_ERR_OTHER;
5423             }
5424             size_t str_len = strlen(reply->str);
5425             memcpy(redis->context->errstr, reply->str, SW_MIN(str_len, sizeof(redis->context->errstr) - 1));
5426         }
5427         zend_update_property_long(
5428             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), redis->context->err);
5429         zend_update_property_long(swoole_redis_coro_ce,
5430                                   SW_Z8_OBJ_P(redis->zobject),
5431                                   ZEND_STRL("errCode"),
5432                                   sw_redis_convert_err(redis->context->err));
5433         zend_update_property_string(
5434             swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), redis->context->errstr);
5435         break;
5436 
5437     case REDIS_REPLY_STATUS:
5438         if (redis->context->err == 0) {
5439             if (reply->len > 0) {
5440                 if (strncmp(reply->str, "OK", 2) == 0) {
5441                     ZVAL_TRUE(return_value);
5442                     break;
5443                 }
5444                 long l;
5445                 if (strncmp(reply->str, "string", 6) == 0) {
5446                     l = SW_REDIS_TYPE_STRING;
5447                 } else if (strncmp(reply->str, "set", 3) == 0) {
5448                     l = SW_REDIS_TYPE_SET;
5449                 } else if (strncmp(reply->str, "list", 4) == 0) {
5450                     l = SW_REDIS_TYPE_LIST;
5451                 } else if (strncmp(reply->str, "zset", 4) == 0) {
5452                     l = SW_REDIS_TYPE_ZSET;
5453                 } else if (strncmp(reply->str, "hash", 4) == 0) {
5454                     l = SW_REDIS_TYPE_HASH;
5455                 } else {
5456                     l = SW_REDIS_TYPE_NOT_FOUND;
5457                 }
5458                 ZVAL_LONG(return_value, l);
5459             } else {
5460                 ZVAL_TRUE(return_value);
5461             }
5462         } else {
5463             ZVAL_FALSE(return_value);
5464             zend_update_property_long(
5465                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errType"), redis->context->err);
5466             zend_update_property_long(swoole_redis_coro_ce,
5467                                       SW_Z8_OBJ_P(redis->zobject),
5468                                       ZEND_STRL("errCode"),
5469                                       sw_redis_convert_err(redis->context->err));
5470             zend_update_property_string(
5471                 swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("errMsg"), redis->context->errstr);
5472         }
5473         break;
5474 
5475     case REDIS_REPLY_STRING:
5476         if (redis->serialize) {
5477             char *reserve_str = reply->str;
5478             php_unserialize_data_t s_ht;
5479             PHP_VAR_UNSERIALIZE_INIT(s_ht);
5480             if (!php_var_unserialize(return_value,
5481                                      (const unsigned char **) &reply->str,
5482                                      (const unsigned char *) reply->str + reply->len,
5483                                      &s_ht)) {
5484                 ZVAL_STRINGL(return_value, reply->str, reply->len);
5485             }
5486             PHP_VAR_UNSERIALIZE_DESTROY(s_ht);
5487             reply->str = reserve_str;
5488         } else {
5489             ZVAL_STRINGL(return_value, reply->str, reply->len);
5490         }
5491         break;
5492 
5493     case REDIS_REPLY_ARRAY:
5494         array_init(return_value);
5495         for (j = 0; j < (int) reply->elements; j++) {
5496             swoole_redis_coro_parse_result(redis, val, reply->element[j]);
5497             (void) add_next_index_zval(return_value, val);
5498         }
5499         break;
5500 
5501     case REDIS_REPLY_NIL:
5502     default:
5503         ZVAL_NULL(return_value);
5504         return;
5505     }
5506 }
5507