Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify FORTRAN access to the new plugin path mechanism #3058

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion include/netcdf_aux.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,15 @@ EXTERNL int ncaux_add_field(void* tag, const char *name, nc_type field_type,
struct NCPluginList;

/**
Parse a string into a sequence of path directories.
Parse a counted string into a sequence of path directories.

The pathlist argument has the following syntax:
paths := <empty> | dirlist
dirlist := dir | dirlist separator dir
separator := ';' | ':'
dir := <OS specific directory path>

@param pathlen length of pathlist arg
@param pathlist a string encoding a list of directories
@param sep one of ';' | ':' | '\0' where '\0' means use the platform's default separator.
@param dirs a pointer to an NCPluginPath object for returning the number and vector of directories from the parse.
Expand All @@ -121,6 +122,17 @@ will allocate the space for the vector of directory path.
The user is then responsible for free'ing that vector
(or call ncaux_plugin_path_reclaim).

Author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_parsen(size_t pathlen, const char* pathlist, char sep, struct NCPluginList* dirs);

/**
Parse a nul-terminated string into a sequence of path directories.
@param pathlist a string encoding a list of directories
@param sep one of ';' | ':' | '\0' where '\0' means use the platform's default separator.
@param dirs a pointer to an NCPluginPath object for returning the number and vector of directories from the parse.
@return ::NC_NOERR | NC_EXXX
See also the comments for ncaux_plugin_path_parsen
Author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_parse(const char* pathlist, char sep, struct NCPluginList* dirs);
Expand Down Expand Up @@ -192,6 +204,47 @@ Author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_prepend(struct NCPluginList* dirs, const char* dir);

/**************************************************/
/* FORTRAN is not good at manipulating C char** vectors,
so provide some wrappers for use by netcdf-fortran
that read/write plugin path as a single string.
For simplicity, the path separator is always semi-colon.
*/

/**
* Return the length (as in strlen) of the current plugin path directories encoded as a string.
* @return length of the string encoded plugin path.
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_stringlen(void);

/**
* Return the current sequence of directories in the internal global
* plugin path list encoded as a string path using ';' as a path separator.
* @param pathlen the length of the path argument.
* @param path a string into which the current plugin paths are encodeded.
* @return NC_NOERR | NC_EXXX
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_stringget(int pathlen, char* path);

/**
* Set the current sequence of directories in the internal global
* plugin path list to the sequence of directories encoded as a
* string path using ';' as a path separator.
* @param pathlen the length of the path argument.
* @param path a string encoding the sequence of directories and using ';' to separate them.
* @return NC_NOERR | NC_EXXX
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
EXTERNL int ncaux_plugin_path_stringset(int pathlen, const char* path);

#if defined(__cplusplus)
}
#endif
Expand Down
134 changes: 120 additions & 14 deletions libdispatch/daux.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ EXTERNL int
ncaux_abort_compound(void* tag)
{
#ifdef USE_NETCDF4
int i;
size_t i;
struct NCAUX_CMPD* cmpd = (struct NCAUX_CMPD*)tag;
if(cmpd == NULL) goto done;
if(cmpd->name) free(cmpd->name);
Expand Down Expand Up @@ -164,7 +164,7 @@ EXTERNL int
ncaux_end_compound(void* tag, nc_type* idp)
{
#ifdef USE_NETCDF4
int i;
size_t i;
int status = NC_NOERR;
struct NCAUX_CMPD* cmpd = (struct NCAUX_CMPD*)tag;

Expand Down Expand Up @@ -247,7 +247,7 @@ getpadding(size_t offset, size_t alignment)
static size_t
dimproduct(size_t ndims, int* dimsizes)
{
int i;
size_t i;
size_t product = 1;
for(i=0;i<ndims;i++) product *= (size_t)dimsizes[i];
return product;
Expand All @@ -256,7 +256,7 @@ dimproduct(size_t ndims, int* dimsizes)
static int
computefieldinfo(struct NCAUX_CMPD* cmpd)
{
int i;
size_t i;
int status = NC_NOERR;
size_t offset = 0;
size_t totaldimsize;
Expand All @@ -272,7 +272,7 @@ computefieldinfo(struct NCAUX_CMPD* cmpd)

for(offset=0,i=0;i<cmpd->nfields;i++) {
struct NCAUX_FIELD* field = &cmpd->fields[i];
int alignment = 0;
size_t alignment = 0;
nc_type firsttype = findfirstfield(cmpd->ncid,field->fieldtype);

/* only support 'c' alignment for now*/
Expand Down Expand Up @@ -432,7 +432,8 @@ and the parameters themselves (hence the unsigned int** paramsp).
EXTERNL int
ncaux_h5filterspec_parse(const char* txt, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp)
{
int i,stat = NC_NOERR;
int stat = NC_NOERR;
size_t i;
char* p;
char* sdata0 = NULL; /* what to free */
char* sdata = NULL; /* sdata0 with leading prefix skipped */
Expand Down Expand Up @@ -595,7 +596,7 @@ ncaux_h5filterspec_parselist(const char* txt0, int* formatp, size_t* nspecsp, NC
p = q + 1;
}
if(nspecs > 0) {
int count = 0;
size_t count = 0;
if((vector = (NC_H5_Filterspec**)calloc(sizeof(NC_H5_Filterspec*),nspecs)) == NULL)
{stat = NC_ENOMEM; goto done;}
/* pass 2: parse */
Expand Down Expand Up @@ -961,6 +962,7 @@ ncaux_dump_data(int ncid, int xtype, void* memory, size_t count, char** bufp)
/* Path List Utilities */

/* Path-list Parser:
@param pathlen length of the pathlist0 arg
@param pathlist0 the string to parse
@param dirs return the parsed directories -- see note below.
@param sep the separator parsing: one of ';' | ':' | '\0', where zero means use platform default.
Expand All @@ -972,19 +974,18 @@ The user is then responsible for free'ing that vector
(or call ncaux_plugin_path_reclaim).
*/
EXTERNL int
ncaux_plugin_path_parse(const char* pathlist0, char sep, NCPluginList* dirs)
ncaux_plugin_path_parsen(size_t pathlen, const char* pathlist0, char sep, NCPluginList* dirs)
{
int stat = NC_NOERR;
size_t i;
char* path = NULL;
char* p;
size_t count;
size_t plen;
char seps[2] = "\0\0"; /* will contain all allowable separators */

if(dirs == NULL) {stat = NC_EINVAL; goto done;}

if(pathlist0 == NULL || pathlist0[0] == '\0') {dirs->ndirs = 0; goto done;}
if(pathlen == 0 || pathlist0 == NULL) {dirs->ndirs = 0; goto done;}

/* If a separator is specified, use it, otherwise search for ';' or ':' */
seps[0] = sep;
Expand All @@ -995,10 +996,9 @@ ncaux_plugin_path_parse(const char* pathlist0, char sep, NCPluginList* dirs)
else
seps[0] = ':';
}
plen = strlen(pathlist0); /* assert plen > 0 */
if((path = malloc(plen+1+1))==NULL) {stat = NC_ENOMEM; goto done;}
memcpy(path,pathlist0,plen);
path[plen] = '\0'; path[plen+1] = '\0'; /* double null term */
if((path = malloc(pathlen+1+1))==NULL) {stat = NC_ENOMEM; goto done;}
memcpy(path,pathlist0,pathlen);
path[pathlen] = '\0'; path[pathlen+1] = '\0'; /* double null term */

for(count=0,p=path;*p;p++) {
if(strchr(seps,*p) == NULL)
Expand Down Expand Up @@ -1029,6 +1029,20 @@ ncaux_plugin_path_parse(const char* pathlist0, char sep, NCPluginList* dirs)
return stat;
}

/* Wrapper around ncaux_plugin_path_parsen
to allow passing a nul-terminated string to parse.
@param pathlist0 the nul-termiated string to parse
@param dirs return the parsed directories -- see note below.
@param sep the separator parsing: one of ';' | ':' | '\0', where zero means use platform default.
@return NC_NOERR || NC_EXXX
See also the comments for ncaux_plugin_path_parsen.
*/
EXTERNL int
ncaux_plugin_path_parse(const char* pathlist0, char sep, NCPluginList* dirs)
{
return ncaux_plugin_path_parsen(nulllen(pathlist0),pathlist0,sep,dirs);
}

/*
Path-list concatenator where given a vector of directories,
concatenate all dirs with specified separator.
Expand Down Expand Up @@ -1168,3 +1182,95 @@ ncaux_plugin_path_prepend(struct NCPluginList* dirs, const char* dir)
done:
return stat;
}

/* FORTRAN is not good at manipulating C char** vectors,
so provide some wrappers for use by netcdf-fortran
that read/write plugin path as a single string.
For simplicity, the path separator is always semi-colon.
*/

/**
* Return the length (as in strlen) of the current plugin path directories encoded as a string.
* @return length of the string encoded plugin path or -1 if failed.
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
int
ncaux_plugin_path_stringlen(void)
{
int len = 0;
int stat = NC_NOERR;
struct NCPluginList npl = {0,NULL};
char* buf = NULL;

/* Get the list of dirs */
if((stat = nc_plugin_path_get(&npl))) goto done;
/* Convert to a string path separated by ';' */
if((stat = ncaux_plugin_path_tostring(&npl,';',&buf))) goto done;
len = nulllen(buf);

done:
if(npl.dirs != NULL) {(void)ncaux_plugin_path_clear(&npl);}
nullfree(buf);
if(stat) return -1; else return len;
}

/**
* Return the current sequence of directories in the internal global
* plugin path list encoded as a string path using ';' as a path separator.
* @param pathlen the length of the path argument.
* @param path a string into which the current plugin paths are encodeded.
* @return NC_NOERR | NC_EXXX
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
int
ncaux_plugin_path_stringget(int pathlen, char* path)
{
int stat = NC_NOERR;
struct NCPluginList npl = {0,NULL};
char* buf = NULL;

if(pathlen == 0 || path == NULL) {stat = NC_EINVAL; goto done;}

/* Get the list of dirs */
if((stat = nc_plugin_path_get(&npl))) goto done;
/* Convert to a string path separated by ';' */
if((stat = ncaux_plugin_path_tostring(&npl,';',&buf))) goto done;
strncpy(path,buf,(size_t)pathlen);

done:
nullfree(buf);
if(npl.dirs != NULL) {(void)ncaux_plugin_path_clear(&npl);}
return stat;
}

/**
* Set the current sequence of directories in the internal global
* plugin path list to the sequence of directories encoded as a
* string path using ';' as a path separator.
* @param pathlen the length of the path argument.
* @param path a string encoding the sequence of directories and using ';' to separate them.
* @return NC_NOERR | NC_EXXX
* @author Dennis Heimbigner
*
* @author: Dennis Heimbigner
*/
int
ncaux_plugin_path_stringset(int pathlen, const char* path)
{
int stat = NC_NOERR;
struct NCPluginList npl = {0,NULL};

if(pathlen == 0 || path == NULL) {stat = NC_EINVAL; goto done;}
/* Parse the incoming path */
if((stat = ncaux_plugin_path_parsen((size_t)pathlen,path,';',&npl))) goto done;
/* set the list of dirs */
if((stat = nc_plugin_path_set(&npl))) goto done;

done:
if(npl.dirs != NULL) {(void)ncaux_plugin_path_clear(&npl);}
return stat;
}
1 change: 1 addition & 0 deletions unit_test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ endif
EXTRA_DIST = CMakeLists.txt run_s3sdk.sh run_reclaim_tests.sh run_aws_config.sh run_pluginpaths.sh run_dfaltpluginpath.sh
EXTRA_DIST += nctest_netcdf4_classic.nc reclaim_tests.cdl
EXTRA_DIST += ref_get.txt ref_set.txt
EXTRA_DIST += ref_xget.txt ref_xset.txt

CLEANFILES = reclaim_tests*.txt reclaim_tests.nc tmp_*.txt

Expand Down
1 change: 1 addition & 0 deletions unit_test/ref_xget.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testxget(global): /zero;/one;/two;/three;/four
2 changes: 2 additions & 0 deletions unit_test/ref_xset.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
testxset(global): before: /zero;/one;/two;/three;/four
testxset(global): after: /zero;/one;/mod;/two;/three;/four
18 changes: 17 additions & 1 deletion unit_test/run_pluginpaths.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ testset() {
printf "testset(nczarr): after: %s\n" `${TP} -x "set:${DFALT},set:${DFALTSET},get:nczarr"` >> ${filename}.txt
}

# Test the ncaux set/get/clear functions */
testxget() {
filenamefor tmp xget
# print out the global state
printf "testxget(global): %s\n" `${TP} -x "xset:${DFALT},xget:global"` >> ${filename}.txt
}

testxset() {
filenamefor tmp xset
# print out the global state, modify it and print again
printf "testxset(global): before: %s\n" `${TP} -x "xset:${DFALT},xget:global"` >> ${filename}.txt
printf "testxset(global): after: %s\n" `${TP} -x "xset:${DFALT},xset:${DFALTSET},xget:global"` >> ${filename}.txt
}

#########################

cleanup() {
Expand All @@ -98,7 +112,7 @@ init() {

# Verify output for a specific action
verify() {
for action in get set ; do
for action in get set xget xset; do
if diff -wBb ${srcdir}/ref_${action}.txt tmp_${action}.txt ; then
echo "***PASS: $action"
else
Expand All @@ -111,5 +125,7 @@ verify() {
init
testget
testset
testxget
testxset
verify
cleanup
Loading
Loading