diff options
author | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2011-05-13 17:31:00 +0200 |
---|---|---|
committer | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2011-05-13 17:31:00 +0200 |
commit | 2e4b0e7727743cf03d25da0f535ecc02aad82d1f (patch) | |
tree | 83f5f5a143abccc328c5c9feb67b03d6118e0536 /src/rio.c | |
parent | 70bc5f7724364e93c63865c02d517bc0164274d9 (diff) | |
download | redis-2e4b0e7727743cf03d25da0f535ecc02aad82d1f.tar.gz |
Abstract file/buffer I/O to support in-memory serialization
Diffstat (limited to 'src/rio.c')
-rw-r--r-- | src/rio.c | 106 |
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); +} |