read.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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 "read.h"
  44. #include "sds.h"
  45. #include "win32.h"
  46. static void __redisReaderSetError(redisReader *r, int type, const char *str) {
  47. size_t len;
  48. if (r->reply != NULL && r->fn && r->fn->freeObject) {
  49. r->fn->freeObject(r->reply);
  50. r->reply = NULL;
  51. }
  52. /* Clear input buffer on errors. */
  53. sdsfree(r->buf);
  54. r->buf = NULL;
  55. r->pos = r->len = 0;
  56. /* Reset task stack. */
  57. r->ridx = -1;
  58. /* Set error. */
  59. r->err = type;
  60. len = strlen(str);
  61. len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);
  62. memcpy(r->errstr,str,len);
  63. r->errstr[len] = '\0';
  64. }
  65. static size_t chrtos(char *buf, size_t size, char byte) {
  66. size_t len = 0;
  67. switch(byte) {
  68. case '\\':
  69. case '"':
  70. len = snprintf(buf,size,"\"\\%c\"",byte);
  71. break;
  72. case '\n': len = snprintf(buf,size,"\"\\n\""); break;
  73. case '\r': len = snprintf(buf,size,"\"\\r\""); break;
  74. case '\t': len = snprintf(buf,size,"\"\\t\""); break;
  75. case '\a': len = snprintf(buf,size,"\"\\a\""); break;
  76. case '\b': len = snprintf(buf,size,"\"\\b\""); break;
  77. default:
  78. if (isprint(byte))
  79. len = snprintf(buf,size,"\"%c\"",byte);
  80. else
  81. len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte);
  82. break;
  83. }
  84. return len;
  85. }
  86. static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {
  87. char cbuf[8], sbuf[128];
  88. chrtos(cbuf,sizeof(cbuf),byte);
  89. snprintf(sbuf,sizeof(sbuf),
  90. "Protocol error, got %s as reply type byte", cbuf);
  91. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);
  92. }
  93. static void __redisReaderSetErrorOOM(redisReader *r) {
  94. __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory");
  95. }
  96. static char *readBytes(redisReader *r, unsigned int bytes) {
  97. char *p;
  98. if (r->len-r->pos >= bytes) {
  99. p = r->buf+r->pos;
  100. r->pos += bytes;
  101. return p;
  102. }
  103. return NULL;
  104. }
  105. /* Find pointer to \r\n. */
  106. static char *seekNewline(char *s, size_t len) {
  107. int pos = 0;
  108. int _len = len-1;
  109. /* Position should be < len-1 because the character at "pos" should be
  110. * followed by a \n. Note that strchr cannot be used because it doesn't
  111. * allow to search a limited length and the buffer that is being searched
  112. * might not have a trailing NULL character. */
  113. while (pos < _len) {
  114. while(pos < _len && s[pos] != '\r') pos++;
  115. if (pos==_len) {
  116. /* Not found. */
  117. return NULL;
  118. } else {
  119. if (s[pos+1] == '\n') {
  120. /* Found. */
  121. return s+pos;
  122. } else {
  123. /* Continue searching. */
  124. pos++;
  125. }
  126. }
  127. }
  128. return NULL;
  129. }
  130. /* Convert a string into a long long. Returns REDIS_OK if the string could be
  131. * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value
  132. * will be set to the parsed value when appropriate.
  133. *
  134. * Note that this function demands that the string strictly represents
  135. * a long long: no spaces or other characters before or after the string
  136. * representing the number are accepted, nor zeroes at the start if not
  137. * for the string "0" representing the zero number.
  138. *
  139. * Because of its strictness, it is safe to use this function to check if
  140. * you can convert a string into a long long, and obtain back the string
  141. * from the number without any loss in the string representation. */
  142. static int string2ll(const char *s, size_t slen, long long *value) {
  143. const char *p = s;
  144. size_t plen = 0;
  145. int negative = 0;
  146. unsigned long long v;
  147. if (plen == slen)
  148. return REDIS_ERR;
  149. /* Special case: first and only digit is 0. */
  150. if (slen == 1 && p[0] == '0') {
  151. if (value != NULL) *value = 0;
  152. return REDIS_OK;
  153. }
  154. if (p[0] == '-') {
  155. negative = 1;
  156. p++; plen++;
  157. /* Abort on only a negative sign. */
  158. if (plen == slen)
  159. return REDIS_ERR;
  160. }
  161. /* First digit should be 1-9, otherwise the string should just be 0. */
  162. if (p[0] >= '1' && p[0] <= '9') {
  163. v = p[0]-'0';
  164. p++; plen++;
  165. } else if (p[0] == '0' && slen == 1) {
  166. *value = 0;
  167. return REDIS_OK;
  168. } else {
  169. return REDIS_ERR;
  170. }
  171. while (plen < slen && p[0] >= '0' && p[0] <= '9') {
  172. if (v > (ULLONG_MAX / 10)) /* Overflow. */
  173. return REDIS_ERR;
  174. v *= 10;
  175. if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */
  176. return REDIS_ERR;
  177. v += p[0]-'0';
  178. p++; plen++;
  179. }
  180. /* Return if not all bytes were used. */
  181. if (plen < slen)
  182. return REDIS_ERR;
  183. if (negative) {
  184. if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
  185. return REDIS_ERR;
  186. if (value != NULL) *value = -v;
  187. } else {
  188. if (v > LLONG_MAX) /* Overflow. */
  189. return REDIS_ERR;
  190. if (value != NULL) *value = v;
  191. }
  192. return REDIS_OK;
  193. }
  194. static char *readLine(redisReader *r, int *_len) {
  195. char *p, *s;
  196. int len;
  197. p = r->buf+r->pos;
  198. s = seekNewline(p,(r->len-r->pos));
  199. if (s != NULL) {
  200. len = s-(r->buf+r->pos);
  201. r->pos += len+2; /* skip \r\n */
  202. if (_len) *_len = len;
  203. return p;
  204. }
  205. return NULL;
  206. }
  207. static void moveToNextTask(redisReader *r) {
  208. redisReadTask *cur, *prv;
  209. while (r->ridx >= 0) {
  210. /* Return a.s.a.p. when the stack is now empty. */
  211. if (r->ridx == 0) {
  212. r->ridx--;
  213. return;
  214. }
  215. cur = &(r->rstack[r->ridx]);
  216. prv = &(r->rstack[r->ridx-1]);
  217. assert(prv->type == REDIS_REPLY_ARRAY ||
  218. prv->type == REDIS_REPLY_MAP ||
  219. prv->type == REDIS_REPLY_SET);
  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->rstack[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. if (r->fn && r->fn->createInteger) {
  240. long long v;
  241. if (string2ll(p, len, &v) == REDIS_ERR) {
  242. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  243. "Bad integer value");
  244. return REDIS_ERR;
  245. }
  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. if (r->fn && r->fn->createDouble) {
  252. char buf[326], *eptr;
  253. double d;
  254. if ((size_t)len >= sizeof(buf)) {
  255. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  256. "Double value is too large");
  257. return REDIS_ERR;
  258. }
  259. memcpy(buf,p,len);
  260. buf[len] = '\0';
  261. if (strcasecmp(buf,",inf") == 0) {
  262. d = INFINITY; /* Positive infinite. */
  263. } else if (strcasecmp(buf,",-inf") == 0) {
  264. d = -INFINITY; /* Nevative infinite. */
  265. } else {
  266. d = strtod((char*)buf,&eptr);
  267. if (buf[0] == '\0' || eptr[0] != '\0' || isnan(d)) {
  268. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  269. "Bad double value");
  270. return REDIS_ERR;
  271. }
  272. }
  273. obj = r->fn->createDouble(cur,d,buf,len);
  274. } else {
  275. obj = (void*)REDIS_REPLY_DOUBLE;
  276. }
  277. } else if (cur->type == REDIS_REPLY_NIL) {
  278. if (r->fn && r->fn->createNil)
  279. obj = r->fn->createNil(cur);
  280. else
  281. obj = (void*)REDIS_REPLY_NIL;
  282. } else if (cur->type == REDIS_REPLY_BOOL) {
  283. int bval = p[0] == 't' || p[0] == 'T';
  284. if (r->fn && r->fn->createBool)
  285. obj = r->fn->createBool(cur,bval);
  286. else
  287. obj = (void*)REDIS_REPLY_BOOL;
  288. } else {
  289. /* Type will be error or status. */
  290. if (r->fn && r->fn->createString)
  291. obj = r->fn->createString(cur,p,len);
  292. else
  293. obj = (void*)(size_t)(cur->type);
  294. }
  295. if (obj == NULL) {
  296. __redisReaderSetErrorOOM(r);
  297. return REDIS_ERR;
  298. }
  299. /* Set reply if this is the root object. */
  300. if (r->ridx == 0) r->reply = obj;
  301. moveToNextTask(r);
  302. return REDIS_OK;
  303. }
  304. return REDIS_ERR;
  305. }
  306. static int processBulkItem(redisReader *r) {
  307. redisReadTask *cur = &(r->rstack[r->ridx]);
  308. void *obj = NULL;
  309. char *p, *s;
  310. long long len;
  311. unsigned long bytelen;
  312. int success = 0;
  313. p = r->buf+r->pos;
  314. s = seekNewline(p,r->len-r->pos);
  315. if (s != NULL) {
  316. p = r->buf+r->pos;
  317. bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
  318. if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) {
  319. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  320. "Bad bulk string length");
  321. return REDIS_ERR;
  322. }
  323. if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) {
  324. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  325. "Bulk string length out of range");
  326. return REDIS_ERR;
  327. }
  328. if (len == -1) {
  329. /* The nil object can always be created. */
  330. if (r->fn && r->fn->createNil)
  331. obj = r->fn->createNil(cur);
  332. else
  333. obj = (void*)REDIS_REPLY_NIL;
  334. success = 1;
  335. } else {
  336. /* Only continue when the buffer contains the entire bulk item. */
  337. bytelen += len+2; /* include \r\n */
  338. if (r->pos+bytelen <= r->len) {
  339. if ((cur->type == REDIS_REPLY_VERB && len < 4) ||
  340. (cur->type == REDIS_REPLY_VERB && s[5] != ':'))
  341. {
  342. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  343. "Verbatim string 4 bytes of content type are "
  344. "missing or incorrectly encoded.");
  345. return REDIS_ERR;
  346. }
  347. if (r->fn && r->fn->createString)
  348. obj = r->fn->createString(cur,s+2,len);
  349. else
  350. obj = (void*)(long)cur->type;
  351. success = 1;
  352. }
  353. }
  354. /* Proceed when obj was created. */
  355. if (success) {
  356. if (obj == NULL) {
  357. __redisReaderSetErrorOOM(r);
  358. return REDIS_ERR;
  359. }
  360. r->pos += bytelen;
  361. /* Set reply if this is the root object. */
  362. if (r->ridx == 0) r->reply = obj;
  363. moveToNextTask(r);
  364. return REDIS_OK;
  365. }
  366. }
  367. return REDIS_ERR;
  368. }
  369. /* Process the array, map and set types. */
  370. static int processAggregateItem(redisReader *r) {
  371. redisReadTask *cur = &(r->rstack[r->ridx]);
  372. void *obj;
  373. char *p;
  374. long long elements;
  375. int root = 0, len;
  376. /* Set error for nested multi bulks with depth > 7 */
  377. if (r->ridx == 8) {
  378. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  379. "No support for nested multi bulk replies with depth > 7");
  380. return REDIS_ERR;
  381. }
  382. if ((p = readLine(r,&len)) != NULL) {
  383. if (string2ll(p, len, &elements) == REDIS_ERR) {
  384. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  385. "Bad multi-bulk length");
  386. return REDIS_ERR;
  387. }
  388. root = (r->ridx == 0);
  389. if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX)) {
  390. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  391. "Multi-bulk length out of range");
  392. return REDIS_ERR;
  393. }
  394. if (elements == -1) {
  395. if (r->fn && r->fn->createNil)
  396. obj = r->fn->createNil(cur);
  397. else
  398. obj = (void*)REDIS_REPLY_NIL;
  399. if (obj == NULL) {
  400. __redisReaderSetErrorOOM(r);
  401. return REDIS_ERR;
  402. }
  403. moveToNextTask(r);
  404. } else {
  405. if (cur->type == REDIS_REPLY_MAP) elements *= 2;
  406. if (r->fn && r->fn->createArray)
  407. obj = r->fn->createArray(cur,elements);
  408. else
  409. obj = (void*)(long)cur->type;
  410. if (obj == NULL) {
  411. __redisReaderSetErrorOOM(r);
  412. return REDIS_ERR;
  413. }
  414. /* Modify task stack when there are more than 0 elements. */
  415. if (elements > 0) {
  416. cur->elements = elements;
  417. cur->obj = obj;
  418. r->ridx++;
  419. r->rstack[r->ridx].type = -1;
  420. r->rstack[r->ridx].elements = -1;
  421. r->rstack[r->ridx].idx = 0;
  422. r->rstack[r->ridx].obj = NULL;
  423. r->rstack[r->ridx].parent = cur;
  424. r->rstack[r->ridx].privdata = r->privdata;
  425. } else {
  426. moveToNextTask(r);
  427. }
  428. }
  429. /* Set reply if this is the root object. */
  430. if (root) r->reply = obj;
  431. return REDIS_OK;
  432. }
  433. return REDIS_ERR;
  434. }
  435. static int processItem(redisReader *r) {
  436. redisReadTask *cur = &(r->rstack[r->ridx]);
  437. char *p;
  438. /* check if we need to read type */
  439. if (cur->type < 0) {
  440. if ((p = readBytes(r,1)) != NULL) {
  441. switch (p[0]) {
  442. case '-':
  443. cur->type = REDIS_REPLY_ERROR;
  444. break;
  445. case '+':
  446. cur->type = REDIS_REPLY_STATUS;
  447. break;
  448. case ':':
  449. cur->type = REDIS_REPLY_INTEGER;
  450. break;
  451. case ',':
  452. cur->type = REDIS_REPLY_DOUBLE;
  453. break;
  454. case '_':
  455. cur->type = REDIS_REPLY_NIL;
  456. break;
  457. case '$':
  458. cur->type = REDIS_REPLY_STRING;
  459. break;
  460. case '*':
  461. cur->type = REDIS_REPLY_ARRAY;
  462. break;
  463. case '%':
  464. cur->type = REDIS_REPLY_MAP;
  465. break;
  466. case '~':
  467. cur->type = REDIS_REPLY_SET;
  468. break;
  469. case '#':
  470. cur->type = REDIS_REPLY_BOOL;
  471. break;
  472. case '=':
  473. cur->type = REDIS_REPLY_VERB;
  474. break;
  475. default:
  476. __redisReaderSetErrorProtocolByte(r,*p);
  477. return REDIS_ERR;
  478. }
  479. } else {
  480. /* could not consume 1 byte */
  481. return REDIS_ERR;
  482. }
  483. }
  484. /* process typed item */
  485. switch(cur->type) {
  486. case REDIS_REPLY_ERROR:
  487. case REDIS_REPLY_STATUS:
  488. case REDIS_REPLY_INTEGER:
  489. case REDIS_REPLY_DOUBLE:
  490. case REDIS_REPLY_NIL:
  491. case REDIS_REPLY_BOOL:
  492. return processLineItem(r);
  493. case REDIS_REPLY_STRING:
  494. case REDIS_REPLY_VERB:
  495. return processBulkItem(r);
  496. case REDIS_REPLY_ARRAY:
  497. case REDIS_REPLY_MAP:
  498. case REDIS_REPLY_SET:
  499. return processAggregateItem(r);
  500. default:
  501. assert(NULL);
  502. return REDIS_ERR; /* Avoid warning. */
  503. }
  504. }
  505. redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) {
  506. redisReader *r;
  507. r = calloc(1,sizeof(redisReader));
  508. if (r == NULL)
  509. return NULL;
  510. r->fn = fn;
  511. r->buf = sdsempty();
  512. r->maxbuf = REDIS_READER_MAX_BUF;
  513. if (r->buf == NULL) {
  514. free(r);
  515. return NULL;
  516. }
  517. r->ridx = -1;
  518. return r;
  519. }
  520. void redisReaderFree(redisReader *r) {
  521. if (r == NULL)
  522. return;
  523. if (r->reply != NULL && r->fn && r->fn->freeObject)
  524. r->fn->freeObject(r->reply);
  525. sdsfree(r->buf);
  526. free(r);
  527. }
  528. int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
  529. sds newbuf;
  530. /* Return early when this reader is in an erroneous state. */
  531. if (r->err)
  532. return REDIS_ERR;
  533. /* Copy the provided buffer. */
  534. if (buf != NULL && len >= 1) {
  535. /* Destroy internal buffer when it is empty and is quite large. */
  536. if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
  537. sdsfree(r->buf);
  538. r->buf = sdsempty();
  539. r->pos = 0;
  540. /* r->buf should not be NULL since we just free'd a larger one. */
  541. assert(r->buf != NULL);
  542. }
  543. newbuf = sdscatlen(r->buf,buf,len);
  544. if (newbuf == NULL) {
  545. __redisReaderSetErrorOOM(r);
  546. return REDIS_ERR;
  547. }
  548. r->buf = newbuf;
  549. r->len = sdslen(r->buf);
  550. }
  551. return REDIS_OK;
  552. }
  553. int redisReaderGetReply(redisReader *r, void **reply) {
  554. /* Default target pointer to NULL. */
  555. if (reply != NULL)
  556. *reply = NULL;
  557. /* Return early when this reader is in an erroneous state. */
  558. if (r->err)
  559. return REDIS_ERR;
  560. /* When the buffer is empty, there will never be a reply. */
  561. if (r->len == 0)
  562. return REDIS_OK;
  563. /* Set first item to process when the stack is empty. */
  564. if (r->ridx == -1) {
  565. r->rstack[0].type = -1;
  566. r->rstack[0].elements = -1;
  567. r->rstack[0].idx = -1;
  568. r->rstack[0].obj = NULL;
  569. r->rstack[0].parent = NULL;
  570. r->rstack[0].privdata = r->privdata;
  571. r->ridx = 0;
  572. }
  573. /* Process items in reply. */
  574. while (r->ridx >= 0)
  575. if (processItem(r) != REDIS_OK)
  576. break;
  577. /* Return ASAP when an error occurred. */
  578. if (r->err)
  579. return REDIS_ERR;
  580. /* Discard part of the buffer when we've consumed at least 1k, to avoid
  581. * doing unnecessary calls to memmove() in sds.c. */
  582. if (r->pos >= 1024) {
  583. sdsrange(r->buf,r->pos,-1);
  584. r->pos = 0;
  585. r->len = sdslen(r->buf);
  586. }
  587. /* Emit a reply when there is one. */
  588. if (r->ridx == -1) {
  589. if (reply != NULL) {
  590. *reply = r->reply;
  591. } else if (r->reply != NULL && r->fn && r->fn->freeObject) {
  592. r->fn->freeObject(r->reply);
  593. }
  594. r->reply = NULL;
  595. }
  596. return REDIS_OK;
  597. }