1 /* Copyright (C) 1992-1998 The Geometry Center
2 * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3 *
4 * This file is part of Geomview.
5 *
6 * Geomview is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Geomview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Geomview; see the file COPYING. If not, write
18 * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19 * USA, or visit http://www.gnu.org.
20 */
21 #ifndef _GV_VVVEC_H_
22 #define _GV_VVVEC_H_
23
24 #include <ooglutil.h>
25
26 /*
27 * Variable-sized arrays ("vectors").
28 */
29 static inline void vvinit(vvec *v, int elsize, int minelems);
30 static inline void vvuse(vvec *v, void *buf, int allocated);
31 static inline void vvzero(vvec *v);
32 static inline void vvtrim(vvec *v);
33 static inline void vvfree(vvec *v);
34 static inline void vvneeds(vvec *v, int needed);
35 static inline void *vvindex(vvec *v, int index);
36 static inline void vvcopy(vvec *src, vvec *dest);
37
38 static inline void
vvinit(vvec * v,int elsize,int minelems)39 vvinit(vvec *v, int elsize, int minelems)
40 {
41 v->elsize = elsize;
42 v->count = 0;
43 v->malloced = 0;
44 v->dozero = 0;
45 v->allocated = -minelems;
46 v->base = NULL;
47 }
48
49 static inline void
vvuse(vvec * v,void * buf,int allocated)50 vvuse(vvec *v, void *buf, int allocated)
51 {
52 vvfree(v);
53 v->base = buf;
54 v->allocated = allocated;
55 }
56
57 static inline void
vvzero(vvec * v)58 vvzero(vvec *v)
59 {
60 v->dozero = 1;
61 if(v->allocated > v->count)
62 memset(v->base + v->elsize*v->count, 0,
63 v->elsize * (v->allocated - v->count));
64 }
65
66 /*
67 * Trim vvec to minimum size; ensure its buffer is malloced if it wasn't.
68 */
69 static inline void
vvtrim(vvec * v)70 vvtrim(vvec *v)
71 {
72 int newalloc = (v->count > 0 ? v->count : 1);
73 int want = newalloc * v->elsize;
74 static char why[] = "trimming vvec";
75
76 (void)why;
77
78 if(!v->malloced) {
79 void *base = OOGLNewNE(char, want, why);
80 if(v->base) memcpy(base, v->base, want);
81 else memset(base, '\0', want);
82 v->base = base;
83 v->malloced = 1;
84 } else if(v->allocated > v->count) {
85 v->base = (void *)OOGLRenewNE(char, v->base, want, why);
86 } else
87 return;
88 v->allocated = newalloc;
89 }
90
91 static inline void
vvfree(vvec * v)92 vvfree(vvec *v)
93 {
94 if(v->malloced) {
95 OOGLFree(v->base);
96 v->base = NULL;
97 v->malloced = 0;
98 }
99 }
100
101 static inline void
vvneeds(vvec * v,int needed)102 vvneeds(vvec *v, int needed)
103 {
104 if(needed > v->allocated) {
105 int had = v->allocated;
106 int want = needed + (needed>>2) + 1;
107
108 if(had < 0) {
109 if(want < -had)
110 want = -had;
111 had = 0;
112 } else {
113 int next = had + (had>>1) + 2;
114 if(next > needed)
115 want = next;
116 }
117
118 if(v->malloced) {
119 v->base = OOGLRenewNE(char, v->base,
120 want * v->elsize, "extending vvec");
121 if(had > v->count) had = v->count;
122 } else {
123 void *was = v->base;
124 v->base = OOGLNewNE(char, want * v->elsize, "allocating vvec");
125 if(v->count > 0 && had > 0)
126 memcpy(v->base, was, (v->count<had ? v->count:had) * v->elsize);
127 }
128 v->allocated = want;
129 v->malloced = 1;
130 if(v->dozero)
131 memset(v->base + v->elsize * had, 0,
132 v->elsize * (want-had));
133 }
134 }
135
136 static inline void *
vvindex(vvec * v,int index)137 vvindex(vvec *v, int index)
138 {
139 if(index < 0) {
140 OOGLError(1, "negative array index: %d", index);
141 return v->base;
142 }
143 if(index >= v->allocated)
144 vvneeds(v, index+1);
145 if(index >= v->count)
146 v->count = index+1;
147 return v->base + index*v->elsize;
148 }
149
150 static inline void
vvcopy(vvec * src,vvec * dest)151 vvcopy(vvec *src, vvec *dest)
152 {
153 char *newbase;
154 if(src->base == NULL) {
155 *dest = *src;
156 } else {
157 vvneeds(dest, src->allocated);
158 newbase = dest->base;
159 *dest = *src;
160 dest->base = newbase;
161 memcpy(dest->base, src->base, dest->allocated * dest->elsize);
162 }
163 }
164
165 #endif
166