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