#include <sys_defs.h>
#include <msg.h>
#include <vstream.h>
#include <vstring.h>
#include <vstring_vstream.h>
#include <compat_va_copy.h>
#include <memcache_proto.h>
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
int memcache_get(VSTREAM *stream, VSTRING *vp, ssize_t bound)
{
int last_char;
int next_char;
last_char = (bound == 0 ? vstring_get(vp, stream) :
vstring_get_bound(vp, stream, bound));
switch (last_char) {
case '\r':
if ((next_char = VSTREAM_GETC(stream)) == '\n') {
VSTRING_ADDCH(vp, '\n');
} else {
if (next_char != VSTREAM_EOF)
vstream_ungetc(stream, next_char);
default:
if (msg_verbose)
msg_info("%s got %s", VSTREAM_PATH(stream),
LEN(vp) < bound ? "EOF" : "input too long");
return (-1);
}
case '\n':
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
if (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
VSTRING_TERMINATE(vp);
if (msg_verbose)
msg_info("%s got: %s", VSTREAM_PATH(stream), STR(vp));
return (0);
}
}
int memcache_fwrite(VSTREAM *stream, const char *cp, ssize_t todo)
{
if (todo < 0)
msg_panic("memcache_fwrite: negative todo %ld", (long) todo);
if (msg_verbose)
msg_info("%s write: %.*s", VSTREAM_PATH(stream), (int) todo, cp);
if (vstream_fwrite(stream, cp, todo) != todo
|| vstream_fputs("\r\n", stream) == VSTREAM_EOF)
return (-1);
else
return (0);
}
int memcache_fread(VSTREAM *stream, VSTRING *buf, ssize_t todo)
{
if (todo < 0)
msg_panic("memcache_fread: negative todo %ld", (long) todo);
VSTRING_SPACE(buf, todo);
VSTRING_AT_OFFSET(buf, todo);
if (vstream_fread(stream, STR(buf), todo) != todo
|| VSTREAM_GETC(stream) != '\r'
|| VSTREAM_GETC(stream) != '\n') {
if (msg_verbose)
msg_info("%s read: error", VSTREAM_PATH(stream));
return (-1);
} else {
vstring_truncate(buf, todo);
VSTRING_TERMINATE(buf);
if (msg_verbose)
msg_info("%s read: %s", VSTREAM_PATH(stream), STR(buf));
return (0);
}
}
int memcache_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
{
vstream_vfprintf(stream, fmt, ap);
vstream_fputs("\r\n", stream);
if (vstream_ferror(stream))
return (-1);
else
return (0);
}
int memcache_printf(VSTREAM *stream, const char *fmt,...)
{
va_list ap;
int ret;
va_start(ap, fmt);
if (msg_verbose) {
VSTRING *buf = vstring_alloc(100);
va_list ap2;
VA_COPY(ap2, ap);
vstring_vsprintf(buf, fmt, ap2);
va_end(ap2);
msg_info("%s write: %s", VSTREAM_PATH(stream), STR(buf));
vstring_free(buf);
}
ret = memcache_vprintf(stream, fmt, ap);
va_end(ap);
return (ret);
}