Coverage Report

Created: 2025-10-28 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/netcdf-c/libdispatch/nclist.c
Line
Count
Source
1
/* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc.
2
   See the COPYRIGHT file for more information. */
3
#include <stddef.h>
4
#include <stdlib.h>
5
#include <stdio.h>
6
#include <string.h>
7
8
#include "nclist.h"
9
10
#if defined(_WIN32) && !defined(__MINGW32__)
11
#define strcasecmp _stricmp
12
#endif
13
14
0
int nclistisnull(void* e) {return e == NULL;}
15
16
#define NCLISTDEBUG 1
17
18
#ifndef TRUE
19
4.76k
#define TRUE 1
20
#endif
21
#ifndef FALSE
22
0
#define FALSE 0
23
#endif
24
25
1
#define DEFAULTALLOC 16
26
#define ALLOCINCR 16
27
28
static int
29
nclistfail(void)
30
0
{
31
0
    fflush(stdout);
32
0
    fprintf(stderr,"NClist failure\n");
33
0
    fflush(stderr);
34
0
#ifdef NCLISTDEBUG
35
0
    abort();
36
0
#endif
37
0
    return FALSE;
38
0
}
39
40
NClist* nclistnew(void)
41
1.36k
{
42
1.36k
  NClist* l;
43
/*
44
  if(!ncinitialized) {
45
    memset((void*)&ncDATANULL,0,sizeof(void*));
46
    ncinitialized = 1;
47
  }
48
*/
49
1.36k
  l = (NClist*)calloc(1,sizeof(NClist));
50
1.36k
  if(l) {
51
1.36k
    l->alloc=0;
52
1.36k
    l->length=0;
53
1.36k
    l->content=NULL;
54
1.36k
    l->extendible = 1;
55
1.36k
  }
56
1.36k
  return l;
57
1.36k
}
58
59
int
60
nclistfree(NClist* l)
61
2.04k
{
62
2.04k
  if(l) {
63
1.36k
    l->alloc = 0;
64
1.36k
    if(l->extendible && l->content != NULL) {free(l->content); l->content = NULL;}
65
1.36k
    free(l);
66
1.36k
  }
67
2.04k
  return TRUE;
68
2.04k
}
69
70
/*
71
Free a list and its contents
72
*/
73
int
74
nclistfreeall(NClist* l)
75
1.69k
{
76
1.69k
    nclistclearall(l);
77
1.69k
    return nclistfree(l);
78
1.69k
}
79
80
/*
81
Free the contents of a list
82
*/
83
int
84
nclistclearall(NClist* l)
85
1.69k
{
86
1.69k
  size_t i,len;
87
1.69k
  if(l == NULL) return TRUE;
88
1.01k
  len = l->length;
89
1.02k
  for(i=0;i<len;i++) {
90
2
      void* value = l->content[i];
91
2
      if(value != NULL) free(value);
92
2
  }
93
1.01k
  nclistsetlength(l,0);
94
1.01k
  return TRUE;
95
1.69k
}
96
97
/*
98
Set allocated memory to newalloc elements.
99
If newalloc is zero, then just guarantee that l->content has memory allocated.
100
*/
101
int
102
nclistsetalloc(NClist* l, size_t newalloc)
103
2
{
104
2
  void** newcontent = NULL;
105
2
  size_t alloc;
106
2
  if(l == NULL) return nclistfail();
107
2
  if(newalloc == 0) newalloc = DEFAULTALLOC; /* force newalloc to be greater than 0 */
108
2
  if(l->alloc >= newalloc) {return TRUE;} /* already enough space */
109
  /* Iterate to find an allocation greater or equal to newalloc */
110
2
  alloc = l->alloc;
111
9
  while(alloc < newalloc)
112
7
      alloc = (2*alloc + 1); /* Double until we have a suitable allocation; +1 in case alloc is zero*/
113
2
  newcontent=(void**)calloc(alloc,sizeof(void*));
114
2
  if(newcontent == NULL) return nclistfail(); /* out of memory */
115
  /* Copy data, if any,  to new contents */
116
2
  if(l->alloc > 0 && l->length > 0 && l->content != NULL)
117
0
    memcpy((void*)newcontent,(void*)l->content,sizeof(void*)*l->length);
118
2
  if(l->content != NULL) free(l->content); /* reclaim old contents */
119
2
  l->content = newcontent;
120
2
  l->alloc = alloc;
121
2
  return TRUE;
122
2
}
123
124
int
125
nclistsetlength(NClist* l, size_t newlen)
126
1.02k
{
127
1.02k
  if(l == NULL) return nclistfail();
128
1.02k
  if(newlen > l->alloc && !nclistsetalloc(l,newlen)) return nclistfail();
129
1.02k
  if(newlen > l->length) {
130
      /* clear any extension */
131
1
      memset(&l->content[l->length],0,(newlen - l->length)*sizeof(void*));
132
1
  }
133
1.02k
  l->length = newlen;
134
1.02k
  return TRUE;
135
1.02k
}
136
137
void*
138
nclistget(const NClist* l, size_t index)
139
1
{
140
1
  if(l == NULL) return (nclistfail(),NULL);
141
1
  if(l->length == 0) return NULL;
142
1
  if(index >= l->length) return NULL;
143
1
  return l->content[index];
144
1
}
145
146
/* Insert at position i of l; will overwrite previous value;
147
   guarantees alloc and length
148
*/
149
int
150
nclistset(NClist* l, size_t index, void* elem)
151
0
{
152
0
  if(l == NULL) return nclistfail();
153
0
  if(!nclistsetalloc(l,index+1)) return nclistfail();
154
0
  if(index >= l->length) {
155
0
      if(!nclistsetlength(l,index+1)) return nclistfail();
156
0
  }
157
0
  l->content[index] = elem;
158
0
  return TRUE;
159
0
}
160
161
/* Insert at position i of l; will push up elements i..|seq|. */
162
int
163
nclistinsert(NClist* l, size_t index, void* elem)
164
0
{
165
0
  size_t i;
166
0
  if(l == NULL) return nclistfail();
167
0
  if(index > l->length) return nclistfail();
168
0
  nclistsetalloc(l,0);
169
0
  if(l->length > 0) {
170
0
    for(i=l->length;i>index;i--) l->content[i] = l->content[i-1];
171
0
  }
172
0
  l->content[index] = elem;
173
0
  l->length++;
174
0
  return TRUE;
175
0
}
176
177
int
178
nclistpush(NClist* l, const void* elem)
179
1
{
180
1
  if(l == NULL) return nclistfail();
181
1
  if(l->content == NULL)
182
1
      nclistsetalloc(l,0);
183
1
  if(l->length >= l->alloc) nclistsetalloc(l,l->length+1);
184
1
  l->content[l->length] = (void*)elem;
185
1
  l->length++;
186
1
  return TRUE;
187
1
}
188
189
void*
190
nclistpop(NClist* l)
191
0
{
192
0
  if(l == NULL) return (nclistfail(),NULL);
193
0
  if(l->length == 0) return NULL;
194
0
  l->length--;
195
0
  return l->content[l->length];
196
0
}
197
198
void*
199
nclisttop(NClist* l)
200
0
{
201
0
  if(l == NULL) return (nclistfail(),NULL);
202
0
  if(l->length == 0) return NULL;
203
0
  return l->content[l->length - 1];
204
0
}
205
206
void*
207
nclistremove(NClist* l, size_t i)
208
0
{
209
0
  size_t len;
210
0
  void* elem;
211
0
  if(l == NULL) return (nclistfail(),NULL);
212
0
  if((len=l->length) == 0) return NULL;
213
0
  if(i >= len) return NULL;
214
0
  elem = l->content[i];
215
0
  for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
216
0
  l->length--;
217
0
  return elem;
218
0
}
219
220
/* Match on == */
221
int
222
nclistcontains(NClist* l, void* elem)
223
0
{
224
0
    size_t i;
225
0
    for(i=0;i<nclistlength(l);i++) {
226
0
  if(elem == nclistget(l,i)) return 1;
227
0
    }
228
0
    return 0;
229
0
}
230
231
/* Match on str(case)cmp */
232
int
233
nclistmatch(NClist* l, const char* elem, int casesensitive)
234
0
{
235
0
    size_t i;
236
0
    for(i=0;i<nclistlength(l);i++) {
237
0
  const char* candidate = (const char*)nclistget(l,i);
238
0
  int match;
239
0
  if(casesensitive)
240
0
      match = strcmp(elem,candidate);
241
0
  else
242
0
      match = strcasecmp(elem,candidate);
243
0
  if(match == 0) return 1;
244
0
    }
245
0
    return 0;
246
0
}
247
248
/* Remove element by value; only removes first encountered */
249
int
250
nclistelemremove(NClist* l, void* elem)
251
0
{
252
0
  size_t len;
253
0
  size_t i;
254
0
  int found = 0;
255
0
  if(l == NULL) return nclistfail();
256
0
  if((len=l->length) == 0) return 0;
257
0
  for(i=0;i<nclistlength(l);i++) {
258
0
    void* candidate = l->content[i];
259
0
    if(elem == candidate) {
260
0
      for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
261
0
      l->length--;
262
0
      found = 1;
263
0
      break;
264
0
    }
265
0
  }
266
0
  return found;
267
0
}
268
269
/* Extends nclist to include a unique operator
270
   which remove duplicate values; NULL values removed
271
   return value is always 1.
272
*/
273
274
int
275
nclistunique(NClist* l)
276
0
{
277
0
    size_t i,j,k,len;
278
0
    void** content;
279
0
    if(l == NULL) return nclistfail();
280
0
    if(l->length == 0) return 1;
281
0
    len = l->length;
282
0
    content = l->content;
283
0
    for(i=0;i<len;i++) {
284
0
        for(j=i+1;j<len;j++) {
285
0
      if(content[i] == content[j]) {
286
    /* compress out jth element */
287
0
                for(k=j+1;k<len;k++) content[k-1] = content[k];
288
0
    len--;
289
0
      }
290
0
  }
291
0
    }
292
0
    l->length = len;
293
0
    return 1;
294
0
}
295
296
/* Duplicate a list and if deep is true, assume the contents
297
   are char** and duplicate those also */
298
NClist*
299
nclistclone(const NClist* l, int deep)
300
0
{
301
0
    NClist* clone = NULL;
302
0
    if(l == NULL) goto done;
303
0
    clone = nclistnew();
304
0
    nclistsetalloc(clone,l->length+1); /* make room for final null */
305
0
    if(!deep) {
306
0
        nclistsetlength(clone,l->length);
307
0
        memcpy((void*)clone->content,(void*)l->content,sizeof(void*)*l->length);
308
0
    } else { /*deep*/
309
0
  size_t i;
310
0
  for(i=0;i<nclistlength(l);i++) {
311
0
      char* dups = strdup(nclistget(l,i));
312
0
      if(dups == NULL) {nclistfreeall(clone); clone = NULL; goto done;}
313
0
      nclistpush(clone,dups);     
314
0
  }
315
0
    }
316
0
    clone->content[l->length] = (void*)0;
317
0
done:
318
0
    return clone;
319
0
}
320
321
void*
322
nclistextract(NClist* l)
323
0
{
324
0
    void* result = NULL;
325
0
    if(l) {
326
0
  result = l->content;
327
0
  l->alloc = 0;
328
0
  l->length = 0;
329
0
  l->content = NULL;
330
0
    }
331
0
    return result;
332
0
}
333
334
int
335
nclistsetcontents(NClist* l, void** contents, size_t alloc, size_t length)
336
0
{
337
0
    if(l == NULL) return nclistfail();
338
0
    if(l->extendible && l->content != NULL) {free(l->content);} else {l->content = NULL;}
339
0
    l->content = (void**)contents;
340
0
    l->length = length;
341
0
    l->alloc = alloc;
342
0
    l->extendible = 0;
343
0
    return 1;
344
0
}
345
346
/* Extends nclist to include a NULL that is not included
347
   in list length.
348
   return value is always 1.
349
*/
350
int
351
nclistnull(NClist* l)
352
0
{
353
0
    if(l == NULL) return nclistfail();
354
0
    if(l->length == 0) return 1;
355
0
    nclistpush(l,NULL);
356
0
    nclistsetlength(l,l->length-1);
357
0
    return 1;
358
0
}
359