2011-10-23 04:57:01 -04:00
|
|
|
#include "fmacros.h"
|
2011-05-13 11:31:00 -04:00
|
|
|
#include <string.h>
|
2011-10-23 04:57:01 -04:00
|
|
|
#include <stdio.h>
|
2011-05-13 11:31:00 -04:00
|
|
|
#include "rio.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
/* Returns 1 or 0 for success/failure. */
|
|
|
|
static size_t rioBufferWrite(rio *r, const void *buf, size_t len) {
|
|
|
|
r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);
|
|
|
|
r->io.buffer.pos += len;
|
2011-09-22 09:54:08 -04:00
|
|
|
return 1;
|
2011-05-13 11:31:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns 1 or 0 for success/failure. */
|
|
|
|
static size_t rioBufferRead(rio *r, void *buf, size_t len) {
|
|
|
|
if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)
|
2011-09-22 09:54:08 -04:00
|
|
|
return 0; /* not enough buffer to return len bytes. */
|
2011-05-13 11:31:00 -04:00
|
|
|
memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);
|
|
|
|
r->io.buffer.pos += len;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns read/write position in buffer. */
|
|
|
|
static off_t rioBufferTell(rio *r) {
|
|
|
|
return r->io.buffer.pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns 1 or 0 for success/failure. */
|
|
|
|
static size_t rioFileWrite(rio *r, const void *buf, size_t len) {
|
|
|
|
return fwrite(buf,len,1,r->io.file.fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns 1 or 0 for success/failure. */
|
|
|
|
static size_t rioFileRead(rio *r, void *buf, size_t len) {
|
|
|
|
return fread(buf,len,1,r->io.file.fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns read/write position in file. */
|
|
|
|
static off_t rioFileTell(rio *r) {
|
|
|
|
return ftello(r->io.file.fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const rio rioBufferIO = {
|
|
|
|
rioBufferRead,
|
|
|
|
rioBufferWrite,
|
|
|
|
rioBufferTell,
|
|
|
|
{ { NULL, 0 } } /* union for io-specific vars */
|
|
|
|
};
|
|
|
|
|
|
|
|
static const rio rioFileIO = {
|
|
|
|
rioFileRead,
|
|
|
|
rioFileWrite,
|
|
|
|
rioFileTell,
|
|
|
|
{ { NULL, 0 } } /* union for io-specific vars */
|
|
|
|
};
|
|
|
|
|
2011-09-22 10:00:40 -04:00
|
|
|
void rioInitWithFile(rio *r, FILE *fp) {
|
|
|
|
*r = rioFileIO;
|
|
|
|
r->io.file.fp = fp;
|
2011-05-13 11:31:00 -04:00
|
|
|
}
|
2011-09-22 10:00:40 -04:00
|
|
|
|
|
|
|
void rioInitWithBuffer(rio *r, sds s) {
|
|
|
|
*r = rioBufferIO;
|
|
|
|
r->io.buffer.ptr = s;
|
|
|
|
r->io.buffer.pos = 0;
|
2011-05-13 11:31:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Write multi bulk count in the format: "*<count>\r\n". */
|
|
|
|
size_t rioWriteBulkCount(rio *r, char prefix, int count) {
|
|
|
|
char cbuf[128];
|
|
|
|
int clen;
|
|
|
|
|
|
|
|
cbuf[0] = prefix;
|
|
|
|
clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);
|
|
|
|
cbuf[clen++] = '\r';
|
|
|
|
cbuf[clen++] = '\n';
|
|
|
|
if (rioWrite(r,cbuf,clen) == 0) return 0;
|
|
|
|
return clen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write binary-safe string in the format: "$<count>\r\n<payload>\r\n". */
|
|
|
|
size_t rioWriteBulkString(rio *r, const char *buf, size_t len) {
|
|
|
|
size_t nwritten;
|
|
|
|
|
|
|
|
if ((nwritten = rioWriteBulkCount(r,'$',len)) == 0) return 0;
|
|
|
|
if (len > 0 && rioWrite(r,buf,len) == 0) return 0;
|
|
|
|
if (rioWrite(r,"\r\n",2) == 0) return 0;
|
|
|
|
return nwritten+len+2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write a long long value in format: "$<count>\r\n<payload>\r\n". */
|
|
|
|
size_t rioWriteBulkLongLong(rio *r, long long l) {
|
|
|
|
char lbuf[32];
|
|
|
|
unsigned int llen;
|
|
|
|
|
|
|
|
llen = ll2string(lbuf,sizeof(lbuf),l);
|
|
|
|
return rioWriteBulkString(r,lbuf,llen);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write a double value in the format: "$<count>\r\n<payload>\r\n" */
|
|
|
|
size_t rioWriteBulkDouble(rio *r, double d) {
|
|
|
|
char dbuf[128];
|
|
|
|
unsigned int dlen;
|
|
|
|
|
|
|
|
dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d);
|
|
|
|
return rioWriteBulkString(r,dbuf,dlen);
|
|
|
|
}
|