/* * $Id: util.h,v 1.35 2005/04/12 19:34:35 nohar Exp $ * * This file is part of the bip project * Copyright (C) 2004,2005 Arnaud Cornet * Copyright (C) 2004,2005,2022 Loïc Gomez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * See the file "COPYING" for the exact licensing terms. */ #ifndef UTIL_H #define UTIL_H #include #include #include #include #include /* Warning: must be in order, 0 = less output */ #define LOG_FATAL 0 #define LOG_ERROR 1 #define LOG_WARN 2 #define LOG_INFO 3 #define LOG_DEBUG 4 #define LOG_DEBUGVERB 5 #define LOG_DEBUGTOOMUCH 6 #define HASH_NOCASE 1 #define HASH_DEFAULT 0 void mylog(int level, char *fmt, ...); void _mylog(int level, char *fmt, va_list ap); void fatal(char *fmt, ...); char *timestamp(void); struct hash_item; struct list_item { struct list_item *next; struct list_item *prev; void *ptr; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" typedef struct list { struct list_item *first; struct list_item *last; int (*cmp)(); } list_t; #pragma GCC diagnostic pop typedef struct list_iterator { list_t *list; struct list_item *cur; struct list_item *next; } list_iterator_t; typedef struct hash { list_t lists[256]; } hash_t; typedef struct hash_iterator { int list; list_iterator_t lit; struct hash_item *cur; hash_t *hash; } hash_iterator_t; typedef struct array { int elemc; const void **elemv; } array_t; #define MOVE_STRING(dest, src) \ do { \ if (dest) \ free(dest); \ (dest) = (src); \ (src) = NULL; \ } while (0) #define FREE(a) \ free(a); \ (a) = NULL; #define MAYFREE(a) \ do { \ if (a) { \ free(a); \ (a) = NULL; \ } \ } while (0); #define assert(condition) \ do { \ if (!(condition)) \ fatal("Failed assertion in " __FILE__ \ "(%d): " #condition, \ __LINE__); \ } while (0) #define assert_msg(condition, msg) \ do { \ if (!(condition)) \ fatal("%s in " __FILE__ "(%d): " #condition, (msg), \ __LINE__); \ } while (0) void list_init(list_t *list, int (*cmp)(const void *, const void *)); int list_ptr_cmp(const void *a, const void *b); list_t *list_new(int (*cmp)(const void *, const void *)); void *list_remove(list_t *list, const void *ptr); void *list_remove_if_exists(list_t *list, const void *ptr); void *list_get(list_t *list, const void *ptr); void list_add_first(list_t *list, void *ptr); void list_add_first_uniq(list_t *list, void *ptr); void list_add_last(list_t *list, void *ptr); void *list_get_first(list_t *list); void *list_get_last(list_t *list); void *list_remove_first(list_t *list); void *list_remove_last(list_t *list); void list_it_init(list_t *list, list_iterator_t *ti); void list_it_init_last(list_t *list, list_iterator_t *ti); void *list_it_remove(list_iterator_t *li); void list_free(list_t *t); void list_append(list_t *dest, list_t *src); int list_is_empty(list_t *l); static inline void list_it_next(list_iterator_t *ti) { assert(ti); if (ti->cur) { if (ti->next) fatal("list_it_next: inconsistent iterator state"); ti->cur = ti->cur->next; } else if (ti->next) { ti->cur = ti->next; ti->next = NULL; } } static inline void *list_it_item(list_iterator_t *ti) { assert(ti); if (!ti->cur) return NULL; return ti->cur->ptr; } void hash_init(hash_t *h, int); void hash_free(hash_t *h); void hash_clean(hash_t *h); hash_t *hash_new(int options); void hash_insert(hash_t *hash, const char *key, void *ptr); int hash_includes(hash_t *hash, const char *key); void *hash_get(hash_t *, const char *key); void *hash_remove(hash_t *hash, const char *key); void *hash_remove_if_exists(hash_t *hash, const char *key); int hash_is_empty(hash_t *h); void hash_it_init(hash_t *hash, hash_iterator_t *i); void hash_it_next(hash_iterator_t *hi); void *hash_it_item(hash_iterator_t *h); const char *hash_it_key(hash_iterator_t *h); void *hash_it_remove(hash_iterator_t *li); list_t *hash_keys(hash_t *hash); void hash_rename_key(hash_t *h, const char *oldk, const char *newk); int is_valid_nick(char *str); int is_valid_username(char *str); char *bip_strmaydup(char *s); void strucase(char *s); int ischannel(char p); char *hrtime(time_t t); #ifdef HAVE_LIBSSL char *checkmode2text(int v); #endif #define bool2text(v) ((v) ? "true" : "false") void *bip_malloc(size_t size); void *bip_calloc(size_t nmemb, size_t size); void *bip_realloc(void *ptr, size_t size); void bip_cfree(const void *ptr); char *bip_strdup(const char *str); char *bip_strcat_fit(size_t *remaining, char *str, const char *str2); char *bip_strcatf_fit(size_t *remaining, char *str, const char *str2, ...); void bip_clock_gettime(clockid_t clockid, struct timespec *tp); #define array_each(a, idx, ptr) \ for ((idx) = 0; (idx) < (a)->elemc \ && (((ptr) = bip_strdup(array_get((a), (idx)))) || 1); \ (idx)++) void array_init(array_t *a); array_t *array_new(void); void array_ensure(array_t *a, int index); array_t *array_extract(array_t *a, int index, int upto); void array_deinit(array_t *a); void array_free(array_t *a); const void *array_drop(array_t *a, int index); static inline int array_count(array_t *a) { assert(a); return a->elemc; } static inline int array_includes(array_t *a, int index) { assert(a && index >= 0); return a->elemc > index; } static inline void array_set(array_t *a, int index, void *ptr) { assert(a); array_ensure(a, index); a->elemv[index] = ptr; } static inline const void *array_get(array_t *a, int index) { assert(a && array_includes(a, index)); return a->elemv[index]; } static inline void array_push(array_t *a, void *ptr) { int idx; assert(a); idx = a->elemc; array_ensure(a, idx); a->elemv[idx] = ptr; } static inline void *array_pop(array_t *a) { assert(a); if (a->elemc == 0) return NULL; if (a->elemc == 1) { void *ptr = bip_strdup(a->elemv[0]); free(a->elemv); a->elemv = NULL; a->elemc = 0; return ptr; } return (void *)bip_strdup(a->elemv[--a->elemc]); } #endif