From a4e515660bfc8828b63c8ffb31792a35c81ddab9 Mon Sep 17 00:00:00 2001 From: localvar Date: Mon, 17 Feb 2020 12:33:36 +0800 Subject: [PATCH] update buffer implementation --- src/util/inc/tbuffer.h | 114 ++++++++++++++++++++++++++--------------- src/util/src/tbuffer.c | 84 ++++++++++++++++-------------- 2 files changed, 118 insertions(+), 80 deletions(-) diff --git a/src/util/inc/tbuffer.h b/src/util/inc/tbuffer.h index c3bb336e81..9dc6d97eb6 100644 --- a/src/util/inc/tbuffer.h +++ b/src/util/inc/tbuffer.h @@ -24,45 +24,78 @@ /* SBuffer can be used to read or write a buffer, but cannot be used for both -read & write at a same time. -Read example: - SBuffer rbuf; - if (tbufBeginOperation(&rbuf) != 0) { - // handling errors - } - tbufInitRead(&rbuf, data, 1024); - int32_t a = tbufReadInt32(&rbuf); - // other read functions - -Write example: - SBuffer wbuf; - if (tbufBeginOperation(&wbuf) != 0) { - // handling errors - } - tbufInitWrite(&wbuf, 1024); - tbufWriteInt32(&wbuf, 10); - // other write functions - size_t size = tbufGetSize(&wbuf); - char* data = tbufGetBuffer(&wbuf, true); - tbufUninitWrite(&wbuf); +read & write at a same time. Below is an example: + +int main(int argc, char** argv) { + //--------------------- write ------------------------ + SBuffer wbuf; + int32_t code = tbufBeginWrite(&wbuf); + if (code != 0) { + // handle errors + return 0; + } + + // reserve 1024 bytes for the buffer to improve performance + tbufEnsureCapacity(&wbuf, 1024); + + // write 5 integers to the buffer + for (int i = 0; i < 5; i++) { + tbufWriteInt32(&wbuf, i); + } + + // write a string to the buffer + tbufWriteString(&wbuf, "this is a string.\n"); + + // acquire the result and close the write buffer + size_t size = tbufTell(&wbuf); + char* data = tbufGetData(&wbuf, true); + tbufClose(&wbuf, true); + + + //------------------------ read ----------------------- + SBuffer rbuf; + code = tbufBeginRead(&rbuf, data, size); + if (code != 0) { + printf("you will see this message after print out 5 integers and a string.\n"); + tbufClose(&rbuf, false); + return 0; + } + + // read & print out 5 integers + for (int i = 0; i < 5; i++) { + printf("%d\n", tbufReadInt32(&rbuf)); + } + + // read & print out a string + printf(tbufReadString(&rbuf, NULL)); + + // try read another integer, this result in an error as there no this integer + tbufReadInt32(&rbuf); + + printf("you should not see this message.\n"); + tbufClose(&rbuf, false); + + return 0; +} */ typedef struct { jmp_buf jb; - char* buf; + char* data; size_t pos; size_t size; } SBuffer; // common functions can be used in both read & write -#define tbufBeginOperation(buf) setjmp((buf)->jb) +#define tbufThrowError(buf, code) longjmp((buf)->jb, (code)) size_t tbufTell(SBuffer* buf); size_t tbufSeekTo(SBuffer* buf, size_t pos); size_t tbufSkip(SBuffer* buf, size_t size); +void tbufClose(SBuffer* buf, bool keepData); // basic read functions -void tbufInitRead(SBuffer* buf, void* data, size_t size); +#define tbufBeginRead(buf, data, len) (((buf)->data = (char*)data), ((buf)->pos = 0), ((buf)->size = ((data) == NULL) ? 0 : (len)), setjmp((buf)->jb)) char* tbufRead(SBuffer* buf, size_t size); void tbufReadToBuffer(SBuffer* buf, void* dst, size_t size); const char* tbufReadString(SBuffer* buf, size_t* len); @@ -70,10 +103,9 @@ size_t tbufReadToString(SBuffer* buf, char* dst, size_t size); // basic write functions -void tbufInitWrite(SBuffer* buf, size_t size); +#define tbufBeginWrite(buf) ((buf)->data = NULL, ((buf)->pos = 0), ((buf)->size = 0), setjmp((buf)->jb)) void tbufEnsureCapacity(SBuffer* buf, size_t size); -char* tbufGetResult(SBuffer* buf, bool takeOver); -void tbufUninitWrite(SBuffer* buf); +char* tbufGetData(SBuffer* buf, bool takeOver); void tbufWrite(SBuffer* buf, const void* data, size_t size); void tbufWriteAt(SBuffer* buf, size_t pos, const void* data, size_t size); void tbufWriteStringLen(SBuffer* buf, const char* str, size_t len); @@ -81,24 +113,24 @@ void tbufWriteString(SBuffer* buf, const char* str); // read & write function for primitive types -#ifndef TBUFFER_DEFINE_OPERATION -#define TBUFFER_DEFINE_OPERATION(type, name) \ +#ifndef TBUFFER_DEFINE_FUNCTION +#define TBUFFER_DEFINE_FUNCTION(type, name) \ type tbufRead##name(SBuffer* buf); \ void tbufWrite##name(SBuffer* buf, type data); \ void tbufWrite##name##At(SBuffer* buf, size_t pos, type data); #endif -TBUFFER_DEFINE_OPERATION( bool, Bool ) -TBUFFER_DEFINE_OPERATION( char, Char ) -TBUFFER_DEFINE_OPERATION( int8_t, Int8 ) -TBUFFER_DEFINE_OPERATION( uint8_t, Unt8 ) -TBUFFER_DEFINE_OPERATION( int16_t, Int16 ) -TBUFFER_DEFINE_OPERATION( uint16_t, Uint16 ) -TBUFFER_DEFINE_OPERATION( int32_t, Int32 ) -TBUFFER_DEFINE_OPERATION( uint32_t, Uint32 ) -TBUFFER_DEFINE_OPERATION( int64_t, Int64 ) -TBUFFER_DEFINE_OPERATION( uint64_t, Uint64 ) -TBUFFER_DEFINE_OPERATION( float, Float ) -TBUFFER_DEFINE_OPERATION( double, Double ) +TBUFFER_DEFINE_FUNCTION( bool, Bool ) +TBUFFER_DEFINE_FUNCTION( char, Char ) +TBUFFER_DEFINE_FUNCTION( int8_t, Int8 ) +TBUFFER_DEFINE_FUNCTION( uint8_t, Unt8 ) +TBUFFER_DEFINE_FUNCTION( int16_t, Int16 ) +TBUFFER_DEFINE_FUNCTION( uint16_t, Uint16 ) +TBUFFER_DEFINE_FUNCTION( int32_t, Int32 ) +TBUFFER_DEFINE_FUNCTION( uint32_t, Uint32 ) +TBUFFER_DEFINE_FUNCTION( int64_t, Int64 ) +TBUFFER_DEFINE_FUNCTION( uint64_t, Uint64 ) +TBUFFER_DEFINE_FUNCTION( float, Float ) +TBUFFER_DEFINE_FUNCTION( double, Double ) #endif \ No newline at end of file diff --git a/src/util/src/tbuffer.c b/src/util/src/tbuffer.c index 0b8cfbbae9..ac7d22078d 100644 --- a/src/util/src/tbuffer.c +++ b/src/util/src/tbuffer.c @@ -13,7 +13,11 @@ * along with this program. If not, see . */ -#define TBUFFER_DEFINE_OPERATION(type, name) \ +#include +#include +#include + +#define TBUFFER_DEFINE_FUNCTION(type, name) \ type tbufRead##name(SBuffer* buf) { \ type ret; \ tbufReadToBuffer(buf, &ret, sizeof(type)); \ @@ -38,7 +42,8 @@ size_t tbufTell(SBuffer* buf) { size_t tbufSeekTo(SBuffer* buf, size_t pos) { if (pos > buf->size) { - longjmp(buf->jb, 1); + // TODO: update error code, other tbufThrowError need to be changed too + tbufThrowError(buf, 1); } size_t old = buf->pos; buf->pos = pos; @@ -49,18 +54,20 @@ size_t tbufSkip(SBuffer* buf, size_t size) { return tbufSeekTo(buf, buf->pos + size); } -//////////////////////////////////////////////////////////////////////////////// -// read functions - -void tbufInitRead(SBuffer* buf, void* data, size_t size) { - buf->buf = (char*)data; +void tbufClose(SBuffer* buf, bool keepData) { + if (!keepData) { + free(buf->data); + } + buf->data = NULL; buf->pos = 0; - // empty buffer is not an error, but read an empty buffer is - buf->size = (data == NULL) ? 0 : size; + buf->size = 0; } +//////////////////////////////////////////////////////////////////////////////// +// read functions + char* tbufRead(SBuffer* buf, size_t size) { - char* ret = buf->buf + buf->pos; + char* ret = buf->data + buf->pos; tbufSkip(buf, size); return ret; } @@ -72,8 +79,8 @@ void tbufReadToBuffer(SBuffer* buf, void* dst, size_t size) { } const char* tbufReadString(SBuffer* buf, size_t* len) { - uint16_t l = tbufReadUint16(); - char* ret = buf->buf + buf->pos; + uint16_t l = tbufReadUint16(buf); + char* ret = buf->data + buf->pos; tbufSkip(buf, l + 1); ret[l] = 0; // ensure the string end with '\0' if (len != NULL) { @@ -83,9 +90,12 @@ const char* tbufReadString(SBuffer* buf, size_t* len) { } size_t tbufReadToString(SBuffer* buf, char* dst, size_t size) { + assert(dst != NULL); size_t len; const char* str = tbufReadString(buf, &len); - if (len >= size) len = size - 1; + if (len >= size) { + len = size - 1; + } memcpy(dst, str, len); dst[len] = 0; return len; @@ -98,57 +108,53 @@ size_t tbufReadToString(SBuffer* buf, char* dst, size_t size) { void tbufEnsureCapacity(SBuffer* buf, size_t size) { size += buf->pos; if (size > buf->size) { - char* nbuf = NULL; size_t nsize = size + buf->size; - nbuf = realloc(buf->buf, nsize); - if (nbuf == NULL) { - longjmp(buf->jb, 2); + char* data = realloc(buf->data, nsize); + if (data == NULL) { + tbufThrowError(buf, 2); } - buf->buf = nbuf; + buf->data = data; buf->size = nsize; } } -void tbufInitWrite(SBuffer* buf, size_t size) { - buf->buf = NULL; - buf->pos = 0; - buf->size = 0; - tbufEnsureCapacity(buf, size); -} - -char* tbufGetResult(SBuffer* buf, bool takeOver) { - char* ret = buf->buf; +char* tbufGetData(SBuffer* buf, bool takeOver) { + char* ret = buf->data; if (takeOver) { buf->pos = 0; buf->size = 0; - buf->buf = NULL; + buf->data = NULL; } return ret; } -void tbufUninitWrite(SBuffer* buf) { - free(buf->buf); +void tbufEndWrite(SBuffer* buf) { + free(buf->data); + buf->data = NULL; + buf->pos = 0; + buf->size = 0; } void tbufWrite(SBuffer* buf, const void* data, size_t size) { - tbufEnsureCapacity(size); - memcpy(buf->buf + buf->pos, data, size); + assert(data != NULL); + tbufEnsureCapacity(buf, size); + memcpy(buf->data + buf->pos, data, size); buf->pos += size; } void tbufWriteAt(SBuffer* buf, size_t pos, const void* data, size_t size) { + assert(data != NULL); // this function can only be called to fill the gap on previous writes, // so 'pos + size <= buf->pos' must be true - if (pos + size > buf->pos) { - longjmp(buf->jb, 3); - } - memcpy(buf->buf + pos, data, size); + assert(pos + size <= buf->pos); + memcpy(buf->data + pos, data, size); } void tbufWriteStringLen(SBuffer* buf, const char* str, size_t len) { - if (len > 0xffff) { - longjmp(buf->jb , 4); - } + // maximum string length is 65535, if longer string is required + // this function and the corresponding read function need to be + // revised. + assert(len <= 0xffff); tbufWriteUint16(buf, (uint16_t)len); tbufWrite(buf, str, len + 1); } -- GitLab