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