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 "list.h"
8 
listnull(void * e)9 int listnull(void* e) {return e == NULL;}
10 
11 #ifndef TRUE
12 #define TRUE 1
13 #endif
14 #ifndef FALSE
15 #define FALSE 0
16 #endif
17 
18 #define DEFAULTALLOC 16
19 #define ALLOCINCR 16
20 
listnew(void)21 List* listnew(void)
22 {
23   List* l;
24 /*
25   if(!initialized) {
26     memset((void*)&DATANULL,0,sizeof(void*));
27     initialized = 1;
28   }
29 */
30   l = (List*)malloc(sizeof(List));
31   if(l) {
32     l->alloc=0;
33     l->length=0;
34     l->content=NULL;
35   }
36   return l;
37 }
38 
39 int
listfreeall(List * l)40 listfreeall(List* l)
41 {
42   if(l) {
43     int i;
44     for(i=0;i<listlength(l);i++) {
45 	void* elem = listget(l,i);
46 	if(elem != NULL) free(elem);
47     }
48   }
49   return listfree(l);
50 }
51 
52 int
listfree(List * l)53 listfree(List* l)
54 {
55   if(l) {
56     l->alloc = 0;
57     if(l->content != NULL) {free(l->content); l->content = NULL;}
58     free(l);
59   }
60   return TRUE;
61 }
62 
63 int
listsetalloc(List * l,unsigned long sz)64 listsetalloc(List* l, unsigned long sz)
65 {
66   void** newcontent = NULL;
67   if(l == NULL) return FALSE;
68   if(sz <= 0) {sz = (l->length?2*l->length:DEFAULTALLOC);}
69   if(l->alloc >= sz) {return TRUE;}
70   newcontent=(void**)calloc(sz,sizeof(void*));
71   if(newcontent != NULL && l->alloc > 0 && l->length > 0 && l->content != NULL) {
72     memcpy((void*)newcontent,(void*)l->content,sizeof(void*)*l->length);
73   }
74   if(l->content != NULL) free(l->content);
75   l->content=newcontent;
76   l->alloc=sz;
77   return TRUE;
78 }
79 
80 int
listsetlength(List * l,unsigned long sz)81 listsetlength(List* l, unsigned long sz)
82 {
83   if(l == NULL) return FALSE;
84   if(sz > l->alloc && !listsetalloc(l,sz)) return FALSE;
85   l->length = sz;
86   return TRUE;
87 }
88 
89 void*
listget(List * l,unsigned long index)90 listget(List* l, unsigned long index)
91 {
92   if(l == NULL || l->length == 0) return NULL;
93   if(index >= l->length) return NULL;
94   return l->content[index];
95 }
96 
97 int
listset(List * l,unsigned long index,void * elem)98 listset(List* l, unsigned long index, void* elem)
99 {
100   if(l == NULL) return FALSE;
101   if(index >= l->length) return FALSE;
102   l->content[index] = elem;
103   return TRUE;
104 }
105 
106 /* Insert at position i of l; will push up elements i..|seq|. */
107 int
listinsert(List * l,unsigned long index,void * elem)108 listinsert(List* l, unsigned long index, void* elem)
109 {
110   int i; /* do not make unsigned */
111   if(l == NULL) return FALSE;
112   if(index > l->length) return FALSE;
113   listsetalloc(l,0);
114   for(i=(int)l->length;i>index;i--) l->content[i] = l->content[i-1];
115   l->content[index] = elem;
116   l->length++;
117   return TRUE;
118 }
119 
120 int
listpush(List * l,void * elem)121 listpush(List* l, void* elem)
122 {
123   if(l == NULL) return FALSE;
124   if(l->length >= l->alloc) listsetalloc(l,0);
125   l->content[l->length] = elem;
126   l->length++;
127   return TRUE;
128 }
129 
130 void*
listpop(List * l)131 listpop(List* l)
132 {
133   if(l == NULL || l->length == 0) return NULL;
134   l->length--;
135   return l->content[l->length];
136 }
137 
138 void*
listtop(List * l)139 listtop(List* l)
140 {
141   if(l == NULL || l->length == 0) return NULL;
142   return l->content[l->length - 1];
143 }
144 
145 void*
listremove(List * l,unsigned long i)146 listremove(List* l, unsigned long i)
147 {
148   unsigned long len;
149   void* elem;
150   if(l == NULL || (len=l->length) == 0) return NULL;
151   if(i >= len) return NULL;
152   elem = l->content[i];
153   for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
154   l->length--;
155   return elem;
156 }
157 
158 /* Duplicate and return the content (null terminate) */
159 void**
listdup(List * l)160 listdup(List* l)
161 {
162     void** result = (void**)malloc(sizeof(void*)*(l->length+1));
163     memcpy((void*)result,(void*)l->content,sizeof(void*)*l->length);
164     result[l->length] = (void*)0;
165     return result;
166 }
167 
168 int
listcontains(List * l,void * elem)169 listcontains(List* l, void* elem)
170 {
171     unsigned long i;
172     for(i=0;i<listlength(l);i++) {
173 	if(elem == listget(l,i)) return 1;
174     }
175     return 0;
176 }
177 
178 /* Remove element by value; only removes first encountered */
179 int
listelemremove(List * l,void * elem)180 listelemremove(List* l, void* elem)
181 {
182   unsigned long len;
183   unsigned long i;
184   int found = 0;
185   if(l == NULL || (len=l->length) == 0) return 0;
186   for(i=0;i<listlength(l);i++) {
187     void* candidate = l->content[i];
188     if(elem == candidate) {
189       for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
190       l->length--;
191       found = 1;
192       break;
193     }
194   }
195   return found;
196 }
197 
198 
199 
200 
201 /* Extends list to include a unique operator
202    which remove duplicate values; NULL values removed
203    return value is always 1.
204 */
205 
206 int
listunique(List * l)207 listunique(List* l)
208 {
209     unsigned long i,j,k,len;
210     void** content;
211     if(l == NULL || l->length == 0) return 1;
212     len = l->length;
213     content = l->content;
214     for(i=0;i<len;i++) {
215         for(j=i+1;j<len;j++) {
216 	    if(content[i] == content[j]) {
217 		/* compress out jth element */
218                 for(k=j+1;k<len;k++) content[k-1] = content[k];
219 		len--;
220 	    }
221 	}
222     }
223     l->length = len;
224     return 1;
225 }
226 
227 List*
listclone(List * l)228 listclone(List* l)
229 {
230     List* clone = listnew();
231     *clone = *l;
232     clone->content = listdup(l);
233     return clone;
234 }
235