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