libanim

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