#include #include #include #include #include "vector.h" #define IN_MODE "rb" #define OUT_MODE "wb" #define DEFAULT_SIZE 100 int t_malloc(struct table *t, size_t el_size, size_t size) { size_t s = size*el_size; if( s == 0 ) return YACL_EBADSIZE; if( t->data != NULL ) return YACL_ENOTFREED; t->data = malloc(s); #ifdef DEBUG fprintf(stderr, "\n%s:%d malloc addr = %p size = %u\n",__FILE__, __LINE__, t->data ,s); #endif if(t->data == NULL) return YACL_ENOTMEM; t->elements = 0; t->el_size = el_size; t->size = size; return YACL_SUCCESS; } void t_free(struct table *t) { if( t->data != NULL ) free(t->data); #ifdef DEBUG fprintf(stderr, "\n%s:%d free addr = %p size = %u\n",__FILE__, __LINE__, t->data, t->size*t->el_size); #endif t->data = NULL; t->elements = 0; t->size = 0; } int t_realloc(struct table *t, size_t elements) { struct table tmp; size_t s = t->elements*t->el_size; size_t el = t->elements; if(t->size>elements) return YACL_EBADSIZE; tmp.el_size = t->el_size; tmp.size = elements; switch(t_malloc(&tmp, tmp.el_size, tmp.size)) { case YACL_ENOTMEM: return YACL_ENOTMEM; case YACL_EBADSIZE: return YACL_EBADSIZE; } memcpy(tmp.data, t->data, s); t_free(t); t->data = tmp.data; t->elements = el; t->size = tmp.size; return YACL_SUCCESS; } void t_clear(struct table *t) { t->elements = 0; } int t_deleteEl(struct table *t, size_t n) { register char *dest = (char *)t->data; register char *src = (char *)t->data; register size_t size ; if(n >= t->elements) return YACL_EBADPOS; if( n == t->elements-1 ) { t->elements--; return YACL_SUCCESS; } dest = dest+n*t->el_size; src = dest+(n+1)*t->el_size; size = (t->elements-n+1)*t->el_size; memmove (dest, src, size); t->elements--; return YACL_SUCCESS; } /** Może lepiej byłoby kopiować element ostatni na miejsce elementu usuwanego i zmniejszać rozmiar tablicy o jeden. Taka implementacja zmniejszyłaby wymagania wydajnościowe do O(1)(obecnie O(n), ale usuwanie zaimplementowane w ten sposób może być to mylące. Może trzeba nowa funkcja usuwająca elementy w ten sposób. */ int t_fastDel( struct table *t, size_t n ) { register char *del = (char *)t->data; register char *last = (char *)t->data; if( n >= t->elements ) return YACL_EBADPOS; if( n == t->elements-1 ) { t->elements--; return YACL_SUCCESS; } del = del+n*t->el_size; last = last+(t->elements-1)*t->el_size; memcpy(del, last, t->el_size); t->elements--; return YACL_SUCCESS; } int t_insertEl(struct table *t, const void *data, size_t pos) { char *temp; if( pos>=t->size ) return YACL_EBADPOS; if( pos>=t->elements ) { return t_push(t, data); } else { temp = (char *)t->data; temp = temp+pos*t->el_size; memcpy(temp, data, t->el_size); } return YACL_SUCCESS; } int t_getEl( const struct table *t,void *buffer, size_t pos) { char *temp; if( pos>t->elements ) return YACL_EBADPOS; temp = (char *)t->data; temp = temp+pos*t->el_size; memcpy(buffer, temp, t->el_size); return YACL_SUCCESS; } /** Returns pointer to n element. */ void * t_getElPtr(const struct table *t, size_t n) { register char *temp = (char *)t->data; if( n>t->elements ) return NULL; return (void *)(temp+n*t->el_size); } int t_read(struct table *t, const char *path) { FILE *in; int ret=1; if(t->el_size == 0) return YACL_EBADSIZE; if( (in = fopen(path,IN_MODE)) == NULL) { ret = errno; errno = 0; return ret; } ret = t_fread(t, in); if(fclose(in) == EOF) return YACL_EREAD; if(ret == YACL_SUCCESS) return YACL_SUCCESS; else return YACL_EREAD; } int t_write(struct table *t, const char *path) { FILE *out; int ret; if(t->elements == 0) return YACL_EBADSIZE; if((out=fopen(path, OUT_MODE)) == NULL) { ret = errno; return ret; } ret = t_fwrite(t, out); if(fclose(out)!=0) return YACL_EWRITE; if(ret == YACL_SUCCESS) return YACL_SUCCESS; else return YACL_EWRITE; } int t_push(struct table *t, const void *data) { char *temp; if(data == NULL) return YACL_EBADBUFF; if(t->size <= t->elements) { /* Dokładamy 2 razy więcej pamięci. */ if(t->size == 0) { if(t_malloc(t, t->el_size, DEFAULT_SIZE) == YACL_ENOTMEM) return YACL_ENOTMEM; } else { if(t_realloc(t, 2*t->size)== YACL_ENOTMEM) return YACL_ENOTMEM; } } temp = (char *)t->data; /* find first free element and copy to it */ temp = temp+t->elements*t->el_size; memcpy (temp, data, t->el_size); t->elements++; return YACL_SUCCESS; } int t_pop(struct table *t, void *buffer) { char *temp; if(t->elements == 0) return YACL_EEMPTY; if(buffer == NULL) return YACL_ENVAL; temp = (char *)t->data; t->elements--; temp = temp+t->elements*t->el_size; memcpy(buffer, temp, t->el_size); return YACL_SUCCESS; } int t_copy(struct table *dest, const void *data, size_t pos, size_t n) { size_t size = dest->el_size*n; char *temp; if(pos+n>dest->size) { size_t new_size = pos+n; if(t_realloc(dest, new_size) == YACL_ENOTMEM) return YACL_ENOTMEM; } temp = (char *)dest->data; temp = temp+(dest->el_size*pos); memcpy(temp, data, size); dest->elements+=(pos+n)-dest->elements; return YACL_SUCCESS; } int t_copyListTo(struct table *t, yacl_list *l) { while(l != NULL) { if(t_push(t, l->data) != YACL_SUCCESS) return YACL_ENOTMEM; l=l->next; } return YACL_SUCCESS; } int t_fread(struct table *t, FILE *in) { char *temp; size_t ret = 1; t->elements = 0; temp = (char *)t->data; while(ret>0) { if(t->size <= t->elements) { /* Dokładamy 2 razy więcej pamięci. */ if(t->size == 0) { if(t_malloc(t, t->el_size, DEFAULT_SIZE) != YACL_SUCCESS) return YACL_ENOTMEM; } else { if(t_realloc(t, 2*t->size) != YACL_SUCCESS) return YACL_ENOTMEM; } temp = (char *)t->data; temp = temp+t->elements*t->el_size; } ret = fread(temp, t->el_size, 1, in); if(ferror(in)) { return YACL_EREAD; } if(ret>0){ t->elements++; temp = temp+t->el_size; } } return YACL_SUCCESS; } int t_fwrite(struct table *t, FILE *out) { size_t ret; ret = fwrite(t->data, t->el_size, t->elements, out); if( ret != t->elements ) { return YACL_EWRITE; } return YACL_SUCCESS; }