picox  0.1
xmessage_buffer.h
[詳解]
1 
14 /*
15  * License: MIT license
16  * Copyright (c) <2015> <MaskedW [maskedw00@gmail.com]>
17  *
18  * Permission is hereby granted, free of uint8_tge, to any person
19  * obtaining a copy of self 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 self 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_xmessage_buffer_h_
41 #define picox_container_xmessage_buffer_h_
42 
43 
44 #include <picox/core/xcore.h>
45 
46 
55 #ifdef __cplusplus
56 extern "C" {
57 #endif // __cplusplus
58 
59 
66 typedef union XMessageHeader
67 {
68  size_t size;
69  uint8_t bytes[sizeof(size_t)];
71 
72 
78 typedef struct XMessageBuffer
79 {
81  uint8_t* data;
82  size_t first;
83  size_t last;
84  size_t size;
85  size_t capacity;
87 
88 
99 static inline void
100 xmsgbuf_init(XMessageBuffer* self, void* buffer, size_t size)
101 {
102  X_ASSERT(self);
103  X_ASSERT(buffer);
104  X_ASSERT(size > sizeof(XMessageHeader));
105 
106  self->data = buffer;
107  self->first = self->last = self->size = 0;
108  self->capacity = size;
109 }
110 
111 
114 static inline uint8_t*
116 {
117  X_ASSERT(self);
118  return self->data;
119 }
120 
121 
124 static inline void
126 {
127  X_ASSERT(self);
128  self->first = self->last = self->size = 0;
129 }
130 
131 
136 static inline size_t
138 {
139  X_ASSERT(self);
140  return self->size;
141 }
142 
143 
146 static inline bool
148 {
149  X_ASSERT(self);
150  return self->size == 0;
151 }
152 
153 
156 static inline size_t
158 {
159  X_ASSERT(self);
160  return self->capacity;
161 }
162 
163 
166 static inline size_t
168 {
169  X_ASSERT(self);
170  return self->capacity - self->size;
171 }
172 
173 
179 static inline bool
181 {
182  X_ASSERT(self);
183  return xmsgbuf_reserve(self) <= sizeof(XMessageHeader);
184 }
185 
186 
189 static inline size_t
191 {
192  X_ASSERT(self);
193  if (xmsgbuf_empty(self))
194  return 0;
195 
196  XMessageHeader header;
197  size_t rpos = self->first;
198  int i;
199  for (i = 0; i < (int)sizeof(XMessageHeader); i++)
200  {
201  header.bytes[i] = self->data[rpos++];
202  if (rpos == self->capacity)
203  rpos = 0;
204  }
205 
206  return header.size;
207 }
208 
209 
212 static inline size_t
214 {
215  X_ASSERT(self);
216 
217  size_t n = 0;
218  XMessageHeader hdr;
219  size_t first = self->first;
220  size_t size = self->size;
221  int i;
222 
223  while (size)
224  {
225  for (i = 0; i < (int)sizeof(XMessageHeader); i++)
226  {
227  hdr.bytes[i] = self->data[first++];
228  if (first == self->capacity)
229  first = 0;
230  }
231  size -= (sizeof(XMessageHeader) + hdr.size);
232  first = (first + hdr.size) % self->capacity;
233  n++;
234  }
235 
236  return n;
237 }
238 
239 
242 static inline void
244 {
245  X_ASSERT(self);
246 
247  if (xmsgbuf_empty(self))
248  return;
249 
250  XMessageHeader hdr;
251  size_t first = self->first;
252  int i;
253 
254  for (i = 0; i < (int)sizeof(XMessageHeader); i++)
255  {
256  hdr.bytes[i] = self->data[first++];
257  if (first == self->capacity)
258  first = 0;
259  }
260  first = (first + hdr.size) % self->capacity;
261  self->size -= sizeof(XMessageHeader) + hdr.size;
262  self->first = first;
263 }
264 
265 
273 static inline void
274 xmsgbuf_push(XMessageBuffer* self, const void* src, size_t size)
275 {
276  X_ASSERT(self);
277  X_ASSERT(src);
278  X_ASSERT(size > 0);
279  X_ASSERT(xmsgbuf_reserve(self) >= size + sizeof(XMessageHeader));
280 
281 
282  XMessageHeader header;
283  header.size = size;
284  self->size += sizeof(XMessageHeader) + size;
285 
286  size_t pos = self->last;
287  int i;
288  for (i = 0; i < (int)sizeof(XMessageHeader); i++)
289  {
290  self->data[pos++] = header.bytes[i];
291  if (pos >= self->capacity)
292  pos = 0;
293  }
294 
295  const uint8_t* from = src;
296  uint8_t* to;
297 
298  if (pos + size > self->capacity)
299  {
300  const size_t until_tail = self->capacity - pos;
301  to = self->data + pos;
302  memcpy(to, from, until_tail);
303 
304  size -= until_tail;
305  from += until_tail;
306  pos = 0;
307  }
308 
309  to = self->data + pos;
310  memcpy(to, from, size);
311 
312  pos += size;
313  if (pos == self->capacity)
314  pos = 0;
315  self->last = pos;
316 }
317 
318 
325 static inline size_t
326 xmsgbuf_pull(XMessageBuffer* self, void* dst)
327 {
328  X_ASSERT(self);
329  X_ASSERT(dst);
330 
331  if (xmsgbuf_empty(self))
332  return 0;
333 
334  XMessageHeader header;
335  size_t pos = self->first;
336  int i;
337  for (i = 0; i < (int)sizeof(XMessageHeader); i++) {
338  header.bytes[i] = self->data[pos++];
339  if (pos == self->capacity)
340  pos = 0;
341  }
342 
343  uint8_t* to = dst;
344  const uint8_t* from;
345  size_t to_read = header.size;
346 
347  if (pos + to_read > self->capacity)
348  {
349  const size_t until_tail = self->capacity - pos;
350  from = self->data + pos;
351  memcpy(to, from, until_tail);
352  to_read -= until_tail;
353  to += until_tail;
354  pos = 0;
355  }
356 
357  from = self->data + pos;
358  memcpy(to, from, to_read);
359 
360  pos += to_read;
361  if (pos == self->capacity)
362  pos = 0;
363  self->first = pos;
364  self->size -= header.size + sizeof(XMessageHeader);
365 
366  return header.size;
367 }
368 
369 
370 #ifdef __cplusplus
371 }
372 #endif // __cplusplus
373 
374 
380 #endif // picox_container_xmessage_buffer_h_
static size_t xmsgbuf_reserve(const XMessageBuffer *self)
バッファの空きバイト数を返します
Definition: xmessage_buffer.h:167
static size_t xmsgbuf_size(const XMessageBuffer *self)
バッファに格納されているバイト数を返します
Definition: xmessage_buffer.h:137
static void xmsgbuf_skip(XMessageBuffer *self)
先頭メッセージを読み飛ばします
Definition: xmessage_buffer.h:243
メッセージヘッダ
Definition: xmessage_buffer.h:66
static size_t xmsgbuf_num(const XMessageBuffer *self)
格納メッセージ数を返します
Definition: xmessage_buffer.h:213
static size_t xmsgbuf_msg_size(const XMessageBuffer *self)
先頭メッセージのバイト数を返します
Definition: xmessage_buffer.h:190
static uint8_t * xmsgbuf_data(const XMessageBuffer *self)
要素を格納するバッファを返します
Definition: xmessage_buffer.h:115
static void xmsgbuf_clear(XMessageBuffer *self)
バッファを空にします
Definition: xmessage_buffer.h:125
static size_t xmsgbuf_pull(XMessageBuffer *self, void *dst)
バッファ先頭からメッセージを取り出し、メッセージサイズを返します
Definition: xmessage_buffer.h:326
static void xmsgbuf_init(XMessageBuffer *self, void *buffer, size_t size)
バッファを初期化します
Definition: xmessage_buffer.h:100
static bool xmsgbuf_empty(const XMessageBuffer *self)
バッファが空かどうかを返します
Definition: xmessage_buffer.h:147
可変長バイトデータの管理構造体
Definition: xmessage_buffer.h:78
static bool xmsgbuf_full(const XMessageBuffer *self)
バッファが満タンかどうかを返します
Definition: xmessage_buffer.h:180
static size_t xmsgbuf_capacity(const XMessageBuffer *self)
バッファに格納できる最大バイト数を返します
Definition: xmessage_buffer.h:157
static void xmsgbuf_push(XMessageBuffer *self, const void *src, size_t size)
バッファ末尾にメッセージを追加します
Definition: xmessage_buffer.h:274