+void _addReplyObjectToList(redisClient *c, robj *obj) {
+ redisAssert(obj->type == REDIS_STRING &&
+ obj->encoding == REDIS_ENCODING_RAW);
+ listAddNodeTail(c->reply,obj);
+}
+
+void _ensureBufferInReplyList(redisClient *c) {
+ sds buffer = sdsnewlen(NULL,REDIS_REPLY_CHUNK_SIZE);
+ sdsupdatelen(buffer); /* sdsnewlen expects non-empty string */
+ listAddNodeTail(c->reply,createObject(REDIS_REPLY_NODE,buffer));
+}
+
+void _addReplyStringToBuffer(redisClient *c, char *s, size_t len) {
+ size_t available = 0;
+ redisAssert(len < REDIS_REPLY_CHUNK_THRESHOLD);
+ if (listLength(c->reply) > 0) {
+ robj *o = listNodeValue(listLast(c->reply));
+
+ /* Make sure to append to a reply node with enough bytes available. */
+ if (o->type == REDIS_REPLY_NODE) available = sdsavail(o->ptr);
+ if (o->type != REDIS_REPLY_NODE || len > available) {
+ _ensureBufferInReplyList(c);
+ _addReplyStringToBuffer(c,s,len);
+ } else {
+ o->ptr = sdscatlen(o->ptr,s,len);
+ }
+ } else {
+ available = c->buflen-c->bufpos;
+ if (len > available) {
+ _ensureBufferInReplyList(c);
+ _addReplyStringToBuffer(c,s,len);
+ } else {
+ memcpy(c->buf+c->bufpos,s,len);
+ c->bufpos += len;
+ }
+ }
+}
+
+void addReply(redisClient *c, robj *obj) {
+ if (_ensureFileEvent(c) != REDIS_OK) return;