mirror of https://github.com/yandex/odyssey.git
201 lines
3.8 KiB
C
201 lines
3.8 KiB
C
#ifndef SHAPITO_BUF_H
|
|
#define SHAPITO_BUF_H
|
|
|
|
/*
|
|
* Shapito.
|
|
*
|
|
* Protocol-level PostgreSQL client library.
|
|
*/
|
|
|
|
typedef struct so_stream so_stream_t;
|
|
|
|
struct so_stream
|
|
{
|
|
char *start;
|
|
char *pos;
|
|
char *end;
|
|
};
|
|
|
|
static inline void
|
|
so_stream_init(so_stream_t *stream)
|
|
{
|
|
stream->start = NULL;
|
|
stream->pos = NULL;
|
|
stream->end = NULL;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_free(so_stream_t *stream)
|
|
{
|
|
if (stream->start == NULL)
|
|
return;
|
|
free(stream->start);
|
|
stream->start = NULL;
|
|
stream->pos = NULL;
|
|
stream->end = NULL;
|
|
}
|
|
|
|
static inline int
|
|
so_stream_size(so_stream_t *stream)
|
|
{
|
|
return stream->end - stream->start;
|
|
}
|
|
|
|
static inline int
|
|
so_stream_used(so_stream_t *stream)
|
|
{
|
|
return stream->pos - stream->start;
|
|
}
|
|
|
|
static inline int
|
|
so_stream_left(so_stream_t *stream)
|
|
{
|
|
return stream->end - stream->pos;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_reset(so_stream_t *stream)
|
|
{
|
|
stream->pos = stream->start;
|
|
}
|
|
|
|
static inline int
|
|
so_stream_ensure(so_stream_t *stream, int size)
|
|
{
|
|
if (stream->end - stream->pos >= size)
|
|
return 0;
|
|
int sz = so_stream_size(stream) * 2;
|
|
int actual = so_stream_used(stream) + size;
|
|
if (actual > sz)
|
|
sz = actual;
|
|
char *pointer = realloc(stream->start, sz);
|
|
if (pointer == NULL)
|
|
return -1;
|
|
stream->pos = pointer + (stream->pos - stream->start);
|
|
stream->end = pointer + sz;
|
|
stream->start = pointer;
|
|
assert((stream->end - stream->pos) >= size);
|
|
return 0;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_advance(so_stream_t *stream, int size)
|
|
{
|
|
stream->pos += size;
|
|
assert(stream->pos <= stream->end);
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write8to(char *dest, uint8_t value)
|
|
{
|
|
*dest = (char)value;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write16to(char *dest, uint16_t value)
|
|
{
|
|
dest[0] = (value >> 8) & 255;
|
|
dest[1] = value & 255;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write32to(char *dest, uint32_t value)
|
|
{
|
|
dest[0] = (value >> 24) & 255;
|
|
dest[1] = (value >> 16) & 255;
|
|
dest[2] = (value >> 8) & 255;
|
|
dest[3] = value & 255;
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write8(so_stream_t *stream, uint8_t value)
|
|
{
|
|
so_stream_write8to(stream->pos, value);
|
|
so_stream_advance(stream, sizeof(uint8_t));
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write16(so_stream_t *stream, uint16_t value)
|
|
{
|
|
so_stream_write16to(stream->pos, value);
|
|
so_stream_advance(stream, sizeof(uint16_t));
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write32(so_stream_t *stream, uint32_t value)
|
|
{
|
|
so_stream_write32to(stream->pos, value);
|
|
so_stream_advance(stream, sizeof(uint32_t));
|
|
}
|
|
|
|
static inline void
|
|
so_stream_write(so_stream_t *stream, char *buf, int size)
|
|
{
|
|
memcpy(stream->pos, buf, size);
|
|
so_stream_advance(stream, size);
|
|
}
|
|
|
|
static inline int
|
|
so_stream_read8(char *out, char **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_stream_read16(uint16_t *out, char **pos, uint32_t *size)
|
|
{
|
|
if (so_unlikely(*size < sizeof(uint16_t)))
|
|
return -1;
|
|
unsigned char *ptr = (unsigned char*)*pos;
|
|
*out = ptr[0] << 8 | ptr[1];
|
|
*size -= sizeof(uint16_t);
|
|
*pos += sizeof(uint16_t);
|
|
return 0;
|
|
}
|
|
|
|
static inline int
|
|
so_stream_read32(uint32_t *out, char **pos, uint32_t *size)
|
|
{
|
|
if (so_unlikely(*size < sizeof(uint32_t)))
|
|
return -1;
|
|
unsigned char *ptr = (unsigned char*)*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_stream_readsz(char **pos, uint32_t *size)
|
|
{
|
|
char *p = *pos;
|
|
char *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_stream_read(uint32_t n, char **pos, uint32_t *size)
|
|
{
|
|
char *end = *pos + *size;
|
|
char *next = *pos + n;
|
|
if (so_unlikely(next > end))
|
|
return -1;
|
|
*size -= (uint32_t)(next - *pos);
|
|
*pos = next;
|
|
return 0;
|
|
}
|
|
|
|
#endif /* SHAPITO_BUF_H */
|