/src/gdal/netcdf-c-4.7.4/libdispatch/nclist.c
Line | Count | Source |
1 | | /* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc. |
2 | | See the COPYRIGHT file for more information. */ |
3 | | #include <stdlib.h> |
4 | | #include <stdio.h> |
5 | | #include <string.h> |
6 | | |
7 | | #include "nclist.h" |
8 | | |
9 | 0 | int nclistnull(void* e) {return e == NULL;} |
10 | | |
11 | | #ifndef TRUE |
12 | 1.16M | #define TRUE 1 |
13 | | #endif |
14 | | #ifndef FALSE |
15 | 0 | #define FALSE 0 |
16 | | #endif |
17 | | |
18 | 0 | #define DEFAULTALLOC 16 |
19 | | #define ALLOCINCR 16 |
20 | | |
21 | | NClist* nclistnew(void) |
22 | 362k | { |
23 | 362k | NClist* l; |
24 | | /* |
25 | | if(!ncinitialized) { |
26 | | memset((void*)&ncDATANULL,0,sizeof(void*)); |
27 | | ncinitialized = 1; |
28 | | } |
29 | | */ |
30 | 362k | l = (NClist*)malloc(sizeof(NClist)); |
31 | 362k | if(l) { |
32 | 362k | l->alloc=0; |
33 | 362k | l->length=0; |
34 | 362k | l->content=NULL; |
35 | 362k | } |
36 | 362k | return l; |
37 | 362k | } |
38 | | |
39 | | int |
40 | | nclistfree(NClist* l) |
41 | 362k | { |
42 | 362k | if(l) { |
43 | 362k | l->alloc = 0; |
44 | 362k | if(l->content != NULL) {free(l->content); l->content = NULL;} |
45 | 362k | free(l); |
46 | 362k | } |
47 | 362k | return TRUE; |
48 | 362k | } |
49 | | |
50 | | /* |
51 | | Free a list and its contents |
52 | | */ |
53 | | int |
54 | | nclistfreeall(NClist* l) |
55 | 70.2k | { |
56 | 70.2k | size_t i,len; |
57 | 70.2k | void** content = NULL; |
58 | 70.2k | if(l == NULL) return TRUE; |
59 | 35.1k | len = l->length; |
60 | 35.1k | content = nclistextract(l); |
61 | 35.1k | for(i=0;i<len;i++) { |
62 | 0 | void* value = content[i]; |
63 | 0 | if(value != NULL) free(value); |
64 | 0 | } |
65 | 35.1k | if(content != NULL) free(content); |
66 | 35.1k | return nclistfree(l); |
67 | 70.2k | } |
68 | | |
69 | | int |
70 | | nclistsetalloc(NClist* l, size_t sz) |
71 | 287k | { |
72 | 287k | void** newcontent = NULL; |
73 | 287k | if(l == NULL) return FALSE; |
74 | 287k | if(sz <= 0) {sz = (l->length?2*l->length:DEFAULTALLOC);} |
75 | 287k | if(l->alloc >= sz) {return TRUE;} |
76 | 286k | newcontent=(void**)calloc(sz,sizeof(void*)); |
77 | 286k | if(newcontent != NULL && l->alloc > 0 && l->length > 0 && l->content != NULL) { |
78 | 52.1k | memcpy((void*)newcontent,(void*)l->content,sizeof(void*)*l->length); |
79 | 52.1k | } |
80 | 286k | if(l->content != NULL) free(l->content); |
81 | 286k | l->content=newcontent; |
82 | 286k | l->alloc=sz; |
83 | 286k | return TRUE; |
84 | 287k | } |
85 | | |
86 | | int |
87 | | nclistsetlength(NClist* l, size_t newlen) |
88 | 74.2k | { |
89 | 74.2k | if(l == NULL) return FALSE; |
90 | 74.2k | if(newlen > l->alloc && !nclistsetalloc(l,newlen)) return FALSE; |
91 | 74.2k | if(newlen > l->length) { |
92 | | /* clear any extension */ |
93 | 74.2k | memset(&l->content[l->length],0,(newlen - l->length)*sizeof(void*)); |
94 | 74.2k | } |
95 | 74.2k | l->length = newlen; |
96 | 74.2k | return TRUE; |
97 | 74.2k | } |
98 | | |
99 | | void* |
100 | | nclistget(NClist* l, size_t index) |
101 | 19.3M | { |
102 | 19.3M | if(l == NULL || l->length == 0) return NULL; |
103 | 19.3M | if(index >= l->length) return NULL; |
104 | 19.3M | return l->content[index]; |
105 | 19.3M | } |
106 | | |
107 | | /* Insert at position i of l; will overwrite previous value; |
108 | | guarantees alloc and length |
109 | | */ |
110 | | int |
111 | | nclistset(NClist* l, size_t index, void* elem) |
112 | 75.0k | { |
113 | 75.0k | if(l == NULL) return FALSE; |
114 | 75.0k | if(!nclistsetalloc(l,index+1)) return FALSE; |
115 | 75.0k | if(index >= l->length) { |
116 | 74.2k | if(!nclistsetlength(l,index+1)) return FALSE; |
117 | 74.2k | } |
118 | 75.0k | l->content[index] = elem; |
119 | 75.0k | return TRUE; |
120 | 75.0k | } |
121 | | |
122 | | /* Insert at position i of l; will push up elements i..|seq|. */ |
123 | | int |
124 | | nclistinsert(NClist* l, size_t index, void* elem) |
125 | 0 | { |
126 | 0 | long i; /* do not make unsigned */ |
127 | 0 | if(l == NULL) return FALSE; |
128 | 0 | if(index > l->length) return FALSE; |
129 | 0 | nclistsetalloc(l,0); |
130 | 0 | for(i=(long)l->length;i>index;i--) l->content[i] = l->content[i-1]; |
131 | 0 | l->content[index] = elem; |
132 | 0 | l->length++; |
133 | 0 | return TRUE; |
134 | 0 | } |
135 | | |
136 | | int |
137 | | nclistpush(NClist* l, void* elem) |
138 | 333k | { |
139 | 333k | if(l == NULL) return FALSE; |
140 | 333k | if(l->length >= l->alloc) nclistsetalloc(l,0); |
141 | 333k | l->content[l->length] = elem; |
142 | 333k | l->length++; |
143 | 333k | return TRUE; |
144 | 333k | } |
145 | | |
146 | | void* |
147 | | nclistpop(NClist* l) |
148 | 0 | { |
149 | 0 | if(l == NULL || l->length == 0) return NULL; |
150 | 0 | l->length--; |
151 | 0 | return l->content[l->length]; |
152 | 0 | } |
153 | | |
154 | | void* |
155 | | nclisttop(NClist* l) |
156 | 0 | { |
157 | 0 | if(l == NULL || l->length == 0) return NULL; |
158 | 0 | return l->content[l->length - 1]; |
159 | 0 | } |
160 | | |
161 | | void* |
162 | | nclistremove(NClist* l, size_t i) |
163 | 0 | { |
164 | 0 | size_t len; |
165 | 0 | void* elem; |
166 | 0 | if(l == NULL || (len=l->length) == 0) return NULL; |
167 | 0 | if(i >= len) return NULL; |
168 | 0 | elem = l->content[i]; |
169 | 0 | for(i+=1;i<len;i++) l->content[i-1] = l->content[i]; |
170 | 0 | l->length--; |
171 | 0 | return elem; |
172 | 0 | } |
173 | | |
174 | | /* Duplicate and return the content (null terminate) */ |
175 | | void** |
176 | | nclistdup(NClist* l) |
177 | 0 | { |
178 | 0 | void** result = (void**)malloc(sizeof(void*)*(l->length+1)); |
179 | 0 | memcpy((void*)result,(void*)l->content,sizeof(void*)*l->length); |
180 | 0 | result[l->length] = (void*)0; |
181 | 0 | return result; |
182 | 0 | } |
183 | | |
184 | | int |
185 | | nclistcontains(NClist* l, void* elem) |
186 | 0 | { |
187 | 0 | size_t i; |
188 | 0 | for(i=0;i<nclistlength(l);i++) { |
189 | 0 | if(elem == nclistget(l,i)) return 1; |
190 | 0 | } |
191 | 0 | return 0; |
192 | 0 | } |
193 | | |
194 | | /* Remove element by value; only removes first encountered */ |
195 | | int |
196 | | nclistelemremove(NClist* l, void* elem) |
197 | 0 | { |
198 | 0 | size_t len; |
199 | 0 | size_t i; |
200 | 0 | int found = 0; |
201 | 0 | if(l == NULL || (len=l->length) == 0) return 0; |
202 | 0 | for(i=0;i<nclistlength(l);i++) { |
203 | 0 | void* candidate = l->content[i]; |
204 | 0 | if(elem == candidate) { |
205 | 0 | for(i+=1;i<len;i++) l->content[i-1] = l->content[i]; |
206 | 0 | l->length--; |
207 | 0 | found = 1; |
208 | 0 | break; |
209 | 0 | } |
210 | 0 | } |
211 | 0 | return found; |
212 | 0 | } |
213 | | |
214 | | |
215 | | /* Extends nclist to include a unique operator |
216 | | which remove duplicate values; NULL values removed |
217 | | return value is always 1. |
218 | | */ |
219 | | |
220 | | int |
221 | | nclistunique(NClist* l) |
222 | 0 | { |
223 | 0 | size_t i,j,k,len; |
224 | 0 | void** content; |
225 | 0 | if(l == NULL || l->length == 0) return 1; |
226 | 0 | len = l->length; |
227 | 0 | content = l->content; |
228 | 0 | for(i=0;i<len;i++) { |
229 | 0 | for(j=i+1;j<len;j++) { |
230 | 0 | if(content[i] == content[j]) { |
231 | | /* compress out jth element */ |
232 | 0 | for(k=j+1;k<len;k++) content[k-1] = content[k]; |
233 | 0 | len--; |
234 | 0 | } |
235 | 0 | } |
236 | 0 | } |
237 | 0 | l->length = len; |
238 | 0 | return 1; |
239 | 0 | } |
240 | | |
241 | | NClist* |
242 | | nclistclone(NClist* l) |
243 | 0 | { |
244 | 0 | NClist* clone = nclistnew(); |
245 | 0 | *clone = *l; |
246 | 0 | clone->content = nclistdup(l); |
247 | 0 | return clone; |
248 | 0 | } |
249 | | |
250 | | void* |
251 | | nclistextract(NClist* l) |
252 | 35.1k | { |
253 | 35.1k | void* result = l->content; |
254 | 35.1k | l->alloc = 0; |
255 | 35.1k | l->length = 0; |
256 | | l->content = NULL; |
257 | 35.1k | return result; |
258 | 35.1k | } |