libanim

annotate src/dynarr.c @ 35:d3b583add71f

now merged
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 03 Oct 2014 17:16:51 +0300
parents fad4701f484e
children
rev   line source
nuclear@28 1 /*
nuclear@28 2 libanim - hierarchical keyframe animation library
nuclear@28 3 Copyright (C) 2012-2014 John Tsiombikas <nuclear@member.fsf.org>
nuclear@28 4
nuclear@28 5 This program is free software: you can redistribute it and/or modify
nuclear@28 6 it under the terms of the GNU Lesser General Public License as published
nuclear@28 7 by the Free Software Foundation, either version 3 of the License, or
nuclear@28 8 (at your option) any later version.
nuclear@28 9
nuclear@28 10 This program is distributed in the hope that it will be useful,
nuclear@28 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@28 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@28 13 GNU Lesser General Public License for more details.
nuclear@28 14
nuclear@28 15 You should have received a copy of the GNU Lesser General Public License
nuclear@28 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@28 17 */
nuclear@28 18
nuclear@0 19 #include <stdio.h>
nuclear@0 20 #include <stdlib.h>
nuclear@0 21 #include <string.h>
nuclear@0 22 #include "dynarr.h"
nuclear@0 23
nuclear@0 24 /* The array descriptor keeps auxilliary information needed to manipulate
nuclear@0 25 * the dynamic array. It's allocated adjacent to the array buffer.
nuclear@0 26 */
nuclear@0 27 struct arrdesc {
nuclear@0 28 int nelem, szelem;
nuclear@0 29 int max_elem;
nuclear@0 30 int bufsz; /* not including the descriptor */
nuclear@0 31 };
nuclear@0 32
nuclear@0 33 #define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc)))
nuclear@0 34
nuclear@0 35 void *dynarr_alloc(int elem, int szelem)
nuclear@0 36 {
nuclear@0 37 struct arrdesc *desc;
nuclear@0 38
nuclear@0 39 if(!(desc = malloc(elem * szelem + sizeof *desc))) {
nuclear@0 40 return 0;
nuclear@0 41 }
nuclear@0 42 desc->nelem = desc->max_elem = elem;
nuclear@0 43 desc->szelem = szelem;
nuclear@0 44 desc->bufsz = elem * szelem;
nuclear@0 45 return (char*)desc + sizeof *desc;
nuclear@0 46 }
nuclear@0 47
nuclear@0 48 void dynarr_free(void *da)
nuclear@0 49 {
nuclear@0 50 if(da) {
nuclear@0 51 free(DESC(da));
nuclear@0 52 }
nuclear@0 53 }
nuclear@0 54
nuclear@0 55 void *dynarr_resize(void *da, int elem)
nuclear@0 56 {
nuclear@0 57 int newsz;
nuclear@0 58 void *tmp;
nuclear@0 59 struct arrdesc *desc;
nuclear@0 60
nuclear@0 61 if(!da) return 0;
nuclear@0 62 desc = DESC(da);
nuclear@0 63
nuclear@0 64 newsz = desc->szelem * elem;
nuclear@0 65
nuclear@0 66 if(!(tmp = realloc(desc, newsz + sizeof *desc))) {
nuclear@0 67 return 0;
nuclear@0 68 }
nuclear@0 69 desc = tmp;
nuclear@0 70
nuclear@0 71 desc->nelem = desc->max_elem = elem;
nuclear@0 72 desc->bufsz = newsz;
nuclear@0 73 return (char*)desc + sizeof *desc;
nuclear@0 74 }
nuclear@0 75
nuclear@0 76 int dynarr_empty(void *da)
nuclear@0 77 {
nuclear@0 78 return DESC(da)->nelem ? 0 : 1;
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 int dynarr_size(void *da)
nuclear@0 82 {
nuclear@0 83 return DESC(da)->nelem;
nuclear@0 84 }
nuclear@0 85
nuclear@0 86
nuclear@0 87 /* stack semantics */
nuclear@0 88 void *dynarr_push(void *da, void *item)
nuclear@0 89 {
nuclear@0 90 struct arrdesc *desc;
nuclear@0 91 int nelem;
nuclear@0 92
nuclear@0 93 desc = DESC(da);
nuclear@0 94 nelem = desc->nelem;
nuclear@0 95
nuclear@0 96 if(nelem >= desc->max_elem) {
nuclear@0 97 /* need to resize */
nuclear@0 98 struct arrdesc *tmp;
nuclear@0 99 int newsz = desc->max_elem ? desc->max_elem * 2 : 1;
nuclear@0 100
nuclear@0 101 if(!(tmp = dynarr_resize(da, newsz))) {
nuclear@0 102 fprintf(stderr, "failed to resize\n");
nuclear@0 103 return da;
nuclear@0 104 }
nuclear@0 105 da = tmp;
nuclear@0 106 desc = DESC(da);
nuclear@0 107 desc->nelem = nelem;
nuclear@0 108 }
nuclear@0 109
nuclear@0 110 memcpy((char*)da + desc->nelem++ * desc->szelem, item, desc->szelem);
nuclear@0 111 return da;
nuclear@0 112 }
nuclear@0 113
nuclear@0 114 void *dynarr_pop(void *da)
nuclear@0 115 {
nuclear@0 116 struct arrdesc *desc;
nuclear@0 117 int nelem;
nuclear@0 118
nuclear@0 119 desc = DESC(da);
nuclear@0 120 nelem = desc->nelem;
nuclear@0 121
nuclear@0 122 if(!nelem) return da;
nuclear@0 123
nuclear@0 124 if(nelem <= desc->max_elem / 3) {
nuclear@0 125 /* reclaim space */
nuclear@0 126 struct arrdesc *tmp;
nuclear@0 127 int newsz = desc->max_elem / 2;
nuclear@0 128
nuclear@0 129 if(!(tmp = dynarr_resize(da, newsz))) {
nuclear@0 130 fprintf(stderr, "failed to resize\n");
nuclear@0 131 return da;
nuclear@0 132 }
nuclear@0 133 da = tmp;
nuclear@0 134 desc = DESC(da);
nuclear@0 135 desc->nelem = nelem;
nuclear@0 136 }
nuclear@0 137 desc->nelem--;
nuclear@0 138
nuclear@0 139 return da;
nuclear@0 140 }