/* * Copyright (c) 2020 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef _TD_UTIL_BUFFER_H #define _TD_UTIL_BUFFER_H #ifdef __cplusplus extern "C" { #endif //////////////////////////////////////////////////////////////////////////////// // usage example /* #include #include "exception.h" int main( int argc, char** argv ) { SBufferWriter bw = tbufInitWriter( NULL, false ); TRY( 1 ) { //--------------------- write ------------------------ // reserve 1024 bytes for the buffer to improve performance tbufEnsureCapacity( &bw, 1024 ); // reserve space for the interger count size_t pos = tbufReserve( &bw, sizeof(int32_t) ); // write 5 integers to the buffer for( int i = 0; i < 5; i++) { tbufWriteInt32( &bw, i ); } // write the integer count to buffer at reserved position tbufWriteInt32At( &bw, pos, 5 ); // write a string to the buffer tbufWriteString( &bw, "this is a string.\n" ); // acquire the result and close the write buffer size_t size = tbufTell( &bw ); char* data = tbufGetData( &bw, false ); //------------------------ read ----------------------- SBufferReader br = tbufInitReader( data, size, false ); // read & print out all integers int32_t count = tbufReadInt32( &br ); for( int i = 0; i < count; i++ ) { printf( "%d\n", tbufReadInt32(&br) ); } // read & print out a string puts( tbufReadString(&br, NULL) ); // try read another integer, this result in an error as there no this integer tbufReadInt32( &br ); printf( "you should not see this message.\n" ); } CATCH( code ) { printf( "exception code is: %d, you will see this message after print out 5 integers and a string.\n", code ); } END_TRY tbufCloseWriter( &bw ); return 0; } */ typedef struct SBufferReader { bool endian; const char* data; size_t pos; size_t size; } SBufferReader; typedef struct SBufferWriter { bool endian; char* data; size_t pos; size_t size; void* (*allocator)( void*, size_t ); } SBufferWriter; //////////////////////////////////////////////////////////////////////////////// // common functions & macros for both reader & writer #define tbufTell( buf ) ((buf)->pos) //////////////////////////////////////////////////////////////////////////////// // reader functions & macros // *Endian*, if true, reader functions of primitive types will do 'ntoh' automatically #define tbufInitReader( Data, Size, Endian ) {.endian = (Endian), .data = (Data), .pos = 0, .size = ((Data) == NULL ? 0 :(Size))} size_t tbufSkip( SBufferReader* buf, size_t size ); const char* tbufRead( SBufferReader* buf, size_t size ); void tbufReadToBuffer( SBufferReader* buf, void* dst, size_t size ); const char* tbufReadString( SBufferReader* buf, size_t* len ); size_t tbufReadToString( SBufferReader* buf, char* dst, size_t size ); const char* tbufReadBinary( SBufferReader* buf, size_t *len ); size_t tbufReadToBinary( SBufferReader* buf, void* dst, size_t size ); bool tbufReadBool( SBufferReader* buf ); char tbufReadChar( SBufferReader* buf ); int8_t tbufReadInt8( SBufferReader* buf ); uint8_t tbufReadUint8( SBufferReader* buf ); int16_t tbufReadInt16( SBufferReader* buf ); uint16_t tbufReadUint16( SBufferReader* buf ); int32_t tbufReadInt32( SBufferReader* buf ); uint32_t tbufReadUint32( SBufferReader* buf ); int64_t tbufReadInt64( SBufferReader* buf ); uint64_t tbufReadUint64( SBufferReader* buf ); float tbufReadFloat( SBufferReader* buf ); double tbufReadDouble( SBufferReader* buf ); //////////////////////////////////////////////////////////////////////////////// // writer functions & macros // *Allocator*, function to allocate memory, will use 'realloc' if NULL // *Endian*, if true, writer functions of primitive types will do 'hton' automatically #define tbufInitWriter( Allocator, Endian ) {.endian = (Endian), .data = NULL, .pos = 0, .size = 0, .allocator = ((Allocator) == NULL ? realloc : (Allocator))} void tbufCloseWriter( SBufferWriter* buf ); void tbufEnsureCapacity( SBufferWriter* buf, size_t size ); size_t tbufReserve( SBufferWriter* buf, size_t size ); char* tbufGetData( SBufferWriter* buf, bool takeOver ); void tbufWrite( SBufferWriter* buf, const void* data, size_t size ); void tbufWriteAt( SBufferWriter* buf, size_t pos, const void* data, size_t size ); void tbufWriteStringLen( SBufferWriter* buf, const char* str, size_t len ); void tbufWriteString( SBufferWriter* buf, const char* str ); // the prototype of tbufWriteBinary and tbufWrite are identical // the difference is: tbufWriteBinary writes the length of the data to the buffer // first, then the actual data, which means the reader don't need to know data // size before read. Write only write the data itself, which means the reader // need to know data size before read. void tbufWriteBinary( SBufferWriter* buf, const void* data, size_t len ); void tbufWriteBool( SBufferWriter* buf, bool data ); void tbufWriteBoolAt( SBufferWriter* buf, size_t pos, bool data ); void tbufWriteChar( SBufferWriter* buf, char data ); void tbufWriteCharAt( SBufferWriter* buf, size_t pos, char data ); void tbufWriteInt8( SBufferWriter* buf, int8_t data ); void tbufWriteInt8At( SBufferWriter* buf, size_t pos, int8_t data ); void tbufWriteUint8( SBufferWriter* buf, uint8_t data ); void tbufWriteUint8At( SBufferWriter* buf, size_t pos, uint8_t data ); void tbufWriteInt16( SBufferWriter* buf, int16_t data ); void tbufWriteInt16At( SBufferWriter* buf, size_t pos, int16_t data ); void tbufWriteUint16( SBufferWriter* buf, uint16_t data ); void tbufWriteUint16At( SBufferWriter* buf, size_t pos, uint16_t data ); void tbufWriteInt32( SBufferWriter* buf, int32_t data ); void tbufWriteInt32At( SBufferWriter* buf, size_t pos, int32_t data ); void tbufWriteUint32( SBufferWriter* buf, uint32_t data ); void tbufWriteUint32At( SBufferWriter* buf, size_t pos, uint32_t data ); void tbufWriteInt64( SBufferWriter* buf, int64_t data ); void tbufWriteInt64At( SBufferWriter* buf, size_t pos, int64_t data ); void tbufWriteUint64( SBufferWriter* buf, uint64_t data ); void tbufWriteUint64At( SBufferWriter* buf, size_t pos, uint64_t data ); void tbufWriteFloat( SBufferWriter* buf, float data ); void tbufWriteFloatAt( SBufferWriter* buf, size_t pos, float data ); void tbufWriteDouble( SBufferWriter* buf, double data ); void tbufWriteDoubleAt( SBufferWriter* buf, size_t pos, double data ); #ifdef __cplusplus } #endif #endif /*_TD_UTIL_BUFFER_H*/