]>
Commit | Line | Data |
---|---|---|
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. */ | |
8 | static 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. */ | |
15 | static 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. */ | |
24 | static off_t rioBufferTell(rio *r) { | |
25 | return r->io.buffer.pos; | |
26 | } | |
27 | ||
28 | /* Returns 1 or 0 for success/failure. */ | |
29 | static 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. */ | |
34 | static 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. */ | |
39 | static off_t rioFileTell(rio *r) { | |
40 | return ftello(r->io.file.fp); | |
41 | } | |
42 | ||
43 | static const rio rioBufferIO = { | |
44 | rioBufferRead, | |
45 | rioBufferWrite, | |
46 | rioBufferTell, | |
47 | { { NULL, 0 } } /* union for io-specific vars */ | |
48 | }; | |
49 | ||
50 | static const rio rioFileIO = { | |
51 | rioFileRead, | |
52 | rioFileWrite, | |
53 | rioFileTell, | |
54 | { { NULL, 0 } } /* union for io-specific vars */ | |
55 | }; | |
56 | ||
57 | void rioInitWithFile(rio *r, FILE *fp) { | |
58 | *r = rioFileIO; | |
59 | r->io.file.fp = fp; | |
60 | } | |
61 | ||
62 | void 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". */ | |
69 | size_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". */ | |
82 | size_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". */ | |
92 | size_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" */ | |
101 | size_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 | } |