summaryrefslogtreecommitdiff
path: root/src/rio.c
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2011-05-13 17:31:00 +0200
committerPieter Noordhuis <pcnoordhuis@gmail.com>2011-05-13 17:31:00 +0200
commit2e4b0e7727743cf03d25da0f535ecc02aad82d1f (patch)
tree83f5f5a143abccc328c5c9feb67b03d6118e0536 /src/rio.c
parent70bc5f7724364e93c63865c02d517bc0164274d9 (diff)
downloadredis-2e4b0e7727743cf03d25da0f535ecc02aad82d1f.tar.gz
Abstract file/buffer I/O to support in-memory serialization
Diffstat (limited to 'src/rio.c')
-rw-r--r--src/rio.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/rio.c b/src/rio.c
new file mode 100644
index 000000000..e69d939f2
--- /dev/null
+++ b/src/rio.c
@@ -0,0 +1,106 @@
+#include <string.h>
+#include "rio.h"
+#include "util.h"
+
+/* Returns 1 or 0 for success/failure. */
+static size_t rioBufferWrite(rio *r, const void *buf, size_t len) {
+ r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);
+ r->io.buffer.pos += len;
+ return len;
+}
+
+/* Returns 1 or 0 for success/failure. */
+static size_t rioBufferRead(rio *r, void *buf, size_t len) {
+ if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)
+ return 0;
+ memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);
+ r->io.buffer.pos += len;
+ return 1;
+}
+
+/* Returns read/write position in buffer. */
+static off_t rioBufferTell(rio *r) {
+ return r->io.buffer.pos;
+}
+
+/* Returns 1 or 0 for success/failure. */
+static size_t rioFileWrite(rio *r, const void *buf, size_t len) {
+ return fwrite(buf,len,1,r->io.file.fp);
+}
+
+/* Returns 1 or 0 for success/failure. */
+static size_t rioFileRead(rio *r, void *buf, size_t len) {
+ return fread(buf,len,1,r->io.file.fp);
+}
+
+/* Returns read/write position in file. */
+static off_t rioFileTell(rio *r) {
+ return ftello(r->io.file.fp);
+}
+
+static const rio rioBufferIO = {
+ rioBufferRead,
+ rioBufferWrite,
+ rioBufferTell,
+ { { NULL, 0 } } /* union for io-specific vars */
+};
+
+static const rio rioFileIO = {
+ rioFileRead,
+ rioFileWrite,
+ rioFileTell,
+ { { NULL, 0 } } /* union for io-specific vars */
+};
+
+rio rioInitWithFile(FILE *fp) {
+ rio r = rioFileIO;
+ r.io.file.fp = fp;
+ return r;
+}
+rio rioInitWithBuffer(sds s) {
+ rio r = rioBufferIO;
+ r.io.buffer.ptr = s;
+ r.io.buffer.pos = 0;
+ return r;
+}
+
+/* Write multi bulk count in the format: "*<count>\r\n". */
+size_t rioWriteBulkCount(rio *r, char prefix, int count) {
+ char cbuf[128];
+ int clen;
+
+ cbuf[0] = prefix;
+ clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);
+ cbuf[clen++] = '\r';
+ cbuf[clen++] = '\n';
+ if (rioWrite(r,cbuf,clen) == 0) return 0;
+ return clen;
+}
+
+/* Write binary-safe string in the format: "$<count>\r\n<payload>\r\n". */
+size_t rioWriteBulkString(rio *r, const char *buf, size_t len) {
+ size_t nwritten;
+
+ if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0;
+ if (len > 0 && rioWrite(r,buf,len) == 0) return 0;
+ if (rioWrite(r,"\r\n",2) == 0) return 0;
+ return nwritten+len+2;
+}
+
+/* Write a long long value in format: "$<count>\r\n<payload>\r\n". */
+size_t rioWriteBulkLongLong(rio *r, long long l) {
+ char lbuf[32];
+ unsigned int llen;
+
+ llen = ll2string(lbuf,sizeof(lbuf),l);
+ return rioWriteBulkString(r,lbuf,llen);
+}
+
+/* Write a double value in the format: "$<count>\r\n<payload>\r\n" */
+size_t rioWriteBulkDouble(rio *r, double d) {
+ char dbuf[128];
+ unsigned int dlen;
+
+ dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d);
+ return rioWriteBulkString(r,dbuf,dlen);
+}