read.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /*
  2. * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
  3. * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * * Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of Redis nor the names of its contributors may be used
  16. * to endorse or promote products derived from this software without
  17. * specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "fmacros.h"
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #ifndef _MSC_VER
  35. #include <unistd.h>
  36. #include <strings.h>
  37. #endif
  38. #include <assert.h>
  39. #include <errno.h>
  40. #include <ctype.h>
  41. #include <limits.h>
  42. #include <math.h>
  43. #include "alloc.h"
  44. #include "read.h"
  45. #include "sds.h"
  46. #include "win32.h"
  47. /* Initial size of our nested reply stack and how much we grow it when needd */
  48. #define REDIS_READER_STACK_SIZE 9
  49. static void __redisReaderSetError(redisReader *r, int type, const char *str) {
  50. size_t len;
  51. if (r->reply != NULL && r->fn && r->fn->freeObject) {
  52. r->fn->freeObject(r->reply);
  53. r->reply = NULL;
  54. }
  55. /* Clear input buffer on errors. */
  56. sdsfree(r->buf);
  57. r->buf = NULL;
  58. r->pos = r->len = 0;
  59. /* Reset task stack. */
  60. r->ridx = -1;
  61. /* Set error. */
  62. r->err = type;
  63. len = strlen(str);
  64. len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);
  65. memcpy(r->errstr,str,len);
  66. r->errstr[len] = '\0';
  67. }
  68. static size_t chrtos(char *buf, size_t size, char byte) {
  69. size_t len = 0;
  70. switch(byte) {
  71. case '\\':
  72. case '"':
  73. len = snprintf(buf,size,"\"\\%c\"",byte);
  74. break;
  75. case '\n': len = snprintf(buf,size,"\"\\n\""); break;
  76. case '\r': len = snprintf(buf,size,"\"\\r\""); break;
  77. case '\t': len = snprintf(buf,size,"\"\\t\""); break;
  78. case '\a': len = snprintf(buf,size,"\"\\a\""); break;
  79. case '\b': len = snprintf(buf,size,"\"\\b\""); break;
  80. default:
  81. if (isprint(byte))
  82. len = snprintf(buf,size,"\"%c\"",byte);
  83. else
  84. len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte);
  85. break;
  86. }
  87. return len;
  88. }
  89. static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {
  90. char cbuf[8], sbuf[128];
  91. chrtos(cbuf,sizeof(cbuf),byte);
  92. snprintf(sbuf,sizeof(sbuf),
  93. "Protocol error, got %s as reply type byte", cbuf);
  94. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);
  95. }
  96. static void __redisReaderSetErrorOOM(redisReader *r) {
  97. __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory");
  98. }
  99. static char *readBytes(redisReader *r, unsigned int bytes) {
  100. char *p;
  101. if (r->len-r->pos >= bytes) {
  102. p = r->buf+r->pos;
  103. r->pos += bytes;
  104. return p;
  105. }
  106. return NULL;
  107. }
  108. /* Find pointer to \r\n. */
  109. static char *seekNewline(char *s, size_t len) {
  110. char *ret;
  111. /* We cannot match with fewer than 2 bytes */
  112. if (len < 2)
  113. return NULL;
  114. /* Search up to len - 1 characters */
  115. len--;
  116. /* Look for the \r */
  117. while ((ret = memchr(s, '\r', len)) != NULL) {
  118. if (ret[1] == '\n') {
  119. /* Found. */
  120. break;
  121. }
  122. /* Continue searching. */
  123. ret++;
  124. len -= ret - s;
  125. s = ret;
  126. }
  127. return ret;
  128. }
  129. /* Convert a string into a long long. Returns REDIS_OK if the string could be
  130. * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value
  131. * will be set to the parsed value when appropriate.
  132. *
  133. * Note that this function demands that the string strictly represents
  134. * a long long: no spaces or other characters before or after the string
  135. * representing the number are accepted, nor zeroes at the start if not
  136. * for the string "0" representing the zero number.
  137. *
  138. * Because of its strictness, it is safe to use this function to check if
  139. * you can convert a string into a long long, and obtain back the string
  140. * from the number without any loss in the string representation. */
  141. static int string2ll(const char *s, size_t slen, long long *value) {
  142. const char *p = s;
  143. size_t plen = 0;
  144. int negative = 0;
  145. unsigned long long v;
  146. if (plen == slen)
  147. return REDIS_ERR;
  148. /* Special case: first and only digit is 0. */
  149. if (slen == 1 && p[0] == '0') {
  150. if (value != NULL) *value = 0;
  151. return REDIS_OK;
  152. }
  153. if (p[0] == '-') {
  154. negative = 1;
  155. p++; plen++;
  156. /* Abort on only a negative sign. */
  157. if (plen == slen)
  158. return REDIS_ERR;
  159. }
  160. /* First digit should be 1-9, otherwise the string should just be 0. */
  161. if (p[0] >= '1' && p[0] <= '9') {
  162. v = p[0]-'0';
  163. p++; plen++;
  164. } else if (p[0] == '0' && slen == 1) {
  165. *value = 0;
  166. return REDIS_OK;
  167. } else {
  168. return REDIS_ERR;
  169. }
  170. while (plen < slen && p[0] >= '0' && p[0] <= '9') {
  171. if (v > (ULLONG_MAX / 10)) /* Overflow. */
  172. return REDIS_ERR;
  173. v *= 10;
  174. if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */
  175. return REDIS_ERR;
  176. v += p[0]-'0';
  177. p++; plen++;
  178. }
  179. /* Return if not all bytes were used. */
  180. if (plen < slen)
  181. return REDIS_ERR;
  182. if (negative) {
  183. if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
  184. return REDIS_ERR;
  185. if (value != NULL) *value = -v;
  186. } else {
  187. if (v > LLONG_MAX) /* Overflow. */
  188. return REDIS_ERR;
  189. if (value != NULL) *value = v;
  190. }
  191. return REDIS_OK;
  192. }
  193. static char *readLine(redisReader *r, int *_len) {
  194. char *p, *s;
  195. int len;
  196. p = r->buf+r->pos;
  197. s = seekNewline(p,(r->len-r->pos));
  198. if (s != NULL) {
  199. len = s-(r->buf+r->pos);
  200. r->pos += len+2; /* skip \r\n */
  201. if (_len) *_len = len;
  202. return p;
  203. }
  204. return NULL;
  205. }
  206. static void moveToNextTask(redisReader *r) {
  207. redisReadTask *cur, *prv;
  208. while (r->ridx >= 0) {
  209. /* Return a.s.a.p. when the stack is now empty. */
  210. if (r->ridx == 0) {
  211. r->ridx--;
  212. return;
  213. }
  214. cur = r->task[r->ridx];
  215. prv = r->task[r->ridx-1];
  216. assert(prv->type == REDIS_REPLY_ARRAY ||
  217. prv->type == REDIS_REPLY_MAP ||
  218. prv->type == REDIS_REPLY_SET ||
  219. prv->type == REDIS_REPLY_PUSH);
  220. if (cur->idx == prv->elements-1) {
  221. r->ridx--;
  222. } else {
  223. /* Reset the type because the next item can be anything */
  224. assert(cur->idx < prv->elements);
  225. cur->type = -1;
  226. cur->elements = -1;
  227. cur->idx++;
  228. return;
  229. }
  230. }
  231. }
  232. static int processLineItem(redisReader *r) {
  233. redisReadTask *cur = r->task[r->ridx];
  234. void *obj;
  235. char *p;
  236. int len;
  237. if ((p = readLine(r,&len)) != NULL) {
  238. if (cur->type == REDIS_REPLY_INTEGER) {
  239. long long v;
  240. if (string2ll(p, len, &v) == REDIS_ERR) {
  241. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  242. "Bad integer value");
  243. return REDIS_ERR;
  244. }
  245. if (r->fn && r->fn->createInteger) {
  246. obj = r->fn->createInteger(cur,v);
  247. } else {
  248. obj = (void*)REDIS_REPLY_INTEGER;
  249. }
  250. } else if (cur->type == REDIS_REPLY_DOUBLE) {
  251. char buf[326], *eptr;
  252. double d;
  253. if ((size_t)len >= sizeof(buf)) {
  254. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  255. "Double value is too large");
  256. return REDIS_ERR;
  257. }
  258. memcpy(buf,p,len);
  259. buf[len] = '\0';
  260. if (len == 3 && strcasecmp(buf,"inf") == 0) {
  261. d = INFINITY; /* Positive infinite. */
  262. } else if (len == 4 && strcasecmp(buf,"-inf") == 0) {
  263. d = -INFINITY; /* Negative infinite. */
  264. } else if ((len == 3 && strcasecmp(buf,"nan") == 0) ||
  265. (len == 4 && strcasecmp(buf, "-nan") == 0)) {
  266. d = NAN; /* nan. */
  267. } else {
  268. d = strtod((char*)buf,&eptr);
  269. /* RESP3 only allows "inf", "-inf", and finite values, while
  270. * strtod() allows other variations on infinity,
  271. * etc. We explicity handle our two allowed infinite cases and NaN
  272. * above, so strtod() should only result in finite values. */
  273. if (buf[0] == '\0' || eptr != &buf[len] || !isfinite(d)) {
  274. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  275. "Bad double value");
  276. return REDIS_ERR;
  277. }
  278. }
  279. if (r->fn && r->fn->createDouble) {
  280. obj = r->fn->createDouble(cur,d,buf,len);
  281. } else {
  282. obj = (void*)REDIS_REPLY_DOUBLE;
  283. }
  284. } else if (cur->type == REDIS_REPLY_NIL) {
  285. if (len != 0) {
  286. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  287. "Bad nil value");
  288. return REDIS_ERR;
  289. }
  290. if (r->fn && r->fn->createNil)
  291. obj = r->fn->createNil(cur);
  292. else
  293. obj = (void*)REDIS_REPLY_NIL;
  294. } else if (cur->type == REDIS_REPLY_BOOL) {
  295. int bval;
  296. if (len != 1 || !strchr("tTfF", p[0])) {
  297. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  298. "Bad bool value");
  299. return REDIS_ERR;
  300. }
  301. bval = p[0] == 't' || p[0] == 'T';
  302. if (r->fn && r->fn->createBool)
  303. obj = r->fn->createBool(cur,bval);
  304. else
  305. obj = (void*)REDIS_REPLY_BOOL;
  306. } else if (cur->type == REDIS_REPLY_BIGNUM) {
  307. /* Ensure all characters are decimal digits (with possible leading
  308. * minus sign). */
  309. for (int i = 0; i < len; i++) {
  310. /* XXX Consider: Allow leading '+'? Error on leading '0's? */
  311. if (i == 0 && p[0] == '-') continue;
  312. if (p[i] < '0' || p[i] > '9') {
  313. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  314. "Bad bignum value");
  315. return REDIS_ERR;
  316. }
  317. }
  318. if (r->fn && r->fn->createString)
  319. obj = r->fn->createString(cur,p,len);
  320. else
  321. obj = (void*)REDIS_REPLY_BIGNUM;
  322. } else {
  323. /* Type will be error or status. */
  324. for (int i = 0; i < len; i++) {
  325. if (p[i] == '\r' || p[i] == '\n') {
  326. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  327. "Bad simple string value");
  328. return REDIS_ERR;
  329. }
  330. }
  331. if (r->fn && r->fn->createString)
  332. obj = r->fn->createString(cur,p,len);
  333. else
  334. obj = (void*)(uintptr_t)(cur->type);
  335. }
  336. if (obj == NULL) {
  337. __redisReaderSetErrorOOM(r);
  338. return REDIS_ERR;
  339. }
  340. /* Set reply if this is the root object. */
  341. if (r->ridx == 0) r->reply = obj;
  342. moveToNextTask(r);
  343. return REDIS_OK;
  344. }
  345. return REDIS_ERR;
  346. }
  347. static int processBulkItem(redisReader *r) {
  348. redisReadTask *cur = r->task[r->ridx];
  349. void *obj = NULL;
  350. char *p, *s;
  351. long long len;
  352. unsigned long bytelen;
  353. int success = 0;
  354. p = r->buf+r->pos;
  355. s = seekNewline(p,r->len-r->pos);
  356. if (s != NULL) {
  357. p = r->buf+r->pos;
  358. bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
  359. if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) {
  360. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  361. "Bad bulk string length");
  362. return REDIS_ERR;
  363. }
  364. if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) {
  365. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  366. "Bulk string length out of range");
  367. return REDIS_ERR;
  368. }
  369. if (len == -1) {
  370. /* The nil object can always be created. */
  371. if (r->fn && r->fn->createNil)
  372. obj = r->fn->createNil(cur);
  373. else
  374. obj = (void*)REDIS_REPLY_NIL;
  375. success = 1;
  376. } else {
  377. /* Only continue when the buffer contains the entire bulk item. */
  378. bytelen += len+2; /* include \r\n */
  379. if (r->pos+bytelen <= r->len) {
  380. if ((cur->type == REDIS_REPLY_VERB && len < 4) ||
  381. (cur->type == REDIS_REPLY_VERB && s[5] != ':'))
  382. {
  383. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  384. "Verbatim string 4 bytes of content type are "
  385. "missing or incorrectly encoded.");
  386. return REDIS_ERR;
  387. }
  388. if (r->fn && r->fn->createString)
  389. obj = r->fn->createString(cur,s+2,len);
  390. else
  391. obj = (void*)(uintptr_t)cur->type;
  392. success = 1;
  393. }
  394. }
  395. /* Proceed when obj was created. */
  396. if (success) {
  397. if (obj == NULL) {
  398. __redisReaderSetErrorOOM(r);
  399. return REDIS_ERR;
  400. }
  401. r->pos += bytelen;
  402. /* Set reply if this is the root object. */
  403. if (r->ridx == 0) r->reply = obj;
  404. moveToNextTask(r);
  405. return REDIS_OK;
  406. }
  407. }
  408. return REDIS_ERR;
  409. }
  410. static int redisReaderGrow(redisReader *r) {
  411. redisReadTask **aux;
  412. int newlen;
  413. /* Grow our stack size */
  414. newlen = r->tasks + REDIS_READER_STACK_SIZE;
  415. aux = hi_realloc(r->task, sizeof(*r->task) * newlen);
  416. if (aux == NULL)
  417. goto oom;
  418. r->task = aux;
  419. /* Allocate new tasks */
  420. for (; r->tasks < newlen; r->tasks++) {
  421. r->task[r->tasks] = hi_calloc(1, sizeof(**r->task));
  422. if (r->task[r->tasks] == NULL)
  423. goto oom;
  424. }
  425. return REDIS_OK;
  426. oom:
  427. __redisReaderSetErrorOOM(r);
  428. return REDIS_ERR;
  429. }
  430. /* Process the array, map and set types. */
  431. static int processAggregateItem(redisReader *r) {
  432. redisReadTask *cur = r->task[r->ridx];
  433. void *obj;
  434. char *p;
  435. long long elements;
  436. int root = 0, len;
  437. if (r->ridx == r->tasks - 1) {
  438. if (redisReaderGrow(r) == REDIS_ERR)
  439. return REDIS_ERR;
  440. }
  441. if ((p = readLine(r,&len)) != NULL) {
  442. if (string2ll(p, len, &elements) == REDIS_ERR) {
  443. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  444. "Bad multi-bulk length");
  445. return REDIS_ERR;
  446. }
  447. root = (r->ridx == 0);
  448. if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX) ||
  449. (r->maxelements > 0 && elements > r->maxelements))
  450. {
  451. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  452. "Multi-bulk length out of range");
  453. return REDIS_ERR;
  454. }
  455. if (elements == -1) {
  456. if (r->fn && r->fn->createNil)
  457. obj = r->fn->createNil(cur);
  458. else
  459. obj = (void*)REDIS_REPLY_NIL;
  460. if (obj == NULL) {
  461. __redisReaderSetErrorOOM(r);
  462. return REDIS_ERR;
  463. }
  464. moveToNextTask(r);
  465. } else {
  466. if (cur->type == REDIS_REPLY_MAP) elements *= 2;
  467. if (r->fn && r->fn->createArray)
  468. obj = r->fn->createArray(cur,elements);
  469. else
  470. obj = (void*)(uintptr_t)cur->type;
  471. if (obj == NULL) {
  472. __redisReaderSetErrorOOM(r);
  473. return REDIS_ERR;
  474. }
  475. /* Modify task stack when there are more than 0 elements. */
  476. if (elements > 0) {
  477. cur->elements = elements;
  478. cur->obj = obj;
  479. r->ridx++;
  480. r->task[r->ridx]->type = -1;
  481. r->task[r->ridx]->elements = -1;
  482. r->task[r->ridx]->idx = 0;
  483. r->task[r->ridx]->obj = NULL;
  484. r->task[r->ridx]->parent = cur;
  485. r->task[r->ridx]->privdata = r->privdata;
  486. } else {
  487. moveToNextTask(r);
  488. }
  489. }
  490. /* Set reply if this is the root object. */
  491. if (root) r->reply = obj;
  492. return REDIS_OK;
  493. }
  494. return REDIS_ERR;
  495. }
  496. static int processItem(redisReader *r) {
  497. redisReadTask *cur = r->task[r->ridx];
  498. char *p;
  499. /* check if we need to read type */
  500. if (cur->type < 0) {
  501. if ((p = readBytes(r,1)) != NULL) {
  502. switch (p[0]) {
  503. case '-':
  504. cur->type = REDIS_REPLY_ERROR;
  505. break;
  506. case '+':
  507. cur->type = REDIS_REPLY_STATUS;
  508. break;
  509. case ':':
  510. cur->type = REDIS_REPLY_INTEGER;
  511. break;
  512. case ',':
  513. cur->type = REDIS_REPLY_DOUBLE;
  514. break;
  515. case '_':
  516. cur->type = REDIS_REPLY_NIL;
  517. break;
  518. case '$':
  519. cur->type = REDIS_REPLY_STRING;
  520. break;
  521. case '*':
  522. cur->type = REDIS_REPLY_ARRAY;
  523. break;
  524. case '%':
  525. cur->type = REDIS_REPLY_MAP;
  526. break;
  527. case '~':
  528. cur->type = REDIS_REPLY_SET;
  529. break;
  530. case '#':
  531. cur->type = REDIS_REPLY_BOOL;
  532. break;
  533. case '=':
  534. cur->type = REDIS_REPLY_VERB;
  535. break;
  536. case '>':
  537. cur->type = REDIS_REPLY_PUSH;
  538. break;
  539. case '(':
  540. cur->type = REDIS_REPLY_BIGNUM;
  541. break;
  542. default:
  543. __redisReaderSetErrorProtocolByte(r,*p);
  544. return REDIS_ERR;
  545. }
  546. } else {
  547. /* could not consume 1 byte */
  548. return REDIS_ERR;
  549. }
  550. }
  551. /* process typed item */
  552. switch(cur->type) {
  553. case REDIS_REPLY_ERROR:
  554. case REDIS_REPLY_STATUS:
  555. case REDIS_REPLY_INTEGER:
  556. case REDIS_REPLY_DOUBLE:
  557. case REDIS_REPLY_NIL:
  558. case REDIS_REPLY_BOOL:
  559. case REDIS_REPLY_BIGNUM:
  560. return processLineItem(r);
  561. case REDIS_REPLY_STRING:
  562. case REDIS_REPLY_VERB:
  563. return processBulkItem(r);
  564. case REDIS_REPLY_ARRAY:
  565. case REDIS_REPLY_MAP:
  566. case REDIS_REPLY_SET:
  567. case REDIS_REPLY_PUSH:
  568. return processAggregateItem(r);
  569. default:
  570. assert(NULL);
  571. return REDIS_ERR; /* Avoid warning. */
  572. }
  573. }
  574. redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) {
  575. redisReader *r;
  576. r = hi_calloc(1,sizeof(redisReader));
  577. if (r == NULL)
  578. return NULL;
  579. r->buf = sdsempty();
  580. if (r->buf == NULL)
  581. goto oom;
  582. r->task = hi_calloc(REDIS_READER_STACK_SIZE, sizeof(*r->task));
  583. if (r->task == NULL)
  584. goto oom;
  585. for (; r->tasks < REDIS_READER_STACK_SIZE; r->tasks++) {
  586. r->task[r->tasks] = hi_calloc(1, sizeof(**r->task));
  587. if (r->task[r->tasks] == NULL)
  588. goto oom;
  589. }
  590. r->fn = fn;
  591. r->maxbuf = REDIS_READER_MAX_BUF;
  592. r->maxelements = REDIS_READER_MAX_ARRAY_ELEMENTS;
  593. r->ridx = -1;
  594. return r;
  595. oom:
  596. redisReaderFree(r);
  597. return NULL;
  598. }
  599. void redisReaderFree(redisReader *r) {
  600. if (r == NULL)
  601. return;
  602. if (r->reply != NULL && r->fn && r->fn->freeObject)
  603. r->fn->freeObject(r->reply);
  604. if (r->task) {
  605. /* We know r->task[i] is allocated if i < r->tasks */
  606. for (int i = 0; i < r->tasks; i++) {
  607. hi_free(r->task[i]);
  608. }
  609. hi_free(r->task);
  610. }
  611. sdsfree(r->buf);
  612. hi_free(r);
  613. }
  614. int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
  615. sds newbuf;
  616. /* Return early when this reader is in an erroneous state. */
  617. if (r->err)
  618. return REDIS_ERR;
  619. /* Copy the provided buffer. */
  620. if (buf != NULL && len >= 1) {
  621. /* Destroy internal buffer when it is empty and is quite large. */
  622. if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
  623. sdsfree(r->buf);
  624. r->buf = sdsempty();
  625. if (r->buf == 0) goto oom;
  626. r->pos = 0;
  627. }
  628. newbuf = sdscatlen(r->buf,buf,len);
  629. if (newbuf == NULL) goto oom;
  630. r->buf = newbuf;
  631. r->len = sdslen(r->buf);
  632. }
  633. return REDIS_OK;
  634. oom:
  635. __redisReaderSetErrorOOM(r);
  636. return REDIS_ERR;
  637. }
  638. int redisReaderGetReply(redisReader *r, void **reply) {
  639. /* Default target pointer to NULL. */
  640. if (reply != NULL)
  641. *reply = NULL;
  642. /* Return early when this reader is in an erroneous state. */
  643. if (r->err)
  644. return REDIS_ERR;
  645. /* When the buffer is empty, there will never be a reply. */
  646. if (r->len == 0)
  647. return REDIS_OK;
  648. /* Set first item to process when the stack is empty. */
  649. if (r->ridx == -1) {
  650. r->task[0]->type = -1;
  651. r->task[0]->elements = -1;
  652. r->task[0]->idx = -1;
  653. r->task[0]->obj = NULL;
  654. r->task[0]->parent = NULL;
  655. r->task[0]->privdata = r->privdata;
  656. r->ridx = 0;
  657. }
  658. /* Process items in reply. */
  659. while (r->ridx >= 0)
  660. if (processItem(r) != REDIS_OK)
  661. break;
  662. /* Return ASAP when an error occurred. */
  663. if (r->err)
  664. return REDIS_ERR;
  665. /* Discard part of the buffer when we've consumed at least 1k, to avoid
  666. * doing unnecessary calls to memmove() in sds.c. */
  667. if (r->pos >= 1024) {
  668. if (sdsrange(r->buf,r->pos,-1) < 0) return REDIS_ERR;
  669. r->pos = 0;
  670. r->len = sdslen(r->buf);
  671. }
  672. /* Emit a reply when there is one. */
  673. if (r->ridx == -1) {
  674. if (reply != NULL) {
  675. *reply = r->reply;
  676. } else if (r->reply != NULL && r->fn && r->fn->freeObject) {
  677. r->fn->freeObject(r->reply);
  678. }
  679. r->reply = NULL;
  680. }
  681. return REDIS_OK;
  682. }