2018-12-07 06:40:43 +08:00
|
|
|
/* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc.
|
2012-08-20 05:54:30 +08:00
|
|
|
See the COPYRIGHT file for more information. */
|
2010-06-03 21:24:43 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2018-11-16 01:00:38 +08:00
|
|
|
#include "includes.h"
|
2010-06-03 21:24:43 +08:00
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
int listnull(void* e) {return e == NULL;}
|
2010-06-03 21:24:43 +08:00
|
|
|
|
|
|
|
#ifndef TRUE
|
|
|
|
#define TRUE 1
|
|
|
|
#endif
|
|
|
|
#ifndef FALSE
|
|
|
|
#define FALSE 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define DEFAULTALLOC 16
|
|
|
|
#define ALLOCINCR 16
|
|
|
|
|
|
|
|
List* listnew(void)
|
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
List* l;
|
|
|
|
/*
|
|
|
|
if(!initialized) {
|
|
|
|
memset((void*)&DATANULL,0,sizeof(void*));
|
|
|
|
initialized = 1;
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
2012-08-20 05:54:30 +08:00
|
|
|
*/
|
2018-11-16 01:00:38 +08:00
|
|
|
l = (List*)emalloc(sizeof(List));
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l) {
|
|
|
|
l->alloc=0;
|
|
|
|
l->length=0;
|
|
|
|
l->content=NULL;
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
2012-08-20 05:54:30 +08:00
|
|
|
return l;
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listfree(List* l)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l) {
|
|
|
|
l->alloc = 0;
|
2018-11-16 01:00:38 +08:00
|
|
|
if(l->content != NULL) {efree(l->content); l->content = NULL;}
|
|
|
|
efree(l);
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listsetalloc(List* l, unsigned long sz)
|
|
|
|
{
|
2014-04-08 03:00:47 +08:00
|
|
|
void** newcontent = NULL;
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL) return FALSE;
|
|
|
|
if(sz <= 0) {sz = (l->length?2*l->length:DEFAULTALLOC);}
|
|
|
|
if(l->alloc >= sz) {return TRUE;}
|
2018-11-16 01:00:38 +08:00
|
|
|
newcontent=(void**)ecalloc(sz*sizeof(void*));
|
2014-04-08 03:00:47 +08:00
|
|
|
if(newcontent != NULL && l->alloc > 0 && l->length > 0 && l->content != NULL) {
|
2012-08-20 05:54:30 +08:00
|
|
|
memcpy((void*)newcontent,(void*)l->content,sizeof(void*)*l->length);
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
2018-11-16 01:00:38 +08:00
|
|
|
if(l->content != NULL) efree(l->content);
|
2012-08-20 05:54:30 +08:00
|
|
|
l->content=newcontent;
|
|
|
|
l->alloc=sz;
|
2010-06-03 21:24:43 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listsetlength(List* l, unsigned long sz)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL) return FALSE;
|
|
|
|
if(sz > l->alloc && !listsetalloc(l,sz)) return FALSE;
|
|
|
|
l->length = sz;
|
2010-06-03 21:24:43 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
void*
|
|
|
|
listget(List* l, unsigned long index)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
|
|
if(index >= l->length) return NULL;
|
|
|
|
return l->content[index];
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listset(List* l, unsigned long index, void* elem)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL) return FALSE;
|
|
|
|
if(index >= l->length) return FALSE;
|
|
|
|
l->content[index] = elem;
|
2010-06-03 21:24:43 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
/* Insert at position i of l; will push up elements i..|seq|. */
|
2010-06-03 21:24:43 +08:00
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listinsert(List* l, unsigned long index, void* elem)
|
|
|
|
{
|
|
|
|
int i; /* do not make unsigned */
|
|
|
|
if(l == NULL) return FALSE;
|
|
|
|
if(index > l->length) return FALSE;
|
|
|
|
listsetalloc(l,0);
|
|
|
|
for(i=(int)l->length;i>index;i--) l->content[i] = l->content[i-1];
|
|
|
|
l->content[index] = elem;
|
|
|
|
l->length++;
|
2010-06-03 21:24:43 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listpush(List* l, void* elem)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL) return FALSE;
|
|
|
|
if(l->length >= l->alloc) listsetalloc(l,0);
|
|
|
|
l->content[l->length] = elem;
|
|
|
|
l->length++;
|
2010-06-03 21:24:43 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
void*
|
|
|
|
listpop(List* l)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
|
|
l->length--;
|
|
|
|
return l->content[l->length];
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
void*
|
|
|
|
listtop(List* l)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
|
|
return l->content[l->length - 1];
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
void*
|
|
|
|
listremove(List* l, unsigned long i)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
unsigned long len;
|
|
|
|
void* elem;
|
|
|
|
if(l == NULL || (len=l->length) == 0) return NULL;
|
|
|
|
if(i >= len) return NULL;
|
|
|
|
elem = l->content[i];
|
|
|
|
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
|
|
|
|
l->length--;
|
2010-06-03 21:24:43 +08:00
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Duplicate and return the content (null terminate) */
|
2012-08-20 05:54:30 +08:00
|
|
|
void**
|
|
|
|
listdup(List* l)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2018-11-16 01:00:38 +08:00
|
|
|
void** result = (void**)emalloc(sizeof(void*)*(l->length+1));
|
2012-08-20 05:54:30 +08:00
|
|
|
memcpy((void*)result,(void*)l->content,sizeof(void*)*l->length);
|
|
|
|
result[l->length] = (void*)0;
|
2010-06-03 21:24:43 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listcontains(List* l, void* elem)
|
2010-06-03 21:24:43 +08:00
|
|
|
{
|
2012-08-20 05:54:30 +08:00
|
|
|
unsigned long i;
|
|
|
|
for(i=0;i<listlength(l);i++) {
|
|
|
|
if(elem == listget(l,i)) return 1;
|
|
|
|
}
|
2010-06-03 21:24:43 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-08-20 05:54:30 +08:00
|
|
|
/* Remove element by value; only removes first encountered */
|
2010-06-03 21:24:43 +08:00
|
|
|
int
|
2012-08-20 05:54:30 +08:00
|
|
|
listelemremove(List* l, void* elem)
|
|
|
|
{
|
|
|
|
unsigned long len;
|
|
|
|
unsigned long i;
|
|
|
|
int found = 0;
|
|
|
|
if(l == NULL || (len=l->length) == 0) return 0;
|
|
|
|
for(i=0;i<listlength(l);i++) {
|
|
|
|
void* candidate = l->content[i];
|
|
|
|
if(elem == candidate) {
|
|
|
|
for(i+=1;i<len;i++) l->content[i-1] = l->content[i];
|
|
|
|
l->length--;
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Extends list to include a unique operator
|
|
|
|
which remove duplicate values; NULL values removed
|
|
|
|
return value is always 1.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
listunique(List* l)
|
|
|
|
{
|
|
|
|
unsigned long i,j,k,len;
|
|
|
|
void** content;
|
|
|
|
if(l == NULL || l->length == 0) return 1;
|
|
|
|
len = l->length;
|
|
|
|
content = l->content;
|
|
|
|
for(i=0;i<len;i++) {
|
|
|
|
for(j=i+1;j<len;j++) {
|
|
|
|
if(content[i] == content[j]) {
|
|
|
|
/* compress out jth element */
|
|
|
|
for(k=j+1;k<len;k++) content[k-1] = content[k];
|
|
|
|
len--;
|
|
|
|
}
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|
2012-08-20 05:54:30 +08:00
|
|
|
}
|
|
|
|
l->length = len;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
List*
|
|
|
|
listclone(List* l)
|
|
|
|
{
|
|
|
|
List* clone = listnew();
|
|
|
|
*clone = *l;
|
|
|
|
clone->content = listdup(l);
|
|
|
|
return clone;
|
2010-06-03 21:24:43 +08:00
|
|
|
}
|