picox  0.1
xcircular_buffer.h
[詳解]
1 
14 /*
15  * License: MIT license
16  * Copyright (c) <2016> <MaskedW [maskedw00@gmail.com]>
17  *
18  * Permission is hereby granted, free of charge, to any person
19  * obtaining a copy of this software and associated documentation
20  * files (the "Software"), to deal in the Software without
21  * restriction, including without limitation the rights to use, copy,
22  * modify, merge, publish, distribute, sublicense, and/or sell copies
23  * of the Software, and to permit persons to whom the Software is
24  * furnished to do so, subject to the following conditions:
25  *
26  * The above copyright notice and this permission notice shall be
27  * included in all copies or substantial portions of the Software.
28  *
29  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
33  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
34  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
35  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36  * SOFTWARE.
37  */
38 
39 
40 #ifndef picox_container_xcircular_buffer_h_
41 #define picox_container_xcircular_buffer_h_
42 
43 
44 #include <picox/core/xcore.h>
45 
46 
55 #ifdef __cplusplus
56 extern "C" {
57 #endif /* __cplusplus */
58 
59 
60 /* 内部処理用のマクロ */
61 #define XCBUF__CAPACITY() ((size_t)(self->m_end - self->m_buff))
62 #define XCBUF__ADD(p, n) ((p) + ((n) < (size_t)(self->m_end - (p)) ? (n) : (n) - XCBUF__CAPACITY()))
63 #define XCBUf__SUB(p, n) ((p) - ((n) > ((p) - self->m_buff) ? (n) - XCBUF__CAPACITY() : (n)))
64 #define XCBUF__DECREMENT(p) do { if (p == self->m_buff) p = self->m_end; --p; } while (0)
65 #define XCBUF__INCREMENT(p) do { if (++p == self->m_end) p = self->m_buff; } while (0)
66 
67 
70 typedef struct
71 {
73  uint8_t* m_buff;
74  uint8_t* m_end;
75  uint8_t* m_first;
76  uint8_t* m_last;
77  size_t m_size;
78  bool m_is_heapdata;
80 
81 
82 
90 static inline bool
91 xcbuf_init(XCircularBuffer* self, void* buffer, size_t capacity)
92 {
93  if (!buffer)
94  {
95  buffer = (uint8_t*)x_malloc(capacity);
96  if (!buffer)
97  return false;
98  self->m_is_heapdata = true;
99  }
100  self->m_buff = (uint8_t*)buffer;
101  self->m_end = self->m_buff + capacity;
102  self->m_first = self->m_last = self->m_buff;
103  self->m_size = 0;
104 
105  return true;
106 }
107 
108 
111 static inline void
113 {
114  if (self->m_is_heapdata)
115  x_free(self->m_buff);
116  self->m_is_heapdata = false;
117  self->m_buff = NULL;
118 }
119 
120 
123 static inline void
125 {
126  self->m_first = self->m_last = self->m_buff;
127  self->m_size = 0;
128 }
129 
130 
133 static inline uint8_t*
135 {
136  return self->m_buff;
137 }
138 
139 
142 static inline const uint8_t*
144 {
145  return self->m_buff;
146 }
147 
148 
156 static inline const uint8_t*
157 xcbuf_array_one(const XCircularBuffer* self, size_t* o_size)
158 {
159  const uint8_t* p = ((self->m_last <= self->m_first) && (self->m_size != 0)) ?
160  self->m_end : self->m_last;
161  *o_size = p - self->m_first;
162  return self->m_first;
163 }
164 
165 
168 static inline const uint8_t*
169 xcbuf_array_two(const XCircularBuffer* self, size_t* o_size)
170 {
171  *o_size = ((self->m_last <= self->m_first) && (self->m_size != 0)) ?
172  self->m_last - self->m_buff : 0;
173  return self->m_buff;
174 }
175 
176 
179 static inline uint8_t*
181 {
182  if (self->m_size == 0)
183  return NULL;
184 
185  if ((self->m_first < self->m_last) || (self->m_last == self->m_buff))
186  return self->m_first;
187 
188  uint8_t* src = self->m_first;
189  uint8_t* dest = self->m_buff;
190  size_t moved = 0;
191  uint8_t* first;
192  uint8_t tmp;
193  size_t i;
194  for (first = self->m_first; dest < src; src = first)
195  {
196  for (i = 0; src < self->m_end; ++src, ++dest, ++moved, ++i)
197  {
198  if (moved == self->m_size)
199  {
200  first = dest;
201  break;
202  }
203  if (dest == first)
204  {
205  first += i;
206  break;
207  }
208  tmp = *src;
209  *src = *dest;
210  *dest = tmp;
211  }
212  }
213 
214  self->m_first = self->m_buff;
215  self->m_last = XCBUF__ADD(self->m_buff, self->m_size);
216  return self->m_buff;
217 }
218 
219 
222 static inline bool
224 {
225  return (self->m_first < self->m_last) || (self->m_last == self->m_buff);
226 }
227 
228 
231 static inline size_t
233 {
234  return self->m_size;
235 }
236 
237 
240 static inline bool
242 {
243  return self->m_size == 0;
244 }
245 
246 
249 static inline size_t
251 {
252  return XCBUF__CAPACITY();
253 }
254 
255 
258 static inline bool
260 {
261  return XCBUF__CAPACITY() == self->m_size;
262 }
263 
264 
267 static inline size_t
269 {
270  return XCBUF__CAPACITY() - self->m_size;
271 }
272 
273 
278 static inline void
279 xcbuf_push_back(XCircularBuffer* self, uint8_t value)
280 {
281  if (xcbuf_full(self))
282  {
283  *(self->m_last) = value;
284  XCBUF__INCREMENT(self->m_last);
285  self->m_first = self->m_last;
286  }
287  else
288  {
289  *(self->m_last) = value;
290  XCBUF__INCREMENT(self->m_last);
291  self->m_size++;
292  }
293 }
294 
295 
300 static inline void
301 xcbuf_push_back_n(XCircularBuffer* self, const void* src, size_t n)
302 {
303  const size_t reserved = xcbuf_reserve(self);
304  const size_t nn = (reserved >= n) ? n : reserved;
305  size_t i;
306  const uint8_t* p = (const uint8_t*)src;
307 
308  for (i = 0; i < nn; i++)
309  {
310  *(self->m_last) = *p++;
311  XCBUF__INCREMENT(self->m_last);
312  self->m_size++;
313  }
314 
315  for (; i < n; i++)
316  {
317  *(self->m_last) = *p++;
318  XCBUF__INCREMENT(self->m_last);
319  self->m_first = self->m_last;
320  }
321 }
322 
323 
328 static inline void
329 xcbuf_push_front(XCircularBuffer* self, uint8_t value)
330 {
331  if (xcbuf_full(self))
332  {
333  XCBUF__DECREMENT(self->m_first);
334  *(self->m_first) = value;
335  self->m_last = self->m_first;
336  }
337  else
338  {
339  XCBUF__DECREMENT(self->m_first);
340  *(self->m_first) = value;
341  self->m_size++;
342  }
343 }
344 
345 
350 static inline void
351 xcbuf_push_front_n(XCircularBuffer* self, const void* src, size_t n)
352 {
353  const size_t reserved = xcbuf_reserve(self);
354  const size_t nn = (reserved >= n) ? n : reserved;
355  const uint8_t* p = (const uint8_t*)(src);
356  size_t i;
357 
358  for (i = 0; i < nn; i++)
359  {
360  XCBUF__DECREMENT(self->m_first);
361  *(self->m_first) = *p++;
362  self->m_size++;
363  }
364 
365  for (; i < n; i++)
366  {
367  XCBUF__DECREMENT(self->m_first);
368  *(self->m_first) = *p++;
369  self->m_last = self->m_first;
370  }
371 }
372 
373 
376 static inline uint8_t
378 {
379  const uint8_t* p = self->m_last;
380  XCBUF__DECREMENT(p);
381  return *p;
382 }
383 
384 
387 static inline uint8_t
389 {
390  return *(self->m_first);
391 }
392 
393 
396 static inline uint8_t
398 {
399  XCBUF__DECREMENT(self->m_last);
400  const uint8_t ret = *(self->m_last);
401  self->m_size--;
402  return ret;
403 }
404 
405 
408 static inline uint8_t
410 {
411  const uint8_t ret = *(self->m_first);
412  XCBUF__INCREMENT(self->m_first);
413  self->m_size--;
414  return ret;
415 }
416 
417 
422 static inline void
423 xcbuf_pop_front_n(XCircularBuffer* self, void* dst, size_t n)
424 {
425  size_t i;
426  uint8_t* p;
427  if (dst)
428  {
429  p = (uint8_t*)dst;
430  for (i = 0; i < n; i++)
431  {
432  *p++ = *(self->m_first);
433  XCBUF__INCREMENT(self->m_first);
434  }
435  }
436  else
437  {
438  for (i = 0; i < n; i++)
439  {
440  XCBUF__INCREMENT(self->m_first);
441  }
442  }
443  self->m_size -= n;
444 }
445 
446 
451 static inline void
452 xcbuf_pop_back_n(XCircularBuffer* self, void* dst, size_t n)
453 {
454  size_t i;
455  uint8_t* p;
456  if (dst)
457  {
458  p = (uint8_t*)dst;
459  for (i = 0; i < n; i++)
460  {
461  XCBUF__DECREMENT(self->m_last);
462  *p++ = *(self->m_last);
463  }
464  }
465  else
466  {
467  for (i = 0; i < n; i++)
468  {
469  XCBUF__DECREMENT(self->m_last);
470  }
471  }
472  self->m_size -= n;
473 }
474 
475 
478 static inline void
479 xcbuf_copy_to_mem(const XCircularBuffer* self, size_t pos, void* dst, size_t n)
480 {
481  const uint8_t* src = XCBUF__ADD(self->m_first, pos);
482  uint8_t* p = (uint8_t*)dst;
483  size_t i;
484  for (i = 0; i < n; i++)
485  {
486  *p++ = *src;
487  XCBUF__INCREMENT(src);
488  }
489 
490 }
491 
492 
493 #undef XCBUF__CAPACITY
494 #undef XCBUF__ADD
495 #undef XCBUf__SUB
496 #undef XCBUF__DECREMENT
497 #undef XCBUF__INCREMENT
498 
499 
500 #ifdef __cplusplus
501 }
502 #endif /* __cplusplus */
503 
504 
510 #endif /* picox_container_xcircular_buffer_h_ */
static const uint8_t * xcbuf_array_one(const XCircularBuffer *self, size_t *o_size)
バッファの先頭側の配列を返します
Definition: xcircular_buffer.h:157
static uint8_t xcbuf_front(XCircularBuffer *self)
バッファの先頭要素を返します
Definition: xcircular_buffer.h:388
static void xcbuf_push_front(XCircularBuffer *self, uint8_t value)
バッファ先頭に要素を追加します
Definition: xcircular_buffer.h:329
static uint8_t * xcbuf_data(XCircularBuffer *self)
バッファの先頭アドレスを返します
Definition: xcircular_buffer.h:134
static void xcbuf_push_back_n(XCircularBuffer *self, const void *src, size_t n)
バッファ末尾にnバイトを追加します
Definition: xcircular_buffer.h:301
static size_t xcbuf_capacity(const XCircularBuffer *self)
バッファに格納可能な最大要素数を返します
Definition: xcircular_buffer.h:250
Definition: xcircular_buffer.h:70
static size_t xcbuf_reserve(const XCircularBuffer *self)
バッファに格納可能な残り要素数を返します
Definition: xcircular_buffer.h:268
static void xcbuf_clear(XCircularBuffer *self)
バッファを空にします
Definition: xcircular_buffer.h:124
static const uint8_t * xcbuf_const_data(const XCircularBuffer *self)
バッファのコンストな先頭アドレスを返します
Definition: xcircular_buffer.h:143
static bool xcbuf_init(XCircularBuffer *self, void *buffer, size_t capacity)
循環バッファを初期化します
Definition: xcircular_buffer.h:91
static void xcbuf_push_front_n(XCircularBuffer *self, const void *src, size_t n)
バッファ先頭にnバイトを追加します
Definition: xcircular_buffer.h:351
static bool xcbuf_is_linearized(const XCircularBuffer *self)
バッファの要素が直線に並んでいるかどうかを返します
Definition: xcircular_buffer.h:223
static uint8_t xcbuf_pop_front(XCircularBuffer *self)
バッファの先頭要素を返し、先頭要素は除去されます
Definition: xcircular_buffer.h:409
static void xcbuf_deinit(XCircularBuffer *self)
バッファの終了処理を行います
Definition: xcircular_buffer.h:112
static void x_free(void *ptr)
ptrが指すメモリ空間を開放します
Definition: xstdlib.h:73
static void xcbuf_push_back(XCircularBuffer *self, uint8_t value)
バッファ末尾に要素を追加します
Definition: xcircular_buffer.h:279
static bool xcbuf_full(const XCircularBuffer *self)
バッファが満タンかどうかを返します
Definition: xcircular_buffer.h:259
static uint8_t * xcbuf_linearize(XCircularBuffer *self)
バッファの要素を直線に並べ替えます
Definition: xcircular_buffer.h:180
static const uint8_t * xcbuf_array_two(const XCircularBuffer *self, size_t *o_size)
バッファの後方側の配列を返します
Definition: xcircular_buffer.h:169
static void * x_malloc(size_t size)
sizeバイトのメモリを割り当てて返します
Definition: xstdlib.h:59
static bool xcbuf_empty(const XCircularBuffer *self)
バッファがからかどうかを返します
Definition: xcircular_buffer.h:241
static size_t xcbuf_size(const XCircularBuffer *self)
バッファの要素数を返します
Definition: xcircular_buffer.h:232
static void xcbuf_pop_back_n(XCircularBuffer *self, void *dst, size_t n)
バッファの後方からnバイトを除去し、dstにコピーします
Definition: xcircular_buffer.h:452
static void xcbuf_pop_front_n(XCircularBuffer *self, void *dst, size_t n)
バッファの先頭からnバイトを除去し、dstにコピーします
Definition: xcircular_buffer.h:423
static uint8_t xcbuf_pop_back(XCircularBuffer *self)
バッファの末尾要素を返し、末尾要素は除去されます
Definition: xcircular_buffer.h:397
static void xcbuf_copy_to_mem(const XCircularBuffer *self, size_t pos, void *dst, size_t n)
バッファから位置を指定してnバイトをdstにコピーします
Definition: xcircular_buffer.h:479
static uint8_t xcbuf_back(XCircularBuffer *self)
バッファの末尾要素を返します
Definition: xcircular_buffer.h:377