]>
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; | |
9 | return len; | |
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) | |
15 | return 0; | |
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 | ||
55 | rio rioInitWithFile(FILE *fp) { | |
56 | rio r = rioFileIO; | |
57 | r.io.file.fp = fp; | |
58 | return r; | |
59 | } | |
60 | rio rioInitWithBuffer(sds s) { | |
61 | rio r = rioBufferIO; | |
62 | r.io.buffer.ptr = s; | |
63 | r.io.buffer.pos = 0; | |
64 | return r; | |
65 | } | |
66 | ||
67 | /* Write multi bulk count in the format: "*<count>\r\n". */ | |
68 | size_t rioWriteBulkCount(rio *r, char prefix, int count) { | |
69 | char cbuf[128]; | |
70 | int clen; | |
71 | ||
72 | cbuf[0] = prefix; | |
73 | clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count); | |
74 | cbuf[clen++] = '\r'; | |
75 | cbuf[clen++] = '\n'; | |
76 | if (rioWrite(r,cbuf,clen) == 0) return 0; | |
77 | return clen; | |
78 | } | |
79 | ||
80 | /* Write binary-safe string in the format: "$<count>\r\n<payload>\r\n". */ | |
81 | size_t rioWriteBulkString(rio *r, const char *buf, size_t len) { | |
82 | size_t nwritten; | |
83 | ||
84 | if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0; | |
85 | if (len > 0 && rioWrite(r,buf,len) == 0) return 0; | |
86 | if (rioWrite(r,"\r\n",2) == 0) return 0; | |
87 | return nwritten+len+2; | |
88 | } | |
89 | ||
90 | /* Write a long long value in format: "$<count>\r\n<payload>\r\n". */ | |
91 | size_t rioWriteBulkLongLong(rio *r, long long l) { | |
92 | char lbuf[32]; | |
93 | unsigned int llen; | |
94 | ||
95 | llen = ll2string(lbuf,sizeof(lbuf),l); | |
96 | return rioWriteBulkString(r,lbuf,llen); | |
97 | } | |
98 | ||
99 | /* Write a double value in the format: "$<count>\r\n<payload>\r\n" */ | |
100 | size_t rioWriteBulkDouble(rio *r, double d) { | |
101 | char dbuf[128]; | |
102 | unsigned int dlen; | |
103 | ||
104 | dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d); | |
105 | return rioWriteBulkString(r,dbuf,dlen); | |
106 | } |