1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2013 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBCOUCHBASE_LIST_H
#define LIBCOUCHBASE_LIST_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* Circular list implementation
*
* Could be used to implement queues, stacks etc.
*
* Declare list in your structure:
*
* typedef struct {
* lcb_list_t list;
* lcb_uint32_t msec;
* void (*callback)(struct timer *tm);
* } lcb_timer_t;
*
* Initialize head of list:
*
* lcb_timer_t tm;
* lcb_list_init(&tm.list);
*
* Add new items:
*
* lcb_timer_t *t;
* t->msec = 2000;
* t->callback = my_cb;
* lcb_list_append(&tm.list, t);
*
* Iterate over items:
*
* lcb_timer_t *t, *n;
*
* for (ii = tm.list.next; ii != &tm.list; ii = ii->next) {
* t = LCB_LIST_ITEM(ii, lcb_timer_t, list);
* printf("timeout: %d\n", t->msec);
* }
*
* LCB_LIST_FOR(ii, &tm.list) {
* t = LCB_LIST_ITEM(ii, lcb_timer_t, list);
* printf("timeout: %d\n", t->msec);
* }
*
* LCB_LIST_SAFE_FOR(ii, n, &tm.list) {
* t = LCB_LIST_ITEM(ii, lcb_timer_t, list);
* printf("timeout: %d\n", t->msec);
* }
*/
typedef struct lcb_list_s lcb_list_t;
struct lcb_list_s {
lcb_list_t *next;
lcb_list_t *prev;
};
typedef struct lcb_clist_s {
lcb_list_t *next;
lcb_list_t *prev;
lcb_size_t size;
} lcb_clist_t;
typedef int (*lcb_list_cmp_fn)(lcb_list_t *a, lcb_list_t *b);
void lcb_list_init(lcb_list_t *list);
void lcb_list_prepend(lcb_list_t *list, lcb_list_t *item);
void lcb_list_append(lcb_list_t *list, lcb_list_t *item);
void lcb_list_delete(lcb_list_t *item);
lcb_list_t *lcb_list_shift(lcb_list_t *list);
lcb_list_t *lcb_list_pop(lcb_list_t *list);
int lcb_list_contains(lcb_list_t *list, lcb_list_t *item);
void lcb_list_add_sorted(lcb_list_t *list, lcb_list_t *item, lcb_list_cmp_fn cmp);
/** Definitions for type safety. Rather than macros */
void lcb_clist_init(lcb_clist_t*);
void lcb_clist_append(lcb_clist_t*, lcb_list_t*);
void lcb_clist_prepend(lcb_clist_t*, lcb_list_t*);
void lcb_clist_delete(lcb_clist_t*,lcb_list_t*);
lcb_list_t* lcb_clist_shift(lcb_clist_t*);
lcb_list_t* lcb_clist_pop(lcb_clist_t*);
#define LCB_LIST_IS_EMPTY(list) \
((list) == (list)->next && (list) == (list)->prev)
#define LCB_LIST_ITEM(ptr, type, member) \
((type *) (void *) ((char *)(ptr) - offsetof(type, member)))
#define LCB_LIST_FOR(pos, list) \
for (pos = (list)->next; pos != (list); pos = pos->next)
#define LCB_LIST_SAFE_FOR(pos, n, list) \
for (pos = (list)->next, n = pos->next; pos != (list); pos = n, n = pos->next)
#define LCB_LIST_HAS_NEXT(ll, item) \
((item)->next != ll)
#define LCB_CLIST_SIZE(cl) (cl)->size
#define LCB_LIST_TAIL(list) \
((LCB_LIST_IS_EMPTY(list)) ? NULL : (list)->prev)
#define LCB_LIST_HEAD(list) \
((LCB_LIST_IS_EMPTY(list)) ? NULL : (list)->next)
#ifdef __cplusplus
}
#endif
#endif