169 lines
6.8 KiB
C
169 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2020 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _TD_UTIL_BUFFER_H_
|
|
#define _TD_UTIL_BUFFER_H_
|
|
|
|
#include "os.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// usage example
|
|
/*
|
|
#include <stdio.h>
|
|
#include "texception.h"
|
|
|
|
int32_t main( int32_t 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( int32_t 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( int32_t 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)
|
|
|
|
/* ------------------------ BUFFER WRITER FUNCTIONS AND 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);
|
|
|
|
/* ------------------------ BUFFER READER FUNCTIONS AND 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);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /*_TD_UTIL_BUFFER_H_*/
|