forked from raduprv/Eternal-Lands
-
Notifications
You must be signed in to change notification settings - Fork 3
/
dbuffer.h
154 lines (128 loc) · 3.68 KB
/
dbuffer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#ifndef __dbuffer_h__
#define __dbuffer_h__
/*!
* \ingroup dbuffer
* \file dbuffer.h
* \brief Dynamic buffer implementation.
*
* A dynamic buffer is a buffer that reallocates more memory if needed to
* accomodate a certain data size. The reallocation is done in chunks.
*
* This dynamic buffer implementation only uses one structrure/pointer, so to
* ease manipulation.
*
* Basically you should do:
*
* dbuffer_t *mybuffer = dbuffer_new();
*
* mybuffer = dbuffer_append_data( mybuffer, somedatapointer, somedatasize );
*
* do_something_with_contents( mybuffer->data, mybuffer->current_size );
*
* dbuffer_destroy( mybuffer );
*
*
*/
#include <sys/types.h>
/**
\ingroup dbuffer
\brief Main dbuffer structure
The size of this "structure" is not fixed.
*/
typedef struct {
size_t alloc_size; /**< Current allocated size of buffer */
size_t current_size; /**< Current size used in buffer */
unsigned char data[0]; /**< Data placeholder */
} dbuffer_t;
/**
\ingroup dbuffer
\brief Default allocation chunk size.
*/
#define DBUFFER_CHUNK_SIZE 128
#ifndef DOXYGEN_SHOULD_SKIP_THIS
# define DBUFFER_ALIGN(x) (((x)+(DBUFFER_CHUNK_SIZE)-1)&~(DBUFFER_CHUNK_SIZE-1))
# define DBUFFER_HDRSIZE (sizeof(size_t)+sizeof(size_t))
# ifndef UNUSED_RESULT_DECL
# ifdef __GNUC__
# define UNUSED_RESULT_DECL __attribute__ ((warn_unused_result))
# else
# define UNUSED_RESULT_DECL
# endif
# endif // UNUSED_RESULT_DECL
#endif //DOXYGEN_SHOULD_SKIP_THIS
/**
\ingroup dbuffer
\brief Destroy a dbuffer
\param dbuf The dbuffer to destroy
\returns nothing
*/
static __inline__ void dbuffer_destroy( dbuffer_t *dbuf )
{
free(dbuf);
}
/**
\ingroup dbuffer
\brief Append data to a dbuffer
Append the specified data (bytes) to dbuffer. Make sure you reassign your dbuffer to the return value,
cause it can be reallocated.
\param dbuf The dbuffer
\param data The data to append
\param datalen The data size
\returns The dbuffer (maybe a different pointer)
*/
static __inline__ UNUSED_RESULT_DECL dbuffer_t *dbuffer_append_data( dbuffer_t *dbuf, const unsigned char *data, size_t datalen )
{
size_t next_alloc_size;
if ( NULL!= dbuf ) {
next_alloc_size = DBUFFER_ALIGN( dbuf->current_size+datalen+DBUFFER_HDRSIZE );
if (next_alloc_size>dbuf->alloc_size) {
dbuf = (dbuffer_t*)realloc((void*)dbuf, next_alloc_size);
if (NULL==dbuf)
return NULL;
dbuf->alloc_size = next_alloc_size;
}
} else {
next_alloc_size = DBUFFER_ALIGN( datalen+DBUFFER_HDRSIZE );
dbuf = (dbuffer_t*)malloc( next_alloc_size );
if (NULL==dbuf)
return NULL;
dbuf->alloc_size = next_alloc_size;
dbuf->current_size = 0;
}
if (data) {
memcpy( dbuf->data + dbuf->current_size, data, datalen );
dbuf->current_size += datalen;
}
return dbuf;
}
/**
\ingroup dbuffer
\brief Create a new (empty) dbuffer
\returns The newly created dbuffer.
*/
static __inline__ dbuffer_t *dbuffer_new(void)
{
return dbuffer_append_data(NULL, NULL, 0); /* Will alloc a new buffer */
}
/**
\ingroup dbuffer
\brief Create a new dbuffer, and preallocate size for it
\param datalen The size to preallocate
\returns The newly created dbuffer.
*/
static __inline__ dbuffer_t *dbuffer_sized(size_t datalen)
{
return dbuffer_append_data(NULL, NULL, datalen); /* Will alloc a new buffer */
}
/**
\ingroup dbuffer
\brief Create a new dbuffer, and append the specified data
\param data The data to append to newly created buffer
\param datalen The size of data
\returns The newly created dbuffer.
*/
static __inline__ dbuffer_t *dbuffer_new_with_data( const unsigned char *data, size_t datalen )
{
return dbuffer_append_data(NULL, data, datalen); /* Will alloc a new buffer */
}
#endif