xref: /redis-3.2.3/src/rio.c (revision 80586cb8)
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 }
108