odyssey/lib/so_buf.h

176 lines
2.9 KiB
C

#ifndef SO_BUF_H_
#define SO_BUF_H_
/*
* sonata.
*
* Protocol-level PostgreSQL client library.
*/
typedef struct sobuf_t sobuf_t;
struct sobuf_t {
uint8_t *s, *p, *e;
};
static inline int
so_bufsize(sobuf_t *b) {
return b->e - b->s;
}
static inline int
so_bufused(sobuf_t *b) {
return b->p - b->s;
}
static inline int
so_bufleft(sobuf_t *b) {
return b->e - b->p;
}
static inline void
so_bufreset(sobuf_t *b) {
b->p = b->s;
}
static inline void
so_bufinit(sobuf_t *b)
{
b->s = NULL;
b->p = NULL;
b->e = NULL;
}
static inline void
so_buffree(sobuf_t *b)
{
if (b->s == NULL)
return;
free(b->s);
b->s = NULL;
b->p = NULL;
b->e = NULL;
}
static inline int
so_bufensure(sobuf_t *b, int size)
{
if (b->e - b->p >= size)
return 0;
int sz = so_bufsize(b) * 2;
int actual = so_bufused(b) + size;
if (actual > sz)
sz = actual;
uint8_t *p = (uint8_t*)realloc(b->s, sz);
if (p == NULL)
return -1;
b->p = p + (b->p - b->s);
b->e = p + sz;
b->s = p;
assert((b->e - b->p) >= size);
return 0;
}
static inline void
so_bufadvance(sobuf_t *b, int size)
{
b->p += size;
assert(b->p <= b->e);
}
static inline void
so_bufwrite8(sobuf_t *b, uint8_t v)
{
*b->p = v;
so_bufadvance(b, sizeof(uint8_t));
}
static inline void
so_bufwrite16(sobuf_t *b, uint16_t v)
{
b->p[0] = (v >> 8) & 255;
b->p[1] = v & 255;
so_bufadvance(b, sizeof(uint16_t));
}
static inline void
so_bufwrite32(sobuf_t *b, uint32_t v)
{
b->p[0] = (v >> 24) & 255;
b->p[1] = (v >> 16) & 255;
b->p[2] = (v >> 8) & 255;
b->p[3] = v & 255;
so_bufadvance(b, sizeof(uint32_t));
}
static inline void
so_bufwrite(sobuf_t *b, uint8_t *buf, int size)
{
memcpy(b->p, buf, size);
so_bufadvance(b, size);
}
static inline int
so_bufread8(uint8_t *out, uint8_t **pos, uint32_t *size)
{
if (so_unlikely(*size < sizeof(uint8_t)))
return -1;
*out = *pos[0];
*size -= sizeof(uint8_t);
*pos += sizeof(uint8_t);
return 0;
}
static inline int
so_bufread16(uint16_t *out, uint8_t **pos, uint32_t *size)
{
if (so_unlikely(*size < sizeof(uint16_t)))
return -1;
*out = (*pos)[0] << 8 |
(*pos)[1];
*size -= sizeof(uint16_t);
*pos += sizeof(uint16_t);
return 0;
}
static inline int
so_bufread32(uint32_t *out, uint8_t **pos, uint32_t *size)
{
if (so_unlikely(*size < sizeof(uint32_t)))
return -1;
uint8_t *ptr = *pos;
*out = ptr[0] << 24 | ptr[1] << 16 |
ptr[2] << 8 | ptr[3];
*size -= sizeof(uint32_t);
*pos += sizeof(uint32_t);
return 0;
}
static inline int
so_bufreadsz(uint8_t **pos, uint32_t *size)
{
uint8_t *p = *pos;
uint8_t *end = p + *size;
while (p < end && *p)
p++;
if (so_unlikely(p == end))
return -1;
*size -= (uint32_t)(p - *pos) + 1;
*pos = p + 1;
return 0;
}
static inline int
so_bufread(uint32_t n, uint8_t **pos, uint32_t *size)
{
uint8_t *end = *pos + *size;
uint8_t *next = *pos + n;
if (so_unlikely(next > end))
return -1;
*size -= (uint32_t)(next - *pos);
*pos = next;
return 0;
}
#endif