#ifndef HV_BUF_H_ #define HV_BUF_H_ #include "hdef.h" // for MAX #include "hbase.h" // for HV_ALLOC, HV_FREE typedef struct hbuf_s { char* base; size_t len; #ifdef __cplusplus hbuf_s() { base = NULL; len = 0; } hbuf_s(void* data, size_t len) { this->base = (char*)data; this->len = len; } #endif } hbuf_t; typedef struct offset_buf_s { char* base; size_t len; size_t offset; #ifdef __cplusplus offset_buf_s() { base = NULL; len = 0; offset = 0; } offset_buf_s(void* data, size_t len) { this->base = (char*)data; this->len = len; offset = 0; } #endif } offset_buf_t; typedef struct fifo_buf_s { char* base; size_t len; size_t head; size_t tail; #ifdef __cplusplus fifo_buf_s() { base = NULL; len = 0; head = tail = 0; } fifo_buf_s(void* data, size_t len) { this->base = (char*)data; this->len = len; head = tail = 0; } #endif } fifo_buf_t; #ifdef __cplusplus class HBuf : public hbuf_t { public: HBuf() : hbuf_t() { cleanup_ = false; } HBuf(void* data, size_t len) : hbuf_t(data, len) { cleanup_ = false; } HBuf(size_t cap) { resize(cap); } virtual ~HBuf() { cleanup(); } void* data() { return base; } size_t size() { return len; } bool isNull() { return base == NULL || len == 0; } void cleanup() { if (cleanup_) { HV_FREE(base); len = 0; cleanup_ = false; } } void resize(size_t cap) { if (cap == len) return; if (base == NULL) { HV_ALLOC(base, cap); } else { base = (char*)hv_realloc(base, cap, len); } len = cap; cleanup_ = true; } void copy(void* data, size_t len) { resize(len); memcpy(base, data, len); } void copy(hbuf_t* buf) { copy(buf->base, buf->len); } private: bool cleanup_; }; // VL: Variable-Length class HVLBuf : public HBuf { public: HVLBuf() : HBuf() {_offset = _size = 0;} HVLBuf(void* data, size_t len) : HBuf(data, len) {_offset = 0; _size = len;} HVLBuf(size_t cap) : HBuf(cap) {_offset = _size = 0;} virtual ~HVLBuf() {} char* data() { return base + _offset; } size_t size() { return _size; } void push_front(void* ptr, size_t len) { if (len > this->len - _size) { size_t newsize = MAX(this->len, len)*2; resize(newsize); } if (_offset < len) { // move => end memmove(base+this->len-_size, data(), _size); _offset = this->len-_size; } memcpy(data()-len, ptr, len); _offset -= len; _size += len; } void push_back(void* ptr, size_t len) { if (len > this->len - _size) { size_t newsize = MAX(this->len, len)*2; resize(newsize); } else if (len > this->len - _offset - _size) { // move => start memmove(base, data(), _size); _offset = 0; } memcpy(data()+_size, ptr, len); _size += len; } void pop_front(void* ptr, size_t len) { if (len <= _size) { if (ptr) { memcpy(ptr, data(), len); } _offset += len; if (_offset >= this->len) _offset = 0; _size -= len; } } void pop_back(void* ptr, size_t len) { if (len <= _size) { if (ptr) { memcpy(ptr, data()+_size-len, len); } _size -= len; } } void clear() { _offset = _size = 0; } void prepend(void* ptr, size_t len) { push_front(ptr, len); } void append(void* ptr, size_t len) { push_back(ptr, len); } void insert(void* ptr, size_t len) { push_back(ptr, len); } void remove(size_t len) { pop_front(NULL, len); } private: size_t _offset; size_t _size; }; class HRingBuf : public HBuf { public: HRingBuf() : HBuf() {_head = _tail = _size = 0;} HRingBuf(size_t cap) : HBuf(cap) {_head = _tail = _size = 0;} virtual ~HRingBuf() {} char* alloc(size_t len) { char* ret = NULL; if (_head < _tail || _size == 0) { // [_tail, this->len) && [0, _head) if (this->len - _tail >= len) { ret = base + _tail; _tail += len; if (_tail == this->len) _tail = 0; } else if (_head >= len) { ret = base; _tail = len; } } else { // [_tail, _head) if (_head - _tail >= len) { ret = base + _tail; _tail += len; } } _size += ret ? len : 0; return ret; } void free(size_t len) { _size -= len; if (len <= this->len - _head) { _head += len; if (_head == this->len) _head = 0; } else { _head = len; } } void clear() {_head = _tail = _size = 0;} size_t size() {return _size;} private: size_t _head; size_t _tail; size_t _size; }; #endif #endif // HV_BUF_H_