aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/DSP/dsp_sc/Include/c_datapump.h
blob: bcf3863b1584820157503f55116a1970250aadd0 (plain) (blame)
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__