Verified Commit d34a0553 authored by Max Rees's avatar Max Rees

include: add apk/list.h

parent 84ac7ebd
/* apk_defines.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
* Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#ifndef APK_LIST_H
#define APK_LIST_H
#ifndef apk_container_of
#define apk_container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
void *apk_array_resize(void *array, size_t new_size, size_t elem_size);
#define APK_ARRAY(array_type_name, elem_type_name) \
struct array_type_name { \
size_t num; \
elem_type_name item[]; \
}; \
static inline void \
array_type_name##_init(struct array_type_name **a) \
{ \
*a = apk_array_resize(NULL, 0, 0); \
} \
static inline void \
array_type_name##_free(struct array_type_name **a) \
{ \
*a = apk_array_resize(*a, 0, 0); \
} \
static inline void \
array_type_name##_resize(struct array_type_name **a, size_t size)\
{ \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
} \
static inline void \
array_type_name##_copy(struct array_type_name **a, struct array_type_name *b)\
{ \
if (*a == b) return; \
*a = apk_array_resize(*a, b->num, sizeof(elem_type_name));\
memcpy((*a)->item, b->item, b->num * sizeof(elem_type_name));\
} \
static inline elem_type_name * \
array_type_name##_add(struct array_type_name **a) \
{ \
int size = 1 + (*a)->num; \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
return &(*a)->item[size-1]; \
}
APK_ARRAY(apk_string_array, char *);
#define APK_LIST_END (void *) 0xe01
#define APK_LIST_POISON1 (void *) 0xdeadbeef
#define APK_LIST_POISON2 (void *) 0xabbaabba
struct apk_hlist_head {
struct apk_hlist_node *first;
};
struct apk_hlist_node {
struct apk_hlist_node *next;
};
static inline int apk_hlist_empty(const struct apk_hlist_head *h)
{
return !h->first;
}
static inline int apk_hlist_hashed(const struct apk_hlist_node *n)
{
return n->next != NULL;
}
static inline void _apk_hlist_del(struct apk_hlist_node *n, struct apk_hlist_node **pprev)
{
*pprev = n->next;
n->next = NULL;
}
static inline void apk_hlist_del(struct apk_hlist_node *n, struct apk_hlist_head *h)
{
struct apk_hlist_node **pp = &h->first;
while (*pp != NULL && *pp != APK_LIST_END && *pp != n)
pp = &(*pp)->next;
if (*pp == n)
_apk_hlist_del(n, pp);
}
static inline void apk_hlist_add_head(struct apk_hlist_node *n, struct apk_hlist_head *h)
{
struct apk_hlist_node *first = h->first;
n->next = first ? first : APK_LIST_END;
h->first = n;
}
static inline void apk_hlist_add_after(struct apk_hlist_node *n, struct apk_hlist_node **prev)
{
n->next = *prev ? *prev : APK_LIST_END;
*prev = n;
}
static inline struct apk_hlist_node **apk_hlist_tail_ptr(struct apk_hlist_head *h)
{
struct apk_hlist_node *n = h->first;
if (n == NULL || n == APK_LIST_END)
return &h->first;
while (n->next != NULL && n->next != APK_LIST_END)
n = n->next;
return &n->next;
}
#define apk_hlist_entry(ptr, type, member) apk_container_of(ptr,type,member)
#define apk_hlist_for_each(pos, head) \
for (pos = (head)->first; pos && pos != APK_LIST_END; \
pos = pos->next)
#define apk_hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && pos != APK_LIST_END && \
({ n = pos->next; 1; }); \
pos = n)
#define apk_hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && pos != APK_LIST_END && \
({ tpos = apk_hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
#define apk_hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && pos != APK_LIST_END && ({ n = pos->next; 1; }) && \
({ tpos = apk_hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
struct apk_list_head {
struct apk_list_head *next, *prev;
};
static inline void apk_list_init(struct apk_list_head *list)
{
list->next = list;
list->prev = list;
}
static inline void _apk_list_add(struct apk_list_head *new,
struct apk_list_head *prev,
struct apk_list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void apk_list_add(struct apk_list_head *new, struct apk_list_head *head)
{
_apk_list_add(new, head, head->next);
}
static inline void apk_list_add_tail(struct apk_list_head *new, struct apk_list_head *head)
{
_apk_list_add(new, head->prev, head);
}
static inline void _apk_list_del(struct apk_list_head *prev, struct apk_list_head *next)
{
next->prev = prev;
prev->next = next;
}
static inline void apk_list_del(struct apk_list_head *entry)
{
_apk_list_del(entry->prev, entry->next);
entry->next = APK_LIST_POISON1;
entry->prev = APK_LIST_POISON2;
}
static inline void apk_list_del_init(struct apk_list_head *entry)
{
_apk_list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
static inline int apk_list_hashed(const struct apk_list_head *n)
{
return n->next != n && n->next != NULL;
}
static inline int apk_list_empty(const struct apk_list_head *n)
{
return n->next == n;
}
static inline struct apk_list_head *_apk_list_pop(struct apk_list_head *head)
{
struct apk_list_head *n = head->next;
apk_list_del_init(n);
return n;
}
#define apk_list_entry(ptr, type, member) apk_container_of(ptr,type,member)
#define apk_list_pop(head, type, member) apk_container_of(_apk_list_pop(head),type,member)
#define apk_list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define apk_list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define apk_list_for_each_entry(pos, head, member) \
for (pos = apk_list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = apk_list_entry(pos->member.next, typeof(*pos), member))
#define apk_list_for_each_entry_safe(pos, n, head, member) \
for (pos = apk_list_entry((head)->next, typeof(*pos), member), \
n = apk_list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = apk_list_entry(n->member.next, typeof(*n), member))
#endif
......@@ -36,8 +36,8 @@
#include "apk_io.h"
static const struct apk_option_group *default_optgroups[] = { &optgroup_global, NULL };
static struct list_head apk_applet_list;
#define foreach_applet(iter) list_for_each_entry(iter, &apk_applet_list, node)
static struct apk_list_head apk_applet_list;
#define foreach_applet(iter) apk_list_for_each_entry(iter, &apk_applet_list, node)
#ifdef TEST_MODE
static const char *test_installed_db = NULL;
......@@ -65,7 +65,7 @@ static struct apk_repository_list *apk_repository_new(const char *url)
struct apk_repository_list *r = calloc(1, sizeof(struct apk_repository_list));
if (r) {
r->url = url;
list_init(&r->list);
apk_list_init(&r->list);
}
return r;
}
......@@ -87,7 +87,7 @@ static int option_parse_global(void *ctx, struct apk_db_options *dbopts, int opt
break;
case 'X':
repo = apk_repository_new(optarg);
if (repo) list_add(&repo->list, &dbopts->repository_list);
if (repo) apk_list_add(&repo->list, &dbopts->repository_list);
break;
case 'q':
apk_verbosity--;
......@@ -496,8 +496,8 @@ static void setup_automatic_flags(void)
void apk_applet_register(struct apk_applet *applet)
{
list_init(&applet->node);
list_add_tail(&applet->node, &apk_applet_list);
apk_list_init(&applet->node);
apk_list_add_tail(&applet->node, &apk_applet_list);
}
static void apk_applet_register_builtin(void)
......@@ -505,7 +505,7 @@ static void apk_applet_register_builtin(void)
extern apk_init_func_t __start_initapplets[], __stop_initapplets[];
apk_init_func_t *p;
list_init(&apk_applet_list);
apk_list_init(&apk_applet_list);
for (p = __start_initapplets; p < __stop_initapplets; p++)
(*p)();
}
......@@ -541,7 +541,7 @@ int main(int argc, char **argv)
apk_argv[argc+1] = NULL;
memset(&dbopts, 0, sizeof(dbopts));
list_init(&dbopts.repository_list);
apk_list_init(&dbopts.repository_list);
apk_atom_init();
umask(0);
setup_terminal();
......
......@@ -40,7 +40,7 @@ struct apk_option_group {
};
struct apk_applet {
struct list_head node;
struct apk_list_head node;
const char *name;
const char *arguments;
......
......@@ -32,8 +32,8 @@ struct apk_db_acl {
};
struct apk_db_file {
struct hlist_node hash_node;
struct hlist_node diri_files_list;
struct apk_hlist_node hash_node;
struct apk_hlist_node diri_files_list;
struct apk_db_dir_instance *diri;
struct apk_db_acl *acl;
......@@ -86,8 +86,8 @@ struct apk_db_dir {
#define DIR_FILE_PRINTF(dir,file) (dir)->name, (dir)->namelen ? "/" : "", (file)->name
struct apk_db_dir_instance {
struct hlist_node pkg_dirs_list;
struct hlist_head owned_files;
struct apk_hlist_node pkg_dirs_list;
struct apk_hlist_head owned_files;
struct apk_package *pkg;
struct apk_db_dir *dir;
struct apk_db_acl *acl;
......@@ -117,7 +117,7 @@ struct apk_repository {
};
struct apk_repository_list {
struct list_head list;
struct apk_list_head list;
const char *url;
};
......@@ -130,7 +130,7 @@ struct apk_db_options {
const char *keys_dir;
const char *cache_dir;
const char *repositories_file;
struct list_head repository_list;
struct apk_list_head repository_list;
};
#define APK_REPOSITORY_CACHED 0
......@@ -174,8 +174,8 @@ struct apk_database {
} available;
struct {
struct list_head packages;
struct list_head triggers;
struct apk_list_head packages;
struct apk_list_head triggers;
struct apk_hash dirs;
struct apk_hash files;
struct {
......
......@@ -16,7 +16,12 @@
#include <string.h>
#include <time.h>
#include <apk/list.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define foreach_array_item(iter, array) \
for (iter = &(array)->item[0]; iter < &(array)->item[(array)->num]; iter++)
#define BIT(x) (1 << (x))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
......@@ -29,10 +34,6 @@
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0L
#endif
#define EAPKBADURL 1024
#define EAPKSTALEINDEX 1025
......@@ -54,12 +55,6 @@ static inline int IS_ERR_OR_NULL(const void *ptr) { return IS_ERR(ptr) || !ptr;
#define unlikely(x) __builtin_expect((!!(x)),0)
#endif
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
extern int apk_verbosity;
extern unsigned int apk_flags, apk_force;
extern const char *apk_arch;
......@@ -149,222 +144,4 @@ static inline size_t mulmod(size_t a, size_t b, size_t c)
typedef void (*apk_progress_cb)(void *cb_ctx, size_t);
void *apk_array_resize(void *array, size_t new_size, size_t elem_size);
#define APK_ARRAY(array_type_name, elem_type_name) \
struct array_type_name { \
size_t num; \
elem_type_name item[]; \
}; \
static inline void \
array_type_name##_init(struct array_type_name **a) \
{ \
*a = apk_array_resize(NULL, 0, 0); \
} \
static inline void \
array_type_name##_free(struct array_type_name **a) \
{ \
*a = apk_array_resize(*a, 0, 0); \
} \
static inline void \
array_type_name##_resize(struct array_type_name **a, size_t size)\
{ \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
} \
static inline void \
array_type_name##_copy(struct array_type_name **a, struct array_type_name *b)\
{ \
if (*a == b) return; \
*a = apk_array_resize(*a, b->num, sizeof(elem_type_name));\
memcpy((*a)->item, b->item, b->num * sizeof(elem_type_name));\
} \
static inline elem_type_name * \
array_type_name##_add(struct array_type_name **a) \
{ \
int size = 1 + (*a)->num; \
*a = apk_array_resize(*a, size, sizeof(elem_type_name));\
return &(*a)->item[size-1]; \
}
APK_ARRAY(apk_string_array, char *);
#define foreach_array_item(iter, array) \
for (iter = &(array)->item[0]; iter < &(array)->item[(array)->num]; iter++)
#define LIST_END (void *) 0xe01
#define LIST_POISON1 (void *) 0xdeadbeef
#define LIST_POISON2 (void *) 0xabbaabba
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next;
};
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline int hlist_hashed(const struct hlist_node *n)
{
return n->next != NULL;
}
static inline void __hlist_del(struct hlist_node *n, struct hlist_node **pprev)
{
*pprev = n->next;
n->next = NULL;
}
static inline void hlist_del(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node **pp = &h->first;
while (*pp != NULL && *pp != LIST_END && *pp != n)
pp = &(*pp)->next;
if (*pp == n)
__hlist_del(n, pp);
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first ? first : LIST_END;
h->first = n;
}
static inline void hlist_add_after(struct hlist_node *n, struct hlist_node **prev)
{
n->next = *prev ? *prev : LIST_END;
*prev = n;
}
static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h)
{
struct hlist_node *n = h->first;
if (n == NULL || n == LIST_END)
return &h->first;
while (n->next != NULL && n->next != LIST_END)
n = n->next;
return &n->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && pos != LIST_END; \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && pos != LIST_END && \
({ n = pos->next; 1; }); \
pos = n)
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && pos != LIST_END && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && pos != LIST_END && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
struct list_head {
struct list_head *next, *prev;
};
static inline void list_init(struct list_head *list)
{
list->next = list;
list->prev = list;
}
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
static inline int list_hashed(const struct list_head *n)
{
return n->next != n && n->next != NULL;
}
static inline int list_empty(const struct list_head *n)
{
return n->next == n;
}
static inline struct list_head *__list_pop(struct list_head *head)
{
struct list_head *n = head->next;
list_del_init(n);
return n;
}
#define list_entry(ptr, type, member) container_of(ptr,type,member)
#define list_pop(head, type, member) container_of(__list_pop(head),type,member)
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
#endif
......@@ -35,8 +35,8 @@ struct apk_hash_ops {
void (*delete_item)(apk_hash_item item);
};
typedef struct hlist_node apk_hash_node;
APK_ARRAY(apk_hash_array, struct hlist_head);
typedef struct apk_hlist_node apk_hash_node;
APK_ARRAY(apk_hash_array, struct apk_hlist_head);
struct apk_hash {
const struct apk_hash_ops *ops;
......
......@@ -80,9 +80,9 @@ APK_ARRAY(apk_dependency_array, struct apk_dependency);
struct apk_installed_package {
struct apk_package *pkg;
struct list_head installed_pkgs_list;
struct list_head trigger_pkgs_list;
struct hlist_head owned_dirs;
struct apk_list_head installed_pkgs_list;
struct apk_list_head trigger_pkgs_list;
struct apk_hlist_head owned_dirs;
apk_blob_t script[APK_SCRIPT_MAX];
struct apk_string_array *triggers;
struct apk_string_array *pending_triggers;
......
......@@ -20,8 +20,8 @@ struct apk_solver_name_state {
struct apk_provider chosen;
union {
struct {
struct list_head dirty_list;
struct list_head unresolved_list;
struct apk_list_head dirty_list;
struct apk_list_head unresolved_list;
};
struct {
struct apk_name *installed_name;
......
......@@ -92,7 +92,7 @@ struct apk_tar_entry_istream {
static void tar_entry_get_meta(void *stream, struct apk_file_meta *meta)
{
struct apk_tar_entry_istream *teis =
container_of(stream, struct apk_tar_entry_istream, is);
apk_container_of(stream, struct apk_tar_entry_istream, is);
*meta = (struct apk_file_meta) {
.atime = teis->mtime,
.mtime = teis->mtime,
......@@ -102,7 +102,7 @@ static void tar_entry_get_meta(void *stream, struct apk_file_meta *meta)
static ssize_t tar_entry_read(void *stream, void *ptr, size_t size)
{
struct apk_tar_entry_istream *teis =
container_of(stream, struct apk_tar_entry_istream, is);
apk_container_of(stream, struct apk_tar_entry_istream, is);
ssize_t r;
if (size > teis->bytes_left)
......
......@@ -18,7 +18,7 @@
#include "apk_hash.h"
struct apk_blob_atom {
struct hlist_node hash_node;
struct apk_hlist_node hash_node;
apk_blob_t blob;
};
......
This diff is collapsed.
......@@ -100,7 +100,7 @@ static int fix_main(void *pctx, struct apk_database *db, struct apk_string_array
apk_hash_foreach(&db->installed.dirs, mark_recalculate, db);
if (args->num == 0) {
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
apk_list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
if (ipkg->broken_files || ipkg->broken_script ||
(ipkg->broken_xattr && ctx->fix_xattrs))
mark_fix(ctx, ipkg->pkg->name);
......
......@@ -33,7 +33,7 @@ struct apk_gzip_istream {
static void gzi_get_meta(void *stream, struct apk_file_meta *meta)
{
struct apk_gzip_istream *gis =
container_of(stream, struct apk_gzip_istream, is);
apk_container_of(stream, struct apk_gzip_istream, is);
apk_bstream_get_meta(gis->bs, meta);
}
......@@ -50,7 +50,7 @@ static int gzi_boundary_change(struct apk_gzip_istream *gis)
static ssize_t gzi_read(void *stream, void *ptr, size_t size)
{
struct apk_gzip_istream *gis =
container_of(stream, struct apk_gzip_istream, is);
apk_container_of(stream, struct apk_gzip_istream, is);
int r;
if (gis->err != 0) {
......@@ -103,7 +103,7 @@ static ssize_t gzi_read(void *stream, void *ptr, size_t size)
gis->zs.avail_in == 0)
gis->err = 1;
if (gis->cb != NULL) {
gis->cbarg = APK_BLOB_PTR_LEN(gis->cbprev, (void *) gis->zs.next_in - gis->cbprev);
gis->cbarg = APK_BLOB_PTR_LEN(gis->cbprev, (void *) gis->zs.next_in - gis->cbprev);
gis->cbprev = gis->zs.next_in;
}
/* If we hit end of the bitstream (not end
......@@ -137,7 +137,7 @@ ret:
static void gzi_close(void *stream)
{
struct apk_gzip_istream *gis =
container_of(stream, struct apk_gzip_istream, is);
apk_container_of(stream, struct apk_gzip_istream, is);
inflateEnd(&gis->zs);
apk_bstream_close(gis->bs, NULL);
......
......@@ -29,13 +29,13 @@ void apk_hash_free(struct apk_hash *h)
int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx)
{
struct hlist_head *bucket;
struct apk_hlist_head *bucket;
apk_hash_node *pos, *n;
ptrdiff_t offset = h->ops->node_offset;
int r;
foreach_array_item(bucket, h->buckets) {
hlist_for_each_safe(pos, n, bucket) {
apk_hlist_for_each_safe(pos, n, bucket) {
r = e(((void *) pos) - offset, ctx);
if (r != 0 && ctx != NULL)
return r;
......@@ -54,13 +54,13 @@ apk_hash_item apk_hash_get_hashed(struct apk_hash *h, apk_blob_t key, unsigned l
hash %= h->buckets->num;
if (h->ops->compare_item != NULL) {
hlist_for_each(pos, &h->buckets->item[hash]) {
apk_hlist_for_each(pos, &h->buckets->item[hash]) {
item = ((void *) pos) - offset;
if (h->ops->compare_item(item, key) == 0)
return item;
}
} else {
hlist_for_each(pos, &h->buckets->item[hash]) {
apk_hlist_for_each(pos, &h->buckets->item[hash]) {
item = ((void *) pos