picox  0.1
xintrusive_list.h
[詳解]
1 
14 /*
15  * License: MIT license
16  * Copyright (c) <2015> <MaskedW [maskedw00@gmail.com]>
17  *
18  * Permission is hereby granted, free of charge, 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_xintrusive_list_h_
41 #define picox_container_xintrusive_list_h_
42 
43 
44 #include <picox/core/xcore.h>
45 
46 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif // __cplusplus
65 
66 
87 typedef struct XIntrusiveNode
88 {
89  struct XIntrusiveNode* next;
90  struct XIntrusiveNode* prev;
92 
93 
96 typedef struct XIntrusiveList
97 {
99  XIntrusiveNode head;
101 
102 
117 #define xnode_entry(ptr, type, member) X_CONTAINER_OF(ptr, type, member)
118 
119 
125 static inline void
127 {
128  node->next->prev = node->prev;
129  node->prev->next = node->next;
130 }
131 
132 
135 static inline void
137 {
138  p2->prev = p1->prev;
139  p2->next = p1;
140  p1->prev->next = p2;
141  p1->prev = p2;
142 }
143 
144 
147 static inline void
149 {
150  p2->prev = p1;
151  p2->next = p1->next;
152  p1->next->prev = p2;
153  p1->next = p2;
154 }
155 
156 
159 static inline void
161 {
162  p2->next = p1->next;
163  p2->next->prev = p2;
164  p2->prev = p1->prev;
165  p2->prev->next = p2;
166 }
167 
168 
171 static inline void
173 {
174  XIntrusiveNode* first = list->head.next;
175  XIntrusiveNode* last = list->head.prev;
176 
177  first->prev = prev;
178  prev->next = first;
179  last->next = next;
180  next->prev = last;
181 }
182 
183 
186 static inline void
188 {
189  X_ASSERT(self);
190  self->head.next = self->head.prev = &self->head;
191 }
192 
193 
196 static inline XIntrusiveNode*
198 {
199  X_ASSERT(self);
200  return &self->head;
201 }
202 
203 
206 static inline void
208 {
209  X_ASSERT(self);
210  xilist_init(self);
211 }
212 
213 
216 static inline bool
218 {
219  X_ASSERT(self);
220  return self->head.next == &self->head;
221 }
222 
223 
226 static inline XIntrusiveNode*
228 {
229  X_ASSERT(self);
230  return (XIntrusiveNode*)(&self->head);
231 }
232 
233 
236 static inline XIntrusiveNode*
238 {
239  X_ASSERT(self);
240  return self->head.next;
241 }
242 
243 
246 static inline XIntrusiveNode*
248 {
249  X_ASSERT(self);
250  XIntrusiveNode* front = self->head.next;
251  xnode_unlink(front);
252  return front;
253 }
254 
255 
258 static inline XIntrusiveNode*
260 {
261  X_ASSERT(self);
262  return self->head.prev;
263 }
264 
265 
268 static inline XIntrusiveNode*
270 {
271  X_ASSERT(self);
272  XIntrusiveNode* back = self->head.prev;
273  xnode_unlink(back);
274  return back;
275 }
276 
277 
332 #define xilist_foreach(list, ite) \
333  for (ite = xilist_front(list); \
334  ite != xilist_end(list); \
335  ite = ite->next)
336 
337 
342 #define xilist_rforeach(list, ite) \
343  for (ite = xilist_back(list); \
344  ite != xilist_end(list); \
345  ite = ite->prev)
346 
347 
350 static inline size_t
352 {
353  X_ASSERT(self);
354  size_t n = 0;
355  XIntrusiveNode* ite;
356  xilist_foreach(self, ite)
357  n++;
358 
359  return n;
360 }
361 
362 
365 static inline bool
367 {
368  X_ASSERT(self);
369  return (! xilist_empty(self)) && (xilist_front(self) == xilist_back(self));
370 }
371 
372 
378 static inline void
380 {
381  X_ASSERT(self);
382  X_ASSERT(node);
383  xnode_insert_next(&self->head, node);
384 }
385 
386 
392 static inline void
394 {
395  X_ASSERT(self);
396  X_ASSERT(node);
397  xnode_insert_prev(&self->head, node);
398 }
399 
400 
406 static inline void
408 {
409  X_ASSERT(self);
410  X_ASSERT(node);
411  xnode_unlink(node);
412  xilist_push_front(self, node);
413 }
414 
415 
421 static inline void
423 {
424  X_ASSERT(self);
425  X_ASSERT(node);
426  xnode_unlink(node);
427  xilist_push_back(self, node);
428 }
429 
430 
436 static inline void
438 {
439  X_ASSERT(self);
440  X_ASSERT(other);
441  if (! xilist_empty(other))
442  {
443  xnode_splice(&self->head, self->head.next, other);
444  xilist_clear(other);
445  }
446 }
447 
448 
454 static inline void
456 {
457  X_ASSERT(self);
458  X_ASSERT(other);
459  if (! xilist_empty(other))
460  {
461  xnode_splice(self->head.prev, &self->head, other);
462  xilist_clear(other);
463  }
464 }
465 
466 
472 static inline void
474 {
475  X_ASSERT(self);
476  X_ASSERT(other);
477 
478  if (self == other)
479  return;
480 
481  const bool empty_self = xilist_empty(self);
482  const bool empty_other = xilist_empty(other);
483 
484  X_SWAP(self->head, other->head, XIntrusiveNode);
485 
486  if (empty_other)
487  xilist_init(self);
488  else
489  self->head.next->prev = self->head.prev->next = &(self->head);
490 
491  if (empty_self)
492  xilist_init(other);
493  else
494  other->head.next->prev = other->head.prev->next = &(other->head);
495 }
496 
497 
505 static inline void
507 {
508  X_ASSERT(self);
509  X_ASSERT(pos);
510  X_ASSERT(other);
511  X_ASSERT(!xilist_empty(other));
512 
513  XIntrusiveNode* const new_first = pos->next;
514  pos->next = self->head.next;
515  self->head.next = other->head.next;
516  self->head.next->prev = &self->head;
517  self->head.prev = pos;
518  other->head.next = new_first;
519  new_first->prev = &other->head;
520 }
521 
522 
530 static inline void
532 {
533  X_ASSERT(self);
534  X_ASSERT(pos);
535  X_ASSERT(other);
536  X_ASSERT(!xilist_empty(other));
537 
538  XIntrusiveNode* const new_first = pos->next;
539  pos->next = &self->head;
540  pos->prev = self->head.prev;
541  self->head.prev->next = other->head.next;
542  self->head.prev = pos;
543  other->head.next = new_first;
544  new_first->prev = &other->head;
545 }
546 
547 
548 #ifdef __cplusplus
549 }
550 #endif // __cplusplus
551 
552 
558 #endif // picox_container_xintrusive_list_h_
static bool xilist_empty(const XIntrusiveList *self)
コンテナが空かどうかを返します
Definition: xintrusive_list.h:217
static void xilist_splice_front(XIntrusiveList *self, XIntrusiveList *other)
otherを先頭に連結します
Definition: xintrusive_list.h:437
#define X_SWAP(x, y, T)
型Tの変数として、x, yを交換します。
Definition: xutils.h:90
リストノードデータを格納するコンテナ
Definition: xintrusive_list.h:96
static XIntrusiveNode * xilist_front(const XIntrusiveList *self)
コンテナの先頭ノードを返します
Definition: xintrusive_list.h:237
static void xilist_init(XIntrusiveList *self)
コンテナを初期化します
Definition: xintrusive_list.h:187
双方向リンリストリストノード
Definition: xintrusive_list.h:87
static void xilist_transfer_back(XIntrusiveList *self, XIntrusiveList *other, XIntrusiveNode *pos)
末尾にotherの先頭要素からpos(pos自身も含む)までを転送します
Definition: xintrusive_list.h:531
static void xnode_unlink(XIntrusiveNode *node)
ノードのリンクを解除します
Definition: xintrusive_list.h:126
static void xilist_transfer_front(XIntrusiveList *self, XIntrusiveList *other, XIntrusiveNode *pos)
先頭にotherの先頭要素からpos(pos自身も含む)までを転送します
Definition: xintrusive_list.h:506
static void xnode_splice(XIntrusiveNode *prev, XIntrusiveNode *next, XIntrusiveList *list)
prev, next間にlistを連結します
Definition: xintrusive_list.h:172
static void xilist_push_front(XIntrusiveList *self, XIntrusiveNode *node)
ノードを先頭に追加します
Definition: xintrusive_list.h:379
static void xilist_move_back(XIntrusiveList *self, XIntrusiveNode *node)
ノードのリンクを解除してから末尾に追加します
Definition: xintrusive_list.h:422
static void xilist_clear(XIntrusiveList *self)
コンテナを空にします
Definition: xintrusive_list.h:207
static XIntrusiveNode * xilist_pop_front(const XIntrusiveList *self)
先頭ノードをコンテナから除去して返します
Definition: xintrusive_list.h:247
static void xnode_insert_next(XIntrusiveNode *p1, XIntrusiveNode *p2)
p1の前にp2を挿入します
Definition: xintrusive_list.h:148
static void xilist_splice_back(XIntrusiveList *self, XIntrusiveList *other)
otherを末尾に連結します
Definition: xintrusive_list.h:455
static void xilist_swap(XIntrusiveList *self, XIntrusiveList *other)
2つのリストの中身を入れ替えます
Definition: xintrusive_list.h:473
static void xilist_push_back(XIntrusiveList *self, XIntrusiveNode *node)
ノードを末尾に追加します
Definition: xintrusive_list.h:393
static size_t xilist_size(const XIntrusiveList *self)
ノード数を返します
Definition: xintrusive_list.h:351
static XIntrusiveNode * xilist_pop_back(const XIntrusiveList *self)
末尾ノードをコンテナから除去して返します
Definition: xintrusive_list.h:269
static XIntrusiveNode * xilist_back(const XIntrusiveList *self)
コンテナの末尾ノードを返します
Definition: xintrusive_list.h:259
#define xilist_foreach(list, ite)
コンテナ先頭から順方向走査します
Definition: xintrusive_list.h:332
static XIntrusiveNode * xilist_end(const XIntrusiveList *self)
コンテナの終端を指すノードを返します
Definition: xintrusive_list.h:227
static void xnode_insert_prev(XIntrusiveNode *p1, XIntrusiveNode *p2)
p1の後ろにp2を挿入します
Definition: xintrusive_list.h:136
static void xnode_replace(XIntrusiveNode *p1, XIntrusiveNode *p2)
p1のリンクをにp2に置換えます
Definition: xintrusive_list.h:160
static bool xilist_is_singular(const XIntrusiveList *self)
ノード数が1つかどうかを返します
Definition: xintrusive_list.h:366
static XIntrusiveNode * xilist_head(XIntrusiveList *self)
コンテナのルートノードのポインタを返します
Definition: xintrusive_list.h:197
static void xilist_move_front(XIntrusiveList *self, XIntrusiveNode *node)
ノードのリンクを解除してから先頭に追加しま。
Definition: xintrusive_list.h:407