-
Notifications
You must be signed in to change notification settings - Fork 9
/
DBuffer.h
149 lines (119 loc) · 3.17 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
#ifndef _DBUFFER_H
#define _DBUFFER_H
#include "basics.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/*
DBuffer vs. DString
The difference is that with a DBuffer, if you AppendString() multiple times,
you will get null-terminators in between each string. With a DString,
the strings will be concatenated. You can override this behavior in a DBuffer
by calling AppendStringNoNull instead of AppendString, but there is no function
for inserting NULLs into a DString, as that doesn't make sense.
*/
#define DBUFFER_BUILTIN_SIZE 16
class DBuffer
{
public:
DBuffer();
~DBuffer();
void SetTo(const uint8_t *data, int length);
void SetTo(const char *string);
void SetTo(DBuffer *other);
void SetTo(DBuffer &other);
void AppendData(const uchar *data, int length);
void AppendString(const char *str);
void AppendStringNoNull(const char *str);
void AppendBool(bool value);
void AppendChar(uchar ch);
void Append8(uint8_t value);
void Append16(uint16_t value);
void Append24(uint32_t value);
void Append32(uint32_t value);
bool ReadTo(DBuffer *line, uchar ch, bool add_null=true);
void EnsureAlloc(int min_required);
void ReplaceUnprintableChars();
DBuffer &operator= (const DBuffer &other);
// ---------------------------------------
void Clear();
uint8_t *Data();
uint8_t *TakeData();
char *String();
int Length();
private:
uint8_t *fData;
int fLength;
int fAllocSize;
bool fAllocdExternal;
uint8_t fBuiltInData[DBUFFER_BUILTIN_SIZE];
};
inline void DBuffer::EnsureAlloc(int min_required)
{
if (min_required > fAllocSize)
{
fAllocSize = (min_required + (min_required >> 1));
if (fAllocdExternal)
{
fData = (uint8_t *)realloc(fData, fAllocSize);
}
else
{
fData = (uint8_t *)malloc(fAllocSize);
fAllocdExternal = true;
// compatibility with String() - copy the potential extra null-terminator
int copysize = (fLength + 1);
if (copysize > fAllocSize) copysize = fAllocSize;
memcpy(fData, fBuiltInData, copysize);
}
}
}
inline void DBuffer::Clear()
{
// free any external memory and switch back to builtin
if (fAllocdExternal)
{
free(fData);
fData = &fBuiltInData[0];
fAllocSize = DBUFFER_BUILTIN_SIZE;
fAllocdExternal = false;
}
fLength = 0;
}
inline void DBuffer::SetTo(const uint8_t *data, int length)
{
// SetTo from a portion of ourselves
if (data >= fData && data <= fData + (fLength - 1))
{
uint8_t *tempBuffer = (uint8_t *)malloc(length);
memcpy(tempBuffer, data, length);
SetTo(tempBuffer, length);
free(tempBuffer);
return;
}
if (fAllocdExternal && length < DBUFFER_BUILTIN_SIZE)
{
free(fData);
fData = &fBuiltInData[0];
fAllocSize = DBUFFER_BUILTIN_SIZE;
fAllocdExternal = false;
}
else if (length > fAllocSize)
{ // we are growing, so allocate more memory
if (fAllocdExternal) free(fData);
fAllocdExternal = true;
fAllocSize = (length + 16); // arbitrary, is just space for growing
fData = (uint8_t *)malloc(fAllocSize);
}
if (length) memcpy(fData, data, length);
fLength = length;
}
inline void DBuffer::AppendChar(uchar ch)
{
AppendData((uchar *)&ch, 1);
}
inline void DBuffer::Append8(uint8_t value)
{
AppendData((uchar *)&value, 1);
}
#endif