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 }
|