mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-09 08:11:38 +08:00
49737888ca
## Improvements to S3 Documentation * Create a new document *quickstart_paths.md* that give a summary of the legal path formats used by netcdf-c. This includes both file paths and URL paths. * Modify *nczarr.md* to remove most of the S3 related text. * Move the S3 text from *nczarr.md* to a new document *cloud.md*. * Add some S3-related text to the *byterange.md* document. Hopefully, this will make it easier for users to find the information they want. ## Rebuild NCZarr Testing In order to avoid problems with running make check in parallel, two changes were made: 1. The *nczarr_test* test system was rebuilt. Now, for each test. any generated files are kept in a test-specific directory, isolated from all other test executions. 2. Similarly, since the S3 test bucket is shared, any generated S3 objects are isolated using a test-specific key path. ## Other S3 Related Changes * Add code to ensure that files created on S3 are reclaimed at end of testing. * Used the bash "trap" command to ensure S3 cleanup even if the test fails. * Cleanup the S3 related configure.ac flag set since S3 is used in several places. So now one should use the option *--enable-s3* instead of *--enable-nczarr-s3*, although the latter is still kept as a deprecated alias for the former. * Get some of the github actions yml to work with S3; required fixing various test scripts adding a secret to access the Unidata S3 bucket. * Cleanup S3 portion of libnetcdf.settings.in and netcdf_meta.h.in and test_common.in. * Merge partial S3 support into dhttp.c. * Create an experimental s3 access library especially for use with Windows. It is enabled by using the options *--enable-s3-internal* (automake) or *-DENABLE_S3_INTERNAL=ON* (CMake). Also add a unit-test for it. * Move some definitions from ncrc.h to ncs3sdk.h ## Other Changes * Provide a default implementation of strlcpy and move this and similar defaults into *dmissing.c*.
309 lines
6.2 KiB
C
309 lines
6.2 KiB
C
/* Copyright 2018, UCAR/Unidata and OPeNDAP, Inc.
|
|
See the COPYRIGHT file for more information. */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "nclist.h"
|
|
|
|
#if defined(_WIN32) && !defined(__MINGW32__)
|
|
#define strcasecmp _stricmp
|
|
#endif
|
|
|
|
int nclistisnull(void* e) {return e == NULL;}
|
|
|
|
#ifndef TRUE
|
|
#define TRUE 1
|
|
#endif
|
|
#ifndef FALSE
|
|
#define FALSE 0
|
|
#endif
|
|
|
|
#define DEFAULTALLOC 16
|
|
#define ALLOCINCR 16
|
|
|
|
NClist* nclistnew(void)
|
|
{
|
|
NClist* l;
|
|
/*
|
|
if(!ncinitialized) {
|
|
memset((void*)&ncDATANULL,0,sizeof(void*));
|
|
ncinitialized = 1;
|
|
}
|
|
*/
|
|
l = (NClist*)malloc(sizeof(NClist));
|
|
if(l) {
|
|
l->alloc=0;
|
|
l->length=0;
|
|
l->content=NULL;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
int
|
|
nclistfree(NClist* l)
|
|
{
|
|
if(l) {
|
|
l->alloc = 0;
|
|
if(l->content != NULL) {free(l->content); l->content = NULL;}
|
|
free(l);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
Free a list and its contents
|
|
*/
|
|
int
|
|
nclistfreeall(NClist* l)
|
|
{
|
|
nclistclearall(l);
|
|
return nclistfree(l);
|
|
}
|
|
|
|
/*
|
|
Free the contents of a list
|
|
*/
|
|
int
|
|
nclistclearall(NClist* l)
|
|
{
|
|
size_t i,len;
|
|
if(l == NULL) return TRUE;
|
|
len = l->length;
|
|
for(i=0;i<len;i++) {
|
|
void* value = l->content[i];
|
|
if(value != NULL) free(value);
|
|
}
|
|
nclistsetlength(l,0);
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
nclistsetalloc(NClist* l, size_t sz)
|
|
{
|
|
void** newcontent = NULL;
|
|
if(l == NULL) return FALSE;
|
|
if(sz <= 0) {sz = (l->length?2*l->length:DEFAULTALLOC);}
|
|
if(l->alloc >= sz) {return TRUE;}
|
|
newcontent=(void**)calloc(sz,sizeof(void*));
|
|
if(newcontent != NULL && l->alloc > 0 && l->length > 0 && l->content != NULL) {
|
|
memcpy((void*)newcontent,(void*)l->content,sizeof(void*)*l->length);
|
|
}
|
|
if(l->content != NULL) free(l->content);
|
|
l->content=newcontent;
|
|
l->alloc=sz;
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
nclistsetlength(NClist* l, size_t newlen)
|
|
{
|
|
if(l == NULL) return FALSE;
|
|
if(newlen > l->alloc && !nclistsetalloc(l,newlen)) return FALSE;
|
|
if(newlen > l->length) {
|
|
/* clear any extension */
|
|
memset(&l->content[l->length],0,(newlen - l->length)*sizeof(void*));
|
|
}
|
|
l->length = newlen;
|
|
return TRUE;
|
|
}
|
|
|
|
void*
|
|
nclistget(const NClist* l, size_t index)
|
|
{
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
if(index >= l->length) return NULL;
|
|
return l->content[index];
|
|
}
|
|
|
|
/* Insert at position i of l; will overwrite previous value;
|
|
guarantees alloc and length
|
|
*/
|
|
int
|
|
nclistset(NClist* l, size_t index, void* elem)
|
|
{
|
|
if(l == NULL) return FALSE;
|
|
if(!nclistsetalloc(l,index+1)) return FALSE;
|
|
if(index >= l->length) {
|
|
if(!nclistsetlength(l,index+1)) return FALSE;
|
|
}
|
|
l->content[index] = elem;
|
|
return TRUE;
|
|
}
|
|
|
|
/* Insert at position i of l; will push up elements i..|seq|. */
|
|
int
|
|
nclistinsert(NClist* l, size_t index, void* elem)
|
|
{
|
|
long i; /* do not make unsigned */
|
|
if(l == NULL) return FALSE;
|
|
if(index > l->length) return FALSE;
|
|
nclistsetalloc(l,0);
|
|
for(i=(long)l->length;i>index;i--) l->content[i] = l->content[i-1];
|
|
l->content[index] = elem;
|
|
l->length++;
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
nclistpush(NClist* l, const void* elem)
|
|
{
|
|
if(l == NULL) return FALSE;
|
|
if(l->length >= l->alloc) nclistsetalloc(l,0);
|
|
l->content[l->length] = (void*)elem;
|
|
l->length++;
|
|
return TRUE;
|
|
}
|
|
|
|
void*
|
|
nclistpop(NClist* l)
|
|
{
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
l->length--;
|
|
return l->content[l->length];
|
|
}
|
|
|
|
void*
|
|
nclisttop(NClist* l)
|
|
{
|
|
if(l == NULL || l->length == 0) return NULL;
|
|
return l->content[l->length - 1];
|
|
}
|
|
|
|
void*
|
|
nclistremove(NClist* l, size_t i)
|
|
{
|
|
size_t 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--;
|
|
return elem;
|
|
}
|
|
|
|
/* Match on == */
|
|
int
|
|
nclistcontains(NClist* l, void* elem)
|
|
{
|
|
size_t i;
|
|
for(i=0;i<nclistlength(l);i++) {
|
|
if(elem == nclistget(l,i)) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Match on str(case)cmp */
|
|
int
|
|
nclistmatch(NClist* l, const char* elem, int casesensitive)
|
|
{
|
|
size_t i;
|
|
for(i=0;i<nclistlength(l);i++) {
|
|
const char* candidate = (const char*)nclistget(l,i);
|
|
int match;
|
|
if(casesensitive)
|
|
match = strcmp(elem,candidate);
|
|
else
|
|
match = strcasecmp(elem,candidate);
|
|
if(match == 0) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Remove element by value; only removes first encountered */
|
|
int
|
|
nclistelemremove(NClist* l, void* elem)
|
|
{
|
|
size_t len;
|
|
size_t i;
|
|
int found = 0;
|
|
if(l == NULL || (len=l->length) == 0) return 0;
|
|
for(i=0;i<nclistlength(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 nclist to include a unique operator
|
|
which remove duplicate values; NULL values removed
|
|
return value is always 1.
|
|
*/
|
|
|
|
int
|
|
nclistunique(NClist* l)
|
|
{
|
|
size_t 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--;
|
|
}
|
|
}
|
|
}
|
|
l->length = len;
|
|
return 1;
|
|
}
|
|
|
|
/* Duplicate a list and if deep is true, assume the contents
|
|
are char** and duplicate those also */
|
|
NClist*
|
|
nclistclone(const NClist* l, int deep)
|
|
{
|
|
NClist* clone = NULL;
|
|
if(l == NULL) goto done;
|
|
clone = nclistnew();
|
|
nclistsetalloc(clone,l->length+1); /* make room for final null */
|
|
if(!deep) {
|
|
nclistsetlength(clone,l->length);
|
|
memcpy((void*)clone->content,(void*)l->content,sizeof(void*)*l->length);
|
|
} else { /*deep*/
|
|
int i;
|
|
for(i=0;i<nclistlength(l);i++) {
|
|
char* dups = strdup(nclistget(l,i));
|
|
if(dups == NULL) {nclistfreeall(clone); clone = NULL; goto done;}
|
|
nclistpush(clone,dups);
|
|
}
|
|
}
|
|
clone->content[l->length] = (void*)0;
|
|
done:
|
|
return clone;
|
|
}
|
|
|
|
|
|
void*
|
|
nclistextract(NClist* l)
|
|
{
|
|
void* result = l->content;
|
|
l->alloc = 0;
|
|
l->length = 0;
|
|
l->content = NULL;
|
|
return result;
|
|
}
|
|
|
|
/* Extends nclist to include a NULL that is not included
|
|
in list length.
|
|
return value is always 1.
|
|
*/
|
|
int
|
|
nclistnull(NClist* l)
|
|
{
|
|
if(l == NULL || l->length == 0) return 1;
|
|
nclistpush(l,NULL);
|
|
nclistsetlength(l,l->length-1);
|
|
return 1;
|
|
}
|
|
|