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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#ifndef __C_DATAPUMP_H__
#define __C_DATAPUMP_H__
#include <stdlib.h>
#include <memory.h>
#include <stddef.h>
#pragma intrinsic(memcpy,memset)
template<class T> class C_DATAPUMP {
private:
protected:
T *BufferBottom; // bottom of the physical buffer
T *BufferTop; // top of the physical buffer
T *BufferStart; // start of the logical buffer
T *BufferEnd; // end of the logical buffer
virtual void addItems(T *inputBuffer, size_t inputSize) { // inputSize = number of <T> records inputBuffer contains
if(inputBuffer && inputSize) {
memcpy(BufferEnd,inputBuffer,inputSize*sizeof(T)); // copy our records in
BufferEnd += inputSize;
if(BufferEnd >= BufferTop) BufferEnd = BufferBottom + (BufferEnd-BufferTop);
}
}
virtual void delItems(int where, size_t numItems) { // where: 0 = start, 1 = end
if(numItems > 0) {
if(numItems > size()) { // just void everything
BufferEnd = BufferStart;
} else {
if(where == 0) { // start
BufferStart += numItems;
if(BufferStart >= BufferTop) BufferStart = BufferBottom + (BufferTop-BufferStart);
} else if(where == 1) { // end
BufferEnd -= numItems;
if(BufferEnd < BufferBottom) BufferEnd = BufferTop - (BufferBottom-BufferEnd);
}
}
}
}
virtual void getItems(T *outputBuffer, size_t outputSize) { // outputSize = number of <T> records outputBuffer needs
if(outputBuffer && outputSize) {
memcpy(outputBuffer,BufferStart,outputSize*sizeof(T));
}
}
public:
C_DATAPUMP(int bufferSize) { // bufferSize = number of <T> records
BufferBottom = NULL;
BufferTop = NULL;
BufferStart = NULL;
BufferEnd = NULL;
resizeBuffer(bufferSize);
}
virtual ~C_DATAPUMP() {
if(getBufferSize() && BufferBottom) {
free(BufferBottom);
BufferBottom = NULL;
}
}
virtual void resizeBuffer(size_t bufferSize) { // bufferSize = number of <T> records
// this will invalidate any data in the buffer, so be careful when calling this function
if(bufferSize) {
if(getBufferSize() != bufferSize) {
if(BufferBottom && BufferTop && getBufferSize()) { // buffer is valid
if(getBufferSize() > bufferSize) { // buffer is getting smaller (will invalidate buffer)
BufferTop -= getBufferSize()-bufferSize;
invalidate();
} else { // buffer is getting larger (will _NOT_ invalidate buffer... nicely moves the data over =)
T *newBuffer = (T *)malloc(bufferSize * sizeof(T));
// new
BufferEnd = newBuffer + get(newBuffer,bufferSize);
free(BufferBottom);
BufferBottom = newBuffer;
BufferTop = BufferBottom + bufferSize;
BufferStart = BufferBottom;
/* old
T *bufptr = newBuffer;
int top = BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart; // number of <T> records at top of physical buffer
int bottom = BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom; // number of <T> records at bottom of physical buffer
if(top > 0) {
memcpy(bufptr,BufferStart,top*sizeof(T));
bufptr += top;
}
if(bottom > 0) {
memcpy(bufptr,BufferBottom,bottom*sizeof(T));
bufptr += bottom;
}
free(BufferBottom);
BufferBottom = newBuffer;
BufferTop = BufferBottom + bufferSize;
BufferStart = BufferBottom;
BufferEnd = bufptr;
*/
}
} else { // no buffer, create (invalidates the buffer... duh)
BufferBottom = (T *)malloc(bufferSize * sizeof(T));
BufferTop = BufferBottom + bufferSize;
invalidate();
}
}
}
}
virtual size_t size() { // will get the number of <T> records the logical buffer contains
return BufferEnd >= BufferStart ? BufferEnd-BufferStart : (BufferTop-BufferStart)+(BufferEnd-BufferBottom);
}
virtual size_t put(T *inputBuffer, size_t inputSize) { // inputSize = number of <T> records inputBuffer contains
// returns number of <T> records added to logical buffer
size_t retval = 0;
if(inputBuffer && inputSize) {
size_t fitting = ((BufferTop-BufferBottom)-1) - size(); // can't go over our logical boundary.... blah
if(fitting > inputSize) fitting = inputSize; // the entire thing can fit. yeay!
retval = fitting;
if(fitting > 0) {
T *bufptr = inputBuffer;
size_t top = BufferEnd >= BufferStart ? BufferTop-BufferEnd : 0; // number of <T> records free at top of physical buffer
size_t bottom = BufferEnd >= BufferStart ? BufferStart-BufferBottom : (BufferStart-BufferEnd); // number of <T> records free at bottom of physical buffer
if(top > 0) {
if(top > fitting) top = fitting;
addItems(bufptr,top);
fitting -= top;
bufptr += top;
}
if(bottom > 0 && fitting > 0) {
if(bottom > fitting) bottom = fitting;
addItems(bufptr,bottom);
}
}
}
return retval;
}
virtual size_t get(T *outputBuffer, size_t outputSize) { // outputSize = number of <T> records outputBuffer needs
// returns number of <T> records pulled from the logical buffer
size_t retval = 0;
if(outputBuffer && outputSize) {
size_t fitting = size();
if(fitting > outputSize) fitting = outputSize;
retval = fitting;
if(fitting > 0) {
T *bufptr = outputBuffer;
size_t top = BufferEnd >= BufferStart ? BufferEnd-BufferStart : BufferTop-BufferStart; // number of <T> records at top of physical buffer
size_t bottom = BufferEnd >= BufferStart ? 0 : BufferEnd-BufferBottom; // number of <T> records at bottom of physical buffer
if(top > 0) {
if(top > fitting) top = fitting;
getItems(bufptr,top);
delItems(0,top);
fitting -= top;
bufptr += top;
}
if(bottom > 0 && fitting > 0) {
if(bottom > fitting) bottom = fitting;
getItems(bufptr,bottom);
delItems(0,bottom);
}
}
}
return retval;
}
virtual size_t getBufferSize() { // returns the size of the physical buffer in <T> items
return BufferTop-BufferBottom;
}
virtual void invalidate() { // calling this will wipe all data in the buffer and reset the logical pointers
BufferStart = BufferEnd = BufferBottom;
}
};
#endif // !__C_DATAPUMP_H__
|