#include #include #include "hook/iobuf.h" void iobuf_flip(struct const_iobuf *child, struct iobuf *parent) { assert(child != NULL); assert(parent != NULL); child->bytes = parent->bytes; child->pos = 0; child->nbytes = parent->pos; } size_t iobuf_move(struct iobuf *dest, struct const_iobuf *src) { size_t dest_avail; size_t src_avail; size_t chunksz; assert(dest != NULL); assert(dest->bytes != NULL || dest->nbytes == 0); assert(dest->pos <= dest->nbytes); assert(src != NULL); assert(src->bytes != NULL || src->nbytes == 0); assert(src->pos <= src->nbytes); dest_avail = dest->nbytes - dest->pos; src_avail = src->nbytes - src->pos; chunksz = dest_avail < src_avail ? dest_avail : src_avail; memcpy(&dest->bytes[dest->pos], &src->bytes[src->pos], chunksz); dest->pos += chunksz; src->pos += chunksz; return chunksz; } size_t iobuf_shift(struct iobuf *dest, struct iobuf *src) { struct const_iobuf span; assert(dest != NULL); assert(src != NULL); iobuf_flip(&span, src); iobuf_move(dest, &span); memmove(src->bytes, &src->bytes[span.pos], span.nbytes - span.pos); src->pos -= span.pos; return span.pos; } HRESULT iobuf_read(struct const_iobuf *src, void *bytes, size_t nbytes) { assert(src != NULL); assert(bytes != NULL || nbytes == 0); if (src->pos + nbytes > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } memcpy(bytes, &src->bytes[src->pos], nbytes); src->pos += nbytes; return S_OK; } HRESULT iobuf_read_8(struct const_iobuf *src, uint8_t *out) { assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint8_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } *out = src->bytes[src->pos++]; return S_OK; } HRESULT iobuf_read_be16(struct const_iobuf *src, uint16_t *out) { uint16_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint16_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = src->bytes[src->pos++] << 8; value |= src->bytes[src->pos++]; *out = value; return S_OK; } HRESULT iobuf_read_be32(struct const_iobuf *src, uint32_t *out) { uint32_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint32_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = src->bytes[src->pos++] << 24; value |= src->bytes[src->pos++] << 16; value |= src->bytes[src->pos++] << 8; value |= src->bytes[src->pos++]; *out = value; return S_OK; } HRESULT iobuf_read_be64(struct const_iobuf *src, uint64_t *out) { uint64_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint64_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = ((uint64_t) src->bytes[src->pos++]) << 56; value |= ((uint64_t) src->bytes[src->pos++]) << 48; value |= ((uint64_t) src->bytes[src->pos++]) << 40; value |= ((uint64_t) src->bytes[src->pos++]) << 32; value |= ((uint64_t) src->bytes[src->pos++]) << 24; value |= ((uint64_t) src->bytes[src->pos++]) << 16; value |= ((uint64_t) src->bytes[src->pos++]) << 8; value |= ((uint64_t) src->bytes[src->pos++]); *out = value; return S_OK; } HRESULT iobuf_read_le16(struct const_iobuf *src, uint16_t *out) { uint16_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint16_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = src->bytes[src->pos++]; value |= src->bytes[src->pos++] << 8; *out = value; return S_OK; } HRESULT iobuf_read_le32(struct const_iobuf *src, uint32_t *out) { uint32_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint32_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = src->bytes[src->pos++]; value |= src->bytes[src->pos++] << 8; value |= src->bytes[src->pos++] << 16; value |= src->bytes[src->pos++] << 24; *out = value; return S_OK; } HRESULT iobuf_read_le64(struct const_iobuf *src, uint64_t *out) { uint64_t value; assert(src != NULL); assert(out != NULL); if (src->pos + sizeof(uint64_t) > src->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } value = ((uint64_t) src->bytes[src->pos++]); value |= ((uint64_t) src->bytes[src->pos++]) << 8; value |= ((uint64_t) src->bytes[src->pos++]) << 16; value |= ((uint64_t) src->bytes[src->pos++]) << 24; value |= ((uint64_t) src->bytes[src->pos++]) << 32; value |= ((uint64_t) src->bytes[src->pos++]) << 40; value |= ((uint64_t) src->bytes[src->pos++]) << 48; value |= ((uint64_t) src->bytes[src->pos++]) << 56; *out = value; return S_OK; } HRESULT iobuf_write(struct iobuf *dest, const void *bytes, size_t nbytes) { assert(dest != NULL); assert(bytes != NULL || nbytes == 0); if (dest->pos + nbytes > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } memcpy(&dest->bytes[dest->pos], bytes, nbytes); dest->pos += nbytes; return S_OK; } HRESULT iobuf_write_8(struct iobuf *dest, uint8_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint8_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value; return S_OK; } HRESULT iobuf_write_be16(struct iobuf *dest, uint16_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint16_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value >> 8; dest->bytes[dest->pos++] = value; return S_OK; } HRESULT iobuf_write_be32(struct iobuf *dest, uint32_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint32_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value >> 24; dest->bytes[dest->pos++] = value >> 16; dest->bytes[dest->pos++] = value >> 8; dest->bytes[dest->pos++] = value; return S_OK; } HRESULT iobuf_write_be64(struct iobuf *dest, uint64_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint64_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value >> 56; dest->bytes[dest->pos++] = value >> 48; dest->bytes[dest->pos++] = value >> 40; dest->bytes[dest->pos++] = value >> 32; dest->bytes[dest->pos++] = value >> 24; dest->bytes[dest->pos++] = value >> 16; dest->bytes[dest->pos++] = value >> 8; dest->bytes[dest->pos++] = value; return S_OK; } HRESULT iobuf_write_le16(struct iobuf *dest, uint16_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint16_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value; dest->bytes[dest->pos++] = value >> 8; return S_OK; } HRESULT iobuf_write_le32(struct iobuf *dest, uint32_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint32_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value; dest->bytes[dest->pos++] = value >> 8; dest->bytes[dest->pos++] = value >> 16; dest->bytes[dest->pos++] = value >> 24; return S_OK; } HRESULT iobuf_write_le64(struct iobuf *dest, uint64_t value) { assert(dest != NULL); if (dest->pos + sizeof(uint64_t) > dest->nbytes) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } dest->bytes[dest->pos++] = value; dest->bytes[dest->pos++] = value >> 8; dest->bytes[dest->pos++] = value >> 16; dest->bytes[dest->pos++] = value >> 24; dest->bytes[dest->pos++] = value >> 32; dest->bytes[dest->pos++] = value >> 40; dest->bytes[dest->pos++] = value >> 48; dest->bytes[dest->pos++] = value >> 56; return S_OK; }