Mercurial > hg > nnchat
view th_util.c @ 222:a1fefbce0b7a
Add a simple 'press enter to continue' for Windows port, when an error occurs so the user can see it before the application closes.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 27 Nov 2010 17:45:20 +0200 |
parents | 4ec36204d34e |
children | 1807059fb8f2 |
line wrap: on
line source
/* * Generic utility-functions, macros and defaults * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2002-2010 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "th_util.h" #include <stdio.h> /* Default settings */ static BOOL th_initialized = FALSE; int th_verbosityLevel = 2; char *th_prog_name = NULL, *th_prog_fullname = NULL, *th_prog_version = NULL, *th_prog_author = NULL, *th_prog_license = NULL; /* Initialize th_util-library and global variables */ void th_init(char *progName, char *progFullName, char *progVersion, char *progAuthor, char *progLicense) { th_prog_name = progName; th_prog_fullname = progFullName; th_prog_version = progVersion; if (progAuthor) th_prog_author = progAuthor; else th_prog_author = TH_PROG_AUTHOR; if (progLicense) th_prog_license = progLicense; else th_prog_license = TH_PROG_LICENSE; th_initialized = TRUE; } /* Print formatted error, warning and information messages * TODO: Implement th_vfprintf() and friends? */ void THERR_V(const char *fmt, va_list ap) { assert(th_initialized == TRUE); fprintf(stderr, "%s: ", th_prog_name); vfprintf(stderr, fmt, ap); } void THMSG_V(int level, const char *fmt, va_list ap) { assert(th_initialized == TRUE); if (th_verbosityLevel >= level) { fprintf(stderr, "%s: ", th_prog_name); vfprintf(stderr, fmt, ap); } } void THPRINT_V(int level, const char *fmt, va_list ap) { assert(th_initialized == TRUE); if (th_verbosityLevel >= level) { vfprintf(stderr, fmt, ap); } } void THERR(const char *fmt, ...) { va_list ap; assert(th_initialized == TRUE); va_start(ap, fmt); THERR_V(fmt, ap); va_end(ap); } void THMSG(int level, const char *fmt, ...) { va_list ap; assert(th_initialized == TRUE); va_start(ap, fmt); THMSG_V(level, fmt, ap); va_end(ap); } void THPRINT(int level, const char *fmt, ...) { va_list ap; assert(th_initialized == TRUE); va_start(ap, fmt); THPRINT_V(level, fmt, ap); va_end(ap); } /* Memory handling routines */ void *th_malloc(size_t l) { return malloc(l); } void *th_calloc(size_t n, size_t l) { return calloc(n, l); } void *th_realloc(void *p, size_t l) { return realloc(p, l); } void th_free(void *p) { /* Check for NULL pointers for portability due to some libc * implementations not handling free(NULL) too well. */ if (p) free(p); } #ifndef HAVE_MEMSET void *th_memset(void *p, int c, size_t n) { unsigned char *dp = (unsigned char *) p; while (n--) *(dp++) = c; return p; } #endif /* Doubly linked list handling * * In this implementation first node's prev points to last node of the list, * and last node's next is NULL. This way we can semi-efficiently traverse to * beginning and end of the list, assuming user does not do weird things. */ qlist_t * th_llist_new(void *data) { qlist_t *res = th_calloc(sizeof(qlist_t), 1); res->data = data; return res; } void th_llist_free_func(qlist_t *list, void (*freefunc)(void *data)) { qlist_t *curr = list; while (curr != NULL) { qlist_t *next = curr->next; if (freefunc != NULL && curr->data != NULL) freefunc(curr->data); th_free(curr); curr = next; } } void th_llist_free(qlist_t *list) { th_llist_free_func(list, NULL); } void th_llist_append_node(qlist_t **list, qlist_t *node) { if (*list != NULL) { node->prev = (*list)->prev; (*list)->prev->next = node; (*list)->prev = node; (*list)->num++; } else { *list = node; node->prev = *list; (*list)->num = 1; } node->next = NULL; } qlist_t *th_llist_append(qlist_t **list, void *data) { qlist_t *node = th_llist_new(data); th_llist_append_node(list, node); return node; } void th_llist_prepend_node(qlist_t **list, qlist_t *node) { if (*list != NULL) { node->prev = (*list)->prev; node->next = *list; (*list)->prev = node; node->num = (*list)->num + 1; *list = node; } else { *list = node->prev = node; node->next = NULL; (*list)->num = 1; } } qlist_t *th_llist_prepend(qlist_t **list, void *data) { qlist_t *node = th_llist_new(data); th_llist_prepend_node(list, node); return node; } /* 1) Remove a middle node node0->prev->next = node->next (node1) node0->next->prev = node->prev (list) node2 <- list <=> node0 <=> node1 <=> node2 -> NULL node2 <- list <=> node1 <=> node2 -> NULL 2) Remove first node when many items node2 <- list <=> node0 <=> node1 <=> node2 -> NULL node2 <- node0 <=> node1 <=> node2 -> NULL *list = node0 3) Remove last node in list if (node->next == NULL) { list->prev = node->prev; node->prev->next = NULL; } node2 <- list <=> node0 <=> node1 <=> node2 -> NULL node1 <- list <=> node0 <=> node1 -> NULL 4) Remove last list <- list -> NULL */ static void th_llist_delete_node_fast(qlist_t **list, qlist_t *node) { if (node == *list) { /* First node in list */ qlist_t *tmp = (*list)->next; if (tmp != NULL) { tmp->num = (*list)->num - 1; tmp->prev = (*list)->prev; } *list = tmp; } else { /* Somewhere in middle or end */ if (node->prev != NULL) node->prev->next = node->next; if (node->next != NULL) node->next->prev = node->prev; else (*list)->prev = node; /* Last node */ (*list)->num--; } node->next = node->prev = NULL; } void th_llist_delete_node(qlist_t **list, qlist_t *node) { qlist_t *curr = *list; while (curr != NULL) { qlist_t *next = curr->next; if (curr == node) { th_llist_delete_node_fast(list, curr); th_free(node); break; } curr = next; } } void th_llist_delete(qlist_t **list, const void *data) { qlist_t *curr = *list; while (curr != NULL) { qlist_t *next = curr->next; if (curr->data == data) { th_llist_delete_node_fast(list, curr); th_free(curr); break; } curr = next; } } qlist_t * th_llist_get_nth(qlist_t *list, const size_t n) { qlist_t *curr = list; size_t i; for (i = 0; curr != NULL && i < n; curr = curr->next, i++); return curr; } size_t th_llist_length(const qlist_t *list) { if (list == NULL) return 0; else return list->num; } ssize_t th_llist_position(const qlist_t *list, const qlist_t *node) { const qlist_t *curr = list; ssize_t i = 0; while (curr != NULL) { if (curr == node) return i; else i++; curr = curr->next; } return -1; } qlist_t * th_llist_find(qlist_t *list, const void *data) { qlist_t *curr = list; while (curr != NULL) { if (curr->data == data) return curr; curr = curr->next; } return NULL; } qlist_t * th_llist_find_func(qlist_t *list, const void *userdata, int (compare)(const void *, const void *)) { qlist_t *curr = list; while (curr != NULL) { if (compare(curr->data, userdata) == 0) return curr; curr = curr->next; } return NULL; }