Mcucpp

Форк
0
/
data_buffer.cpp 
254 строки · 4.6 Кб
1

2
#include <data_buffer.h>
3
#include <new>
4

5
using namespace Mcucpp;
6

7
uint8_t DataBufferBase::_dummy = 0;
8

9
DataChunk* DataChunk::GetNew(size_t size)
10
{
11
	size_t sizeRequired = (size + sizeof(DataChunk) + 16) & ~0x0f;
12
	void * ptr = new (std::nothrow) uint8_t[sizeRequired];
13
	size_t storage = sizeRequired - sizeof(DataChunk);
14
	if(!ptr)
15
		return nullptr;
16
	uint8_t *data = (uint8_t *)ptr + sizeof(DataChunk);
17

18
	DataChunk * dataChunk = new (ptr)DataChunk(data, size, storage);
19
	return dataChunk;
20
}
21

22
DataChunk* DataChunk::GetNew(const void *data, size_t size)
23
{
24
	DataChunk* buffer = GetNew(size);
25
	if(!buffer)
26
		return 0;
27
	memcpy(buffer->_data, data, size);
28
	return buffer;
29
}
30

31
void DataChunk::Release(DataChunk * data)
32
{
33
    // release only buffers created with GetNew
34
    if(data->_data == reinterpret_cast<uint8_t*>(data) + sizeof(DataChunk) )
35
    {
36
         delete [] (uint8_t *)data;
37
    }
38
}
39

40
void DataChunk::ReleaseRecursive(DataChunk * buffer)
41
{
42
	DataChunk *next;
43
	while(buffer)
44
	{
45
		next = buffer->Next();
46
		DataChunk::Release(buffer);
47
		buffer = next;
48
	}
49
}
50

51
DataChunk* DataChunk::Prev(DataChunk* first) const
52
{
53
	while(first)
54
	{
55
	    if(first->Next() == this)
56
        {
57
            return first;
58
        }
59
		first = first->Next();
60
	}
61
	return nullptr;
62
}
63

64

65
DataBufferBase::DataBufferBase()
66
	:_first(0),
67
	_current(0),
68
	_pos(0)
69
{
70

71
}
72

73
DataBufferBase::DataBufferBase(DataBufferBase &&rhs) noexcept
74
{
75
	_first = rhs._first;
76
	_current = rhs._current;
77
	_pos = rhs._pos;
78
	rhs._first = 0;
79
	rhs._current = 0;
80
	rhs._pos = 0;
81
}
82

83
DataBufferBase& DataBufferBase::operator=(DataBufferBase&& rhs) noexcept
84
{
85
    Clear();
86
	_first = rhs._first;
87
	_current = rhs._current;
88
	_pos = rhs._pos;
89
	rhs._first = 0;
90
	rhs._current = 0;
91
	rhs._pos = 0;
92
	return *this;
93
}
94

95

96
DataBufferBase::~DataBufferBase()
97
{
98
	Clear();
99
}
100

101
void DataBufferBase::Clear()
102
{
103
	DataChunk *buffer = _first;
104
	_current = _first = 0;
105
	DataChunk::ReleaseRecursive(buffer);
106
}
107

108
bool DataBufferBase::InsertFront(size_t size)
109
{
110
	DataChunk* buffer = 0;
111
	DataChunk* next;
112
	do
113
	{
114
		if(!buffer)
115
			buffer = DataChunk::GetNew(size);
116
		if(!buffer)
117
			return false;
118
		next = _first;
119
		buffer->_next = next;
120
	}while(!Atomic::CompareExchange(&_first, next, buffer));
121

122
	return true;
123
}
124

125
DataChunk *DataChunk::FindLast(DataChunk *first)
126
{
127
	if(first)
128
	{
129
		while(first->Next())
130
		{
131
			first = first->Next();
132
		}
133
	}
134
	return first;
135
}
136

137
bool DataBufferBase::InsertBack(size_t size)
138
{
139
	DataChunk *last, *buffer = 0;
140
	DataChunk** pnext;
141
	do
142
	{
143
		last = DataChunk::FindLast(_first);
144
		pnext = last ? &(last->_next) : &_first;
145
		if(last)
146
		{
147
			uint16_t lastSize = last->Size();
148
			if(last->Capacity() >= lastSize + size)
149
			{
150
				if(!Atomic::CompareExchange(&last->_size, lastSize, (uint16_t)(lastSize + size)))
151
					continue;
152
				if(buffer)
153
					DataChunk::Release(buffer);
154
				return true;
155
			}
156
		}
157
		if(!buffer)
158
			buffer = DataChunk::GetNew(size);
159
		if(!buffer)
160
			return false;
161
	}while(!Atomic::CompareExchange(pnext, (DataChunk *)0, buffer));
162

163
	return true;
164
}
165

166
void DataBufferBase::AttachBack(DataChunk* buffer)
167
{
168
	DataChunk *last;
169
	DataChunk** pnext;
170
	do
171
	{
172
		last = DataChunk::FindLast(_first);
173
		pnext = last ? &(last->_next) : &_first;
174
	}while(!Atomic::CompareExchange(pnext, (DataChunk *)0, buffer));
175
}
176

177
void DataBufferBase::AttachFront(DataChunk* buffer)
178
{
179
	DataChunk* next;
180
	do
181
	{
182
		next = _first;
183
		buffer->_next = next;
184
	}while(!Atomic::CompareExchange(&_first, next, buffer));
185
}
186

187
DataChunk* DataBufferBase::DetachFront()
188
{
189
	DataChunk* first, *next;
190
	do
191
	{
192
		first = _first;
193
		next = first->_next;
194
	}while(!Atomic::CompareExchange(&_first, first, next));
195
	return first;
196
}
197

198

199
bool DataBufferBase::Seek(size_t pos)
200
{
201
	DataChunk *current = _first;
202
	while(current && current->Size() <= pos)
203
	{
204
		pos -= current->Size();
205
		current = current->Next();
206
	}
207
	if(!current)
208
	{
209
		return false;
210
	}
211
	_pos = pos;
212
	_current = current;
213
	return true;
214
}
215

216
size_t DataBufferBase::Tell()
217
{
218
	DataChunk *current = _first;
219
	size_t result = _pos;
220

221
	while(current && current != _current)
222
	{
223
		result += current->Size();
224
		current = current->Next();
225
	}
226
	return result;
227
}
228

229
size_t DataBufferBase::Size()
230
{
231
	DataChunk *current = _first;
232
	size_t totalSize = 0;
233
	if(current)
234
	{
235
		do
236
		{
237
			totalSize += current->Size();
238
			current = current->Next();
239
		}while(current);
240
	}
241
	return totalSize;
242
}
243

244
unsigned DataBufferBase::Parts()
245
{
246
	DataChunk *current = _first;
247
	unsigned parts = 0;
248
	while(current)
249
	{
250
		++parts;
251
		current = current->Next();
252
	}
253

254
	return parts;
255
}
256

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.