1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-16 00:00:07 +01:00
libwebsockets/lib/core/lws_dll.c
Andy Green 38fb0e31da lws_struct
lws_struct JSON + sqlite3 serializer and deserializer


See READMEs/README.lws_struct.md
2019-04-06 06:08:47 +08:00

246 lines
5.7 KiB
C

/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010-2019 Andy Green <andy@warmcat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation:
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "core/private.h"
#ifdef LWS_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
void
lws_dll_add_head(struct lws_dll *d, struct lws_dll *phead)
{
if (!lws_dll_is_detached(d, phead)) {
assert(0); /* only wholly detached things can be added */
return;
}
/* our next guy is current first guy, if any */
if (phead->next != d)
d->next = phead->next;
/* if there is a next guy, set his prev ptr to our next ptr */
if (d->next)
d->next->prev = d;
/* there is nobody previous to us, we are the head */
d->prev = NULL;
/* set the first guy to be us */
phead->next = d;
/* if there was nothing on the list before, we are also now the tail */
if (!phead->prev)
phead->prev = d;
assert(d->prev != d);
assert(d->next != d);
}
void
lws_dll_add_tail(struct lws_dll *d, struct lws_dll *phead)
{
if (!lws_dll_is_detached(d, phead)) {
assert(0); /* only wholly detached things can be added */
return;
}
/* our previous guy is current last guy */
d->prev = phead->prev;
/* if there is a prev guy, set his next ptr to our prev ptr */
if (d->prev)
d->prev->next = d;
/* our next ptr is NULL */
d->next = NULL;
/* set the last guy to be us */
phead->prev = d;
/* list head is also us if we're the first */
if (!phead->next)
phead->next = d;
assert(d->prev != d);
assert(d->next != d);
}
void
lws_dll_insert(struct lws_dll *n, struct lws_dll *target,
struct lws_dll *phead, int before)
{
if (!lws_dll_is_detached(n, phead)) {
assert(0); /* only wholly detached things can be inserted */
return;
}
if (!target) {
/*
* the case where there's no target identified degenerates to
* a simple add at head or tail
*/
if (before) {
lws_dll_add_head(n, phead);
return;
}
lws_dll_add_tail(n, phead);
return;
}
/*
* in the case there's a target "cursor", we have to do the work to
* stitch the new guy in appropriately
*/
if (before) {
/*
* we go before dd
* DDp <-> DD <-> DDn --> DDp <-> us <-> DD <-> DDn
*/
/* we point forward to dd */
n->next = target;
/* we point back to what dd used to point back to */
n->prev = target->prev;
/* DDp points forward to us now */
if (target->prev)
target->prev->next = n;
/* DD points back to us now */
target->prev = n;
/* if target was the head, we are now the head */
if (phead->next == target)
phead->next = n;
/* since we are before another guy, we cannot become the tail */
} else {
/*
* we go after dd
* DDp <-> DD <-> DDn --> DDp <-> DD <-> us <-> DDn
*/
/* we point forward to what dd used to point forward to */
n->next = target->next;
/* we point back to dd */
n->prev = target;
/* DDn points back to us */
if (target->next)
target->next->prev = n;
/* DD points forward to us */
target->next = n;
/* if target was the tail, we are now the tail */
if (phead->prev == target)
phead->prev = n;
/* since we go after another guy, we cannot become the head */
}
}
/* situation is:
*
* HEAD: struct lws_dll * = &entry1
*
* Entry 1: struct lws_dll .pprev = &HEAD , .next = Entry 2
* Entry 2: struct lws_dll .pprev = &entry1 , .next = &entry2
* Entry 3: struct lws_dll .pprev = &entry2 , .next = NULL
*
* Delete Entry1:
*
* - HEAD = &entry2
* - Entry2: .pprev = &HEAD, .next = &entry3
* - Entry3: .pprev = &entry2, .next = NULL
*
* Delete Entry2:
*
* - HEAD = &entry1
* - Entry1: .pprev = &HEAD, .next = &entry3
* - Entry3: .pprev = &entry1, .next = NULL
*
* Delete Entry3:
*
* - HEAD = &entry1
* - Entry1: .pprev = &HEAD, .next = &entry2
* - Entry2: .pprev = &entry1, .next = NULL
*
*/
void
lws_dll_remove(struct lws_dll *d)
{
if (!d->prev && !d->next)
return;
/*
* remove us
*
* USp <-> us <-> USn --> USp <-> USn
*/
/* if we have a next guy, set his prev to our prev */
if (d->next)
d->next->prev = d->prev;
/* set our prev guy to our next guy instead of us */
if (d->prev)
d->prev->next = d->next;
/* we're out of the list, we should not point anywhere any more */
d->prev = NULL;
d->next = NULL;
}
void
lws_dll_remove_track_tail(struct lws_dll *d, struct lws_dll *phead)
{
if (lws_dll_is_detached(d, phead)) {
assert(phead->prev != d);
assert(phead->next != d);
return;
}
/* if we have a next guy, set his prev to our prev */
if (d->next)
d->next->prev = d->prev;
/* if we have a previous guy, set his next to our next */
if (d->prev)
d->prev->next = d->next;
if (phead->prev == d)
phead->prev = d->prev;
if (phead->next == d)
phead->next = d->next;
/* we're out of the list, we should not point anywhere any more */
d->prev = NULL;
d->next = NULL;
}
int
lws_dll_foreach_safe(struct lws_dll *phead, void *user,
int (*cb)(struct lws_dll *d, void *user))
{
lws_start_foreach_dll_safe(struct lws_dll *, p, tp, phead->next) {
if (cb(p, user))
return 1;
} lws_end_foreach_dll_safe(p, tp);
return 0;
}