dungeon_crawler
annotate prototype/anim/dynarr.c @ 67:2560a7ab0243
internalized libanim, libimago2, and libpsys
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 07 Oct 2012 02:04:00 +0300 |
parents | |
children |
rev | line source |
---|---|
nuclear@67 | 1 #include <stdio.h> |
nuclear@67 | 2 #include <stdlib.h> |
nuclear@67 | 3 #include <string.h> |
nuclear@67 | 4 #include "dynarr.h" |
nuclear@67 | 5 |
nuclear@67 | 6 /* The array descriptor keeps auxilliary information needed to manipulate |
nuclear@67 | 7 * the dynamic array. It's allocated adjacent to the array buffer. |
nuclear@67 | 8 */ |
nuclear@67 | 9 struct arrdesc { |
nuclear@67 | 10 int nelem, szelem; |
nuclear@67 | 11 int max_elem; |
nuclear@67 | 12 int bufsz; /* not including the descriptor */ |
nuclear@67 | 13 }; |
nuclear@67 | 14 |
nuclear@67 | 15 #define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc))) |
nuclear@67 | 16 |
nuclear@67 | 17 void *dynarr_alloc(int elem, int szelem) |
nuclear@67 | 18 { |
nuclear@67 | 19 struct arrdesc *desc; |
nuclear@67 | 20 |
nuclear@67 | 21 if(!(desc = malloc(elem * szelem + sizeof *desc))) { |
nuclear@67 | 22 return 0; |
nuclear@67 | 23 } |
nuclear@67 | 24 desc->nelem = desc->max_elem = elem; |
nuclear@67 | 25 desc->szelem = szelem; |
nuclear@67 | 26 desc->bufsz = elem * szelem; |
nuclear@67 | 27 return (char*)desc + sizeof *desc; |
nuclear@67 | 28 } |
nuclear@67 | 29 |
nuclear@67 | 30 void dynarr_free(void *da) |
nuclear@67 | 31 { |
nuclear@67 | 32 if(da) { |
nuclear@67 | 33 free(DESC(da)); |
nuclear@67 | 34 } |
nuclear@67 | 35 } |
nuclear@67 | 36 |
nuclear@67 | 37 void *dynarr_resize(void *da, int elem) |
nuclear@67 | 38 { |
nuclear@67 | 39 int newsz; |
nuclear@67 | 40 void *tmp; |
nuclear@67 | 41 struct arrdesc *desc; |
nuclear@67 | 42 |
nuclear@67 | 43 if(!da) return 0; |
nuclear@67 | 44 desc = DESC(da); |
nuclear@67 | 45 |
nuclear@67 | 46 newsz = desc->szelem * elem; |
nuclear@67 | 47 |
nuclear@67 | 48 if(!(tmp = realloc(desc, newsz + sizeof *desc))) { |
nuclear@67 | 49 return 0; |
nuclear@67 | 50 } |
nuclear@67 | 51 desc = tmp; |
nuclear@67 | 52 |
nuclear@67 | 53 desc->nelem = desc->max_elem = elem; |
nuclear@67 | 54 desc->bufsz = newsz; |
nuclear@67 | 55 return (char*)desc + sizeof *desc; |
nuclear@67 | 56 } |
nuclear@67 | 57 |
nuclear@67 | 58 int dynarr_empty(void *da) |
nuclear@67 | 59 { |
nuclear@67 | 60 return DESC(da)->nelem ? 0 : 1; |
nuclear@67 | 61 } |
nuclear@67 | 62 |
nuclear@67 | 63 int dynarr_size(void *da) |
nuclear@67 | 64 { |
nuclear@67 | 65 return DESC(da)->nelem; |
nuclear@67 | 66 } |
nuclear@67 | 67 |
nuclear@67 | 68 |
nuclear@67 | 69 /* stack semantics */ |
nuclear@67 | 70 void *dynarr_push(void *da, void *item) |
nuclear@67 | 71 { |
nuclear@67 | 72 struct arrdesc *desc; |
nuclear@67 | 73 int nelem; |
nuclear@67 | 74 |
nuclear@67 | 75 desc = DESC(da); |
nuclear@67 | 76 nelem = desc->nelem; |
nuclear@67 | 77 |
nuclear@67 | 78 if(nelem >= desc->max_elem) { |
nuclear@67 | 79 /* need to resize */ |
nuclear@67 | 80 struct arrdesc *tmp; |
nuclear@67 | 81 int newsz = desc->max_elem ? desc->max_elem * 2 : 1; |
nuclear@67 | 82 |
nuclear@67 | 83 if(!(tmp = dynarr_resize(da, newsz))) { |
nuclear@67 | 84 fprintf(stderr, "failed to resize\n"); |
nuclear@67 | 85 return da; |
nuclear@67 | 86 } |
nuclear@67 | 87 da = tmp; |
nuclear@67 | 88 desc = DESC(da); |
nuclear@67 | 89 desc->nelem = nelem; |
nuclear@67 | 90 } |
nuclear@67 | 91 |
nuclear@67 | 92 memcpy((char*)da + desc->nelem++ * desc->szelem, item, desc->szelem); |
nuclear@67 | 93 return da; |
nuclear@67 | 94 } |
nuclear@67 | 95 |
nuclear@67 | 96 void *dynarr_pop(void *da) |
nuclear@67 | 97 { |
nuclear@67 | 98 struct arrdesc *desc; |
nuclear@67 | 99 int nelem; |
nuclear@67 | 100 |
nuclear@67 | 101 desc = DESC(da); |
nuclear@67 | 102 nelem = desc->nelem; |
nuclear@67 | 103 |
nuclear@67 | 104 if(!nelem) return da; |
nuclear@67 | 105 |
nuclear@67 | 106 if(nelem <= desc->max_elem / 3) { |
nuclear@67 | 107 /* reclaim space */ |
nuclear@67 | 108 struct arrdesc *tmp; |
nuclear@67 | 109 int newsz = desc->max_elem / 2; |
nuclear@67 | 110 |
nuclear@67 | 111 if(!(tmp = dynarr_resize(da, newsz))) { |
nuclear@67 | 112 fprintf(stderr, "failed to resize\n"); |
nuclear@67 | 113 return da; |
nuclear@67 | 114 } |
nuclear@67 | 115 da = tmp; |
nuclear@67 | 116 desc = DESC(da); |
nuclear@67 | 117 desc->nelem = nelem; |
nuclear@67 | 118 } |
nuclear@67 | 119 desc->nelem--; |
nuclear@67 | 120 |
nuclear@67 | 121 return da; |
nuclear@67 | 122 } |