1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2013-2020 Couchbase, Inc.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include "internal.h"
19
20void lcb_list_init(lcb_list_t *list)
21{
22    list->next = list;
23    list->prev = list;
24}
25
26static void list_insert(lcb_list_t *prev, lcb_list_t *next, lcb_list_t *item)
27{
28    item->next = next;
29    item->prev = prev;
30    next->prev = item;
31    prev->next = item;
32}
33
34void lcb_list_prepend(lcb_list_t *list, lcb_list_t *item)
35{
36    list_insert(list, list->next, item);
37}
38
39void lcb_list_append(lcb_list_t *list, lcb_list_t *item)
40{
41    list_insert(list->prev, list, item);
42}
43
44static void list_eject(lcb_list_t *prev, lcb_list_t *next)
45{
46    next->prev = prev;
47    prev->next = next;
48}
49
50void lcb_list_delete(lcb_list_t *item)
51{
52    list_eject(item->prev, item->next);
53    item->next = item->prev = NULL;
54}
55
56lcb_list_t *lcb_list_shift(lcb_list_t *list)
57{
58    lcb_list_t *item;
59
60    if (LCB_LIST_IS_EMPTY(list)) {
61        return NULL;
62    }
63    item = list->next;
64    lcb_list_delete(item);
65    return item;
66}
67
68lcb_list_t *lcb_list_pop(lcb_list_t *list)
69{
70    lcb_list_t *item;
71
72    if (LCB_LIST_IS_EMPTY(list)) {
73        return NULL;
74    }
75    item = list->prev;
76    lcb_list_delete(item);
77    return item;
78}
79
80int lcb_list_contains(lcb_list_t *list, lcb_list_t *item)
81{
82    lcb_list_t *ptr = list->next;
83
84    while (ptr != list && ptr != item) {
85        ptr = ptr->next;
86    }
87
88    return (ptr == item) ? 1 : 0;
89}
90
91void lcb_list_add_sorted(lcb_list_t *list, lcb_list_t *item, lcb_list_cmp_fn cmp)
92{
93    lcb_list_t *p;
94
95    if (LCB_LIST_IS_EMPTY(list)) {
96        list_insert(list->prev, list, item);
97    } else {
98        LCB_LIST_FOR(p, list)
99        {
100            if (cmp(item, p) < 0) {
101                break;
102            }
103        }
104        list_insert(p->prev, p, item);
105    }
106}
107
108void lcb_clist_init(lcb_clist_t *cl)
109{
110    lcb_list_init((lcb_list_t *)cl);
111    cl->size = 0;
112}
113void lcb_clist_append(lcb_clist_t *cl, lcb_list_t *item)
114{
115    lcb_list_append((lcb_list_t *)cl, item);
116    cl->size++;
117}
118void lcb_clist_prepend(lcb_clist_t *cl, lcb_list_t *item)
119{
120    lcb_list_prepend((lcb_list_t *)cl, item);
121    cl->size++;
122}
123void lcb_clist_delete(lcb_clist_t *cl, lcb_list_t *item)
124{
125    lcb_list_delete(item);
126    cl->size--;
127}
128lcb_list_t *lcb_clist_pop(lcb_clist_t *cl)
129{
130    lcb_list_t *ret = lcb_list_pop((lcb_list_t *)cl);
131    if (ret) {
132        cl->size--;
133    }
134    return ret;
135}
136lcb_list_t *lcb_clist_shift(lcb_clist_t *cl)
137{
138    lcb_list_t *ret = lcb_list_shift((lcb_list_t *)cl);
139    if (ret) {
140        cl->size--;
141    }
142    return ret;
143}
144