|
20 | 20 |
|
21 | 21 | #include "cbuf.h"
|
22 | 22 |
|
| 23 | +#if CONFIG_DISABLE_HAL_LOCKS |
| 24 | +#define CBUF_MUTEX_CREATE() |
| 25 | +#define CBUF_MUTEX_LOCK() |
| 26 | +#define CBUF_MUTEX_UNLOCK() |
| 27 | +#define CBUF_MUTEX_DELETE() |
| 28 | +#else |
| 29 | +#define CBUF_MUTEX_CREATE() if(_lock == NULL){_lock = xSemaphoreCreateMutex(); if(_lock == NULL){log_e("failed to create mutex");}} |
| 30 | +#define CBUF_MUTEX_LOCK() if(_lock != NULL){xSemaphoreTakeRecursive(_lock, portMAX_DELAY);} |
| 31 | +#define CBUF_MUTEX_UNLOCK() if(_lock != NULL){xSemaphoreGiveRecursive(_lock);} |
| 32 | +#define CBUF_MUTEX_DELETE() if(_lock != NULL){SemaphoreHandle_t l = _lock; _lock = NULL; vSemaphoreDelete(l);} |
| 33 | +#endif |
| 34 | + |
23 | 35 | cbuf::cbuf(size_t size) :
|
24 |
| - next(NULL), _size(size+1), _buf(new char[size+1]), _bufend(_buf + size + 1), _begin(_buf), _end(_begin) |
| 36 | + next(NULL), _buf(xRingbufferCreate(size, RINGBUF_TYPE_BYTEBUF)) |
25 | 37 | {
|
| 38 | + if(_buf == NULL) { |
| 39 | + log_e("failed to allocate ring buffer"); |
| 40 | + } |
| 41 | + CBUF_MUTEX_CREATE(); |
26 | 42 | }
|
27 | 43 |
|
28 | 44 | cbuf::~cbuf()
|
29 | 45 | {
|
30 |
| - delete[] _buf; |
| 46 | + CBUF_MUTEX_LOCK(); |
| 47 | + if(_buf != NULL){ |
| 48 | + RingbufHandle_t b = _buf; |
| 49 | + _buf = NULL; |
| 50 | + vRingbufferDelete(b); |
| 51 | + } |
| 52 | + CBUF_MUTEX_UNLOCK(); |
| 53 | + CBUF_MUTEX_DELETE(); |
31 | 54 | }
|
32 | 55 |
|
33 | 56 | size_t cbuf::resizeAdd(size_t addSize)
|
34 | 57 | {
|
35 |
| - return resize(_size + addSize); |
| 58 | + return resize(size() + addSize); |
36 | 59 | }
|
37 | 60 |
|
38 | 61 | size_t cbuf::resize(size_t newSize)
|
39 | 62 | {
|
| 63 | + CBUF_MUTEX_LOCK(); |
| 64 | + size_t _size = size(); |
| 65 | + if(newSize == _size) { |
| 66 | + return _size; |
| 67 | + } |
40 | 68 |
|
41 |
| - size_t bytes_available = available(); |
42 |
| - newSize += 1; |
43 | 69 | // not lose any data
|
44 | 70 | // if data can be lost use remove or flush before resize
|
45 |
| - if((newSize < bytes_available) || (newSize == _size)) { |
| 71 | + size_t bytes_available = available(); |
| 72 | + if(newSize < bytes_available) { |
| 73 | + CBUF_MUTEX_UNLOCK(); |
| 74 | + log_e("new size is less than the currently available data size"); |
46 | 75 | return _size;
|
47 | 76 | }
|
48 | 77 |
|
49 |
| - char *newbuf = new char[newSize]; |
50 |
| - char *oldbuf = _buf; |
51 |
| - |
52 |
| - if(!newbuf) { |
| 78 | + RingbufHandle_t newbuf = xRingbufferCreate(newSize, RINGBUF_TYPE_BYTEBUF); |
| 79 | + if(newbuf == NULL) { |
| 80 | + CBUF_MUTEX_UNLOCK(); |
| 81 | + log_e("failed to allocate new ring buffer"); |
53 | 82 | return _size;
|
54 | 83 | }
|
55 | 84 |
|
56 |
| - if(_buf) { |
57 |
| - read(newbuf, bytes_available); |
58 |
| - memset((newbuf + bytes_available), 0x00, (newSize - bytes_available)); |
| 85 | + if(_buf != NULL) { |
| 86 | + if(bytes_available){ |
| 87 | + char * old_data = (char *)malloc(bytes_available); |
| 88 | + if(old_data == NULL){ |
| 89 | + vRingbufferDelete(newbuf); |
| 90 | + CBUF_MUTEX_UNLOCK(); |
| 91 | + log_e("failed to allocate temporary buffer"); |
| 92 | + return _size; |
| 93 | + } |
| 94 | + bytes_available = read(old_data, bytes_available); |
| 95 | + if(!bytes_available){ |
| 96 | + free(old_data); |
| 97 | + vRingbufferDelete(newbuf); |
| 98 | + CBUF_MUTEX_UNLOCK(); |
| 99 | + log_e("failed to read previous data"); |
| 100 | + return _size; |
| 101 | + } |
| 102 | + if(xRingbufferSend(newbuf, (void*)old_data, bytes_available, 0) != pdTRUE){ |
| 103 | + write(old_data, bytes_available); |
| 104 | + free(old_data); |
| 105 | + vRingbufferDelete(newbuf); |
| 106 | + CBUF_MUTEX_UNLOCK(); |
| 107 | + log_e("failed to restore previous data"); |
| 108 | + return _size; |
| 109 | + } |
| 110 | + free(old_data); |
| 111 | + } |
| 112 | + |
| 113 | + RingbufHandle_t b = _buf; |
| 114 | + _buf = newbuf; |
| 115 | + vRingbufferDelete(b); |
| 116 | + } else { |
| 117 | + _buf = newbuf; |
59 | 118 | }
|
60 |
| - |
61 |
| - _begin = newbuf; |
62 |
| - _end = newbuf + bytes_available; |
63 |
| - _bufend = newbuf + newSize; |
64 |
| - _size = newSize; |
65 |
| - |
66 |
| - _buf = newbuf; |
67 |
| - delete[] oldbuf; |
68 |
| - |
69 |
| - return _size; |
| 119 | + CBUF_MUTEX_UNLOCK(); |
| 120 | + return newSize; |
70 | 121 | }
|
71 | 122 |
|
72 | 123 | size_t cbuf::available() const
|
73 | 124 | {
|
74 |
| - if(_end >= _begin) { |
75 |
| - return _end - _begin; |
| 125 | + size_t available = 0; |
| 126 | + if(_buf != NULL){ |
| 127 | + vRingbufferGetInfo(_buf, NULL, NULL, NULL, NULL, (UBaseType_t *)&available); |
76 | 128 | }
|
77 |
| - return _size - (_begin - _end); |
| 129 | + return available; |
78 | 130 | }
|
79 | 131 |
|
80 | 132 | size_t cbuf::size()
|
81 | 133 | {
|
| 134 | + size_t _size = 0; |
| 135 | + if(_buf != NULL){ |
| 136 | + _size = xRingbufferGetMaxItemSize(_buf); |
| 137 | + } |
82 | 138 | return _size;
|
83 | 139 | }
|
84 | 140 |
|
85 | 141 | size_t cbuf::room() const
|
86 | 142 | {
|
87 |
| - if(_end >= _begin) { |
88 |
| - return _size - (_end - _begin) - 1; |
| 143 | + size_t _room = 0; |
| 144 | + if(_buf != NULL){ |
| 145 | + _room = xRingbufferGetCurFreeSize(_buf); |
89 | 146 | }
|
90 |
| - return _begin - _end - 1; |
| 147 | + return _room; |
91 | 148 | }
|
92 | 149 |
|
93 |
| -int cbuf::peek() |
| 150 | +bool cbuf::empty() const |
94 | 151 | {
|
95 |
| - if(empty()) { |
96 |
| - return -1; |
97 |
| - } |
| 152 | + return available() == 0; |
| 153 | +} |
98 | 154 |
|
99 |
| - return static_cast<int>(*_begin); |
| 155 | +bool cbuf::full() const |
| 156 | +{ |
| 157 | + return room() == 0; |
| 158 | +} |
| 159 | + |
| 160 | +int cbuf::peek() |
| 161 | +{ |
| 162 | + return -1; |
100 | 163 | }
|
101 | 164 |
|
102 | 165 | size_t cbuf::peek(char *dst, size_t size)
|
103 | 166 | {
|
104 |
| - size_t bytes_available = available(); |
105 |
| - size_t size_to_read = (size < bytes_available) ? size : bytes_available; |
106 |
| - size_t size_read = size_to_read; |
107 |
| - char * begin = _begin; |
108 |
| - if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { |
109 |
| - size_t top_size = _bufend - _begin; |
110 |
| - memcpy(dst, _begin, top_size); |
111 |
| - begin = _buf; |
112 |
| - size_to_read -= top_size; |
113 |
| - dst += top_size; |
114 |
| - } |
115 |
| - memcpy(dst, begin, size_to_read); |
116 |
| - return size_read; |
| 167 | + return 0; |
117 | 168 | }
|
118 | 169 |
|
119 | 170 | int cbuf::read()
|
120 | 171 | {
|
121 |
| - if(empty()) { |
| 172 | + char result = 0; |
| 173 | + if(!read(&result, 1)){ |
122 | 174 | return -1;
|
123 | 175 | }
|
124 |
| - |
125 |
| - char result = *_begin; |
126 |
| - _begin = wrap_if_bufend(_begin + 1); |
127 | 176 | return static_cast<int>(result);
|
128 | 177 | }
|
129 | 178 |
|
130 | 179 | size_t cbuf::read(char* dst, size_t size)
|
131 | 180 | {
|
| 181 | + CBUF_MUTEX_LOCK(); |
132 | 182 | size_t bytes_available = available();
|
| 183 | + if(!bytes_available || !size){ |
| 184 | + CBUF_MUTEX_UNLOCK(); |
| 185 | + return 0; |
| 186 | + } |
133 | 187 | size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
134 |
| - size_t size_read = size_to_read; |
135 |
| - if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { |
136 |
| - size_t top_size = _bufend - _begin; |
137 |
| - memcpy(dst, _begin, top_size); |
138 |
| - _begin = _buf; |
139 |
| - size_to_read -= top_size; |
140 |
| - dst += top_size; |
| 188 | + size_t size_read = 0; |
| 189 | + size_t received_size = 0; |
| 190 | + uint8_t *received_buff = (uint8_t *)xRingbufferReceiveUpTo(_buf, &received_size, 0, size_to_read); |
| 191 | + if (received_buff != NULL) { |
| 192 | + if(dst != NULL){ |
| 193 | + memcpy(dst, received_buff, received_size); |
| 194 | + } |
| 195 | + vRingbufferReturnItem(rx_ring_buf, received_buff); |
| 196 | + size_read = received_size; |
| 197 | + size_to_read -= received_size; |
| 198 | + // wrap around data |
| 199 | + if(size_to_read){ |
| 200 | + received_size = 0; |
| 201 | + received_buff = (uint8_t *)xRingbufferReceiveUpTo(_buf, &received_size, 0, size_to_read); |
| 202 | + if (received_buff != NULL) { |
| 203 | + if(dst != NULL){ |
| 204 | + memcpy(dst+size_read, received_buff, received_size); |
| 205 | + } |
| 206 | + vRingbufferReturnItem(rx_ring_buf, received_buff); |
| 207 | + size_read += received_size; |
| 208 | + } else { |
| 209 | + log_e("failed to read wrap around data from ring buffer"); |
| 210 | + } |
| 211 | + } |
| 212 | + } else { |
| 213 | + log_e("failed to read from ring buffer"); |
141 | 214 | }
|
142 |
| - memcpy(dst, _begin, size_to_read); |
143 |
| - _begin = wrap_if_bufend(_begin + size_to_read); |
| 215 | + CBUF_MUTEX_UNLOCK(); |
144 | 216 | return size_read;
|
145 | 217 | }
|
146 | 218 |
|
147 | 219 | size_t cbuf::write(char c)
|
148 | 220 | {
|
149 |
| - if(full()) { |
150 |
| - return 0; |
151 |
| - } |
152 |
| - |
153 |
| - *_end = c; |
154 |
| - _end = wrap_if_bufend(_end + 1); |
155 |
| - return 1; |
| 221 | + return write(&c, 1); |
156 | 222 | }
|
157 | 223 |
|
158 | 224 | size_t cbuf::write(const char* src, size_t size)
|
159 | 225 | {
|
| 226 | + CBUF_MUTEX_LOCK(); |
160 | 227 | size_t bytes_available = room();
|
| 228 | + if(!bytes_available || !size){ |
| 229 | + CBUF_MUTEX_UNLOCK(); |
| 230 | + return 0; |
| 231 | + } |
161 | 232 | size_t size_to_write = (size < bytes_available) ? size : bytes_available;
|
162 |
| - size_t size_written = size_to_write; |
163 |
| - if(_end >= _begin && size_to_write > (size_t) (_bufend - _end)) { |
164 |
| - size_t top_size = _bufend - _end; |
165 |
| - memcpy(_end, src, top_size); |
166 |
| - _end = _buf; |
167 |
| - size_to_write -= top_size; |
168 |
| - src += top_size; |
| 233 | + if(xRingbufferSend(rx_ring_buf, (void*)src, size_to_write, 0) != pdTRUE){ |
| 234 | + CBUF_MUTEX_UNLOCK(); |
| 235 | + log_e("failed to write to ring buffer"); |
| 236 | + return 0; |
169 | 237 | }
|
170 |
| - memcpy(_end, src, size_to_write); |
171 |
| - _end = wrap_if_bufend(_end + size_to_write); |
172 |
| - return size_written; |
| 238 | + CBUF_MUTEX_UNLOCK(); |
| 239 | + return size_to_write; |
173 | 240 | }
|
174 | 241 |
|
175 | 242 | void cbuf::flush()
|
176 | 243 | {
|
177 |
| - _begin = _buf; |
178 |
| - _end = _buf; |
| 244 | + read(NULL, available()); |
179 | 245 | }
|
180 | 246 |
|
181 | 247 | size_t cbuf::remove(size_t size)
|
182 | 248 | {
|
| 249 | + CBUF_MUTEX_LOCK(); |
183 | 250 | size_t bytes_available = available();
|
184 |
| - if(size >= bytes_available) { |
185 |
| - flush(); |
186 |
| - return 0; |
187 |
| - } |
188 |
| - size_t size_to_remove = (size < bytes_available) ? size : bytes_available; |
189 |
| - if(_end < _begin && size_to_remove > (size_t) (_bufend - _begin)) { |
190 |
| - size_t top_size = _bufend - _begin; |
191 |
| - _begin = _buf; |
192 |
| - size_to_remove -= top_size; |
| 251 | + if(bytes_available && size){ |
| 252 | + size_t size_to_remove = (size < bytes_available) ? size : bytes_available; |
| 253 | + bytes_available -= read(NULL, size_to_remove); |
193 | 254 | }
|
194 |
| - _begin = wrap_if_bufend(_begin + size_to_remove); |
195 |
| - return available(); |
| 255 | + CBUF_MUTEX_UNLOCK(); |
| 256 | + return bytes_available; |
196 | 257 | }
|
0 commit comments