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