]> git.saurik.com Git - redis.git/blame_incremental - src/rio.c
Merge pull request #321 from mkwiatkowski/ticket227
[redis.git] / src / rio.c
... / ...
CommitLineData
1#include "fmacros.h"
2#include <string.h>
3#include <stdio.h>
4#include "rio.h"
5#include "util.h"
6
7/* Returns 1 or 0 for success/failure. */
8static size_t rioBufferWrite(rio *r, const void *buf, size_t len) {
9 r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);
10 r->io.buffer.pos += len;
11 return 1;
12}
13
14/* Returns 1 or 0 for success/failure. */
15static size_t rioBufferRead(rio *r, void *buf, size_t len) {
16 if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)
17 return 0; /* not enough buffer to return len bytes. */
18 memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);
19 r->io.buffer.pos += len;
20 return 1;
21}
22
23/* Returns read/write position in buffer. */
24static off_t rioBufferTell(rio *r) {
25 return r->io.buffer.pos;
26}
27
28/* Returns 1 or 0 for success/failure. */
29static size_t rioFileWrite(rio *r, const void *buf, size_t len) {
30 return fwrite(buf,len,1,r->io.file.fp);
31}
32
33/* Returns 1 or 0 for success/failure. */
34static size_t rioFileRead(rio *r, void *buf, size_t len) {
35 return fread(buf,len,1,r->io.file.fp);
36}
37
38/* Returns read/write position in file. */
39static off_t rioFileTell(rio *r) {
40 return ftello(r->io.file.fp);
41}
42
43static const rio rioBufferIO = {
44 rioBufferRead,
45 rioBufferWrite,
46 rioBufferTell,
47 { { NULL, 0 } } /* union for io-specific vars */
48};
49
50static const rio rioFileIO = {
51 rioFileRead,
52 rioFileWrite,
53 rioFileTell,
54 { { NULL, 0 } } /* union for io-specific vars */
55};
56
57void rioInitWithFile(rio *r, FILE *fp) {
58 *r = rioFileIO;
59 r->io.file.fp = fp;
60}
61
62void rioInitWithBuffer(rio *r, sds s) {
63 *r = rioBufferIO;
64 r->io.buffer.ptr = s;
65 r->io.buffer.pos = 0;
66}
67
68/* Write multi bulk count in the format: "*<count>\r\n". */
69size_t rioWriteBulkCount(rio *r, char prefix, int count) {
70 char cbuf[128];
71 int clen;
72
73 cbuf[0] = prefix;
74 clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);
75 cbuf[clen++] = '\r';
76 cbuf[clen++] = '\n';
77 if (rioWrite(r,cbuf,clen) == 0) return 0;
78 return clen;
79}
80
81/* Write binary-safe string in the format: "$<count>\r\n<payload>\r\n". */
82size_t rioWriteBulkString(rio *r, const char *buf, size_t len) {
83 size_t nwritten;
84
85 if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0;
86 if (len > 0 && rioWrite(r,buf,len) == 0) return 0;
87 if (rioWrite(r,"\r\n",2) == 0) return 0;
88 return nwritten+len+2;
89}
90
91/* Write a long long value in format: "$<count>\r\n<payload>\r\n". */
92size_t rioWriteBulkLongLong(rio *r, long long l) {
93 char lbuf[32];
94 unsigned int llen;
95
96 llen = ll2string(lbuf,sizeof(lbuf),l);
97 return rioWriteBulkString(r,lbuf,llen);
98}
99
100/* Write a double value in the format: "$<count>\r\n<payload>\r\n" */
101size_t rioWriteBulkDouble(rio *r, double d) {
102 char dbuf[128];
103 unsigned int dlen;
104
105 dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d);
106 return rioWriteBulkString(r,dbuf,dlen);
107}