--- psiconv/trunk/lib/psiconv/list.c 1999/10/03 21:10:47 2 +++ psiconv/trunk/lib/psiconv/list.c 2002/01/28 21:04:05 141 @@ -1,6 +1,6 @@ /* list.c - Part of psiconv, a PSION 5 file formats converter - Copyright (c) 1999 Frodo Looijaard + Copyright (c) 1999, 2000 Frodo Looijaard 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 @@ -19,24 +19,29 @@ #include "config.h" +#include "compat.h" #include #include #include +#include "general.h" #include "list.h" +#include "error.h" -static void psiconv_list_resize(psiconv_list l,unsigned int nr); +static int psiconv_list_resize(psiconv_list l,psiconv_u32 nr); -struct psiconv_list { - int cur_len; - int max_len; - int el_size; +struct psiconv_list_s { + psiconv_u32 cur_len; + psiconv_u32 max_len; + size_t el_size; void *els; }; -psiconv_list psiconv_list_new(int element_size) +psiconv_list psiconv_list_new(size_t element_size) { psiconv_list l; l = malloc(sizeof(*l)); + if (!l) + return NULL; l->cur_len = 0; l->max_len = 0; l->el_size=element_size; @@ -48,9 +53,8 @@ { if (l->max_len) free(l->els); - l->max_len = 0; - l->cur_len = 0; - l->els = NULL; + free(l); + l = NULL; } void psiconv_list_free_el(psiconv_list l, void free_el(void *el)) @@ -59,7 +63,7 @@ psiconv_list_free(l); } -int psiconv_list_length(const psiconv_list l) +psiconv_u32 psiconv_list_length(const psiconv_list l) { return l->cur_len; } @@ -69,7 +73,12 @@ return l->cur_len == 0; } -void *psiconv_list_get(const psiconv_list l, unsigned int indx) +void psiconv_list_empty(psiconv_list l) +{ + l->cur_len = 0; +} + +void *psiconv_list_get(const psiconv_list l, psiconv_u32 indx) { if (indx >= l->cur_len) return NULL; @@ -77,16 +86,36 @@ return ((char *) (l->els)) + indx * l->el_size; } -void psiconv_list_add(psiconv_list l, void *el) +int psiconv_list_add(psiconv_list l, const void *el) { - psiconv_list_resize(l,l->cur_len + 1); + int res; + if ((res = psiconv_list_resize(l,l->cur_len + 1))) + return res; memcpy(((char *) (l->els)) + l->cur_len * l->el_size, el, l->el_size); l->cur_len ++; + return 0; +} + +int psiconv_list_pop(psiconv_list l, void *el) +{ + if (! l->cur_len) + return -PSICONV_E_OTHER; + l->cur_len --; + memcpy(el,((char *)(l->els)) + l->cur_len * l->el_size,l->el_size); + return -PSICONV_E_OK; +} + +int psiconv_list_replace(psiconv_list l, psiconv_u32 indx, const void *el) +{ + if (indx >= l->cur_len) + return -PSICONV_E_OTHER; + memcpy(((char *) (l->els)) + indx * l->el_size,el, l->el_size); + return -PSICONV_E_OK; } void psiconv_list_foreach_el(psiconv_list l, void action(void *el)) { - int i; + psiconv_u32 i; for (i = 0; i < l->cur_len; i ++) action(psiconv_list_get(l,i)); } @@ -94,36 +123,81 @@ psiconv_list psiconv_list_clone(const psiconv_list l) { psiconv_list l2; - int i; + psiconv_u32 i; l2 = psiconv_list_new(l->el_size); + if (!l2) + return NULL; for (i = 0; i < l->cur_len; i ++) - psiconv_list_add(l2,psiconv_list_get(l,i)); + if (psiconv_list_add(l2,psiconv_list_get(l,i))) { + psiconv_list_free(l2); + return NULL; + } return l2; } -psiconv_list psiconv_list_clone_el(const psiconv_list l,void clone_el(void *el)) -{ - psiconv_list l2 = psiconv_list_clone(l); - psiconv_list_foreach_el(l2,clone_el); - return l2; -} - size_t psiconv_list_fread(psiconv_list l,size_t size, FILE *f) { size_t res; - psiconv_list_resize(l,l->cur_len + size); + if (psiconv_list_resize(l,l->cur_len + size)) + return 0; res = fread(((char *) (l->els)) + l->cur_len * l->el_size,l->el_size,size,f); l->cur_len += res; return res; } -void psiconv_list_resize(psiconv_list l,unsigned int nr) +int psiconv_list_fread_all(psiconv_list l, FILE *f) +{ + while (!feof(f)) { + if (!psiconv_list_fread(l,1024,f) && !feof(f)) + return -PSICONV_E_NOMEM; + } + return -PSICONV_E_OK; +} + +int psiconv_list_fwrite_all(const psiconv_list l, FILE *f) { + psiconv_u32 pos = 0; + psiconv_u32 written; + psiconv_u32 len = psiconv_list_length(l); + while (pos < len) { + if (!(written = fwrite(((char *)(l->els)) + pos * l->el_size,l->el_size, + len - pos,f))) + return -PSICONV_E_OTHER; + pos += written; + } + return -PSICONV_E_OK; +} + +int psiconv_list_resize(psiconv_list l,psiconv_u32 nr) +{ + void * temp; if (nr > l->max_len) { l->max_len = 1.1 * nr; l->max_len += 16 - l->max_len % 16; - l->els = realloc(l->els,l->max_len * l->el_size); + temp = realloc(l->els,l->max_len * l->el_size); + if (temp) { + l->els = temp; + return -PSICONV_E_OK; + } else + return -PSICONV_E_NOMEM; } + return -PSICONV_E_OK; } +int psiconv_list_concat(psiconv_list l, const psiconv_list extra) +{ + int res; + if (l->el_size != extra->el_size) + return -PSICONV_E_OTHER; + if ((res = psiconv_list_resize(l, + l->cur_len + extra->cur_len))) + return res; + /* Unreadable but correct. */ + memcpy(((char *) (l->els)) + l->cur_len * l->el_size,extra->els, + extra->cur_len * extra->el_size); + l->cur_len += extra->cur_len; + return 0; +} + +