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

Step 1 in splitting PR 3068 #3086

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Release Notes {#RELEASE_NOTES}

This file contains a high-level description of this package's evolution. Releases are in reverse chronological order (most recent first). Note that, as of netcdf 4.2, the `netcdf-c++` and `netcdf-fortran` libraries have been separated into their own libraries.

## 4.9.4 - TBD

* Step 1 in splitting PR [Github #3068](https://github.com/Unidata/netcdf-c/pull/3068). Update ncjson.[ch] and ncproplist.[ch]. Also fix references to old API. Also fix include/netcdf_ncjson.h and include/netcdf_proplist.h builds. See [Github #3086](https://github.com/Unidata/netcdf-c/pull/3086) for more information.

## 4.9.3 - February 7, 2025

## Known Issues
Expand Down
19 changes: 12 additions & 7 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,26 @@ BUILT_SOURCES = netcdf_json.h netcdf_proplist.h
# marked with a macro (OPTSTATIC) that marks the entry point as
# static inside netcdf_json.h. This is an ugly hack to avoid
# having to reference libnetcdf in the nczarr code wrappers.
# Note also that we incorporate the core of ncexternl.h into the netcdf_json.h file.
# Note that the file is built in builddir in case the build
# is out of source.

# Give the recipe for building netcdf_json.h
netcdf_json.h: ${top_srcdir}/libdispatch/ncjson.c ${top_srcdir}/include/ncjson.h ${top_srcdir}/include/ncexternl.h
rm -fr ${builddir}/netcdf_json.h
cat ${srcdir}/ncjson.h | sed -e 's/NCJSON_H/NETCDF_JSON_H/' >> ${builddir}/netcdf_json.h
echo '#ifdef NETCDF_JSON_H' >> ${builddir}/netcdf_json.h
sed -e '/ncjson.h/d' < ${srcdir}/../libdispatch/ncjson.c >> ${builddir}/netcdf_json.h
cat ${srcdir}/ncjson.h \
| sed -e '/!NCJSON_H/d' \
| sed -e 's/NCJSON_H/NETCDF_JSON_H/' \
>> ${builddir}/netcdf_json.h
cat ${srcdir}/../libdispatch/ncjson.c | sed -e '/ncjson.h/d' >> ${builddir}/netcdf_json.h
echo '#endif /*NETCDF_JSON_H*/' >> ${builddir}/netcdf_json.h

# netcdf_proplist is analogous to netcdf_json but, of course, using libdispatch/ncproplist.c and include/ncproplist.h
# Give the recipe for building netcdf_proplist.h. Basically same as for netcdf_json.h
netcdf_proplist.h: ${top_srcdir}/libdispatch/ncproplist.c ${top_srcdir}/include/ncproplist.h ${top_srcdir}/include/ncexternl.h
rm -fr ${builddir}/netcdf_proplist.h
cat ${srcdir}/ncproplist.h | sed -e 's/NCPROPLIST_H/NETCDF_PROPLIST_H/' >> ${builddir}/netcdf_proplist.h
echo '#ifdef NETCDF_PROPLIST_H' >> ${builddir}/netcdf_proplist.h
sed -e '/ncproplist.h/d' < ${srcdir}/../libdispatch/ncproplist.c >> ${builddir}/netcdf_proplist.h
cat ${srcdir}/ncproplist.h \
| sed -e '/!NCPROPLIST_H/d' \
| sed -e 's/NCPROPLIST_H/NETCDF_PROPLIST_H/' \
>> ${builddir}/netcdf_proplist.h
cat ${srcdir}/../libdispatch/ncproplist.c | sed -e '/ncproplist.h/d' >> ${builddir}/netcdf_proplist.h
echo '#endif /*NETCDF_PROPLIST_H*/' >> ${builddir}/netcdf_proplist.h
2 changes: 1 addition & 1 deletion include/ncconfigure.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ unsigned long long int strtoull(const char*, char**, int);
#endif /*_WIN32*/

#ifndef nulldup
#define nulldup(s) ((s)==NULL?NULL:strdup(s))
#define nulldup(s) ((s)==NULL?s:strdup(s))
#endif

#ifndef nulllen
Expand Down
94 changes: 67 additions & 27 deletions include/ncjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
*/

#ifndef NCJSON_H
#define NCJSON_H
#define NCJSON_H 1

#ifndef OPTEXPORT
#ifdef NETCDF_JSON_H
#define OPTEXPORT static
#else /*!NETCDF_JSON_H*/
#ifdef _WIN32
#define OPTEXPORT __declspec(dllexport)
#else
#else /*!WIN32*/
#define OPTEXPORT extern
#endif
#endif /*WIN32*/
#endif /*NETCDF_JSON_H*/
#endif /*OPTEXPORT*/

/**************************************************/

/* Return codes */
#define NCJ_OK 0 /* must equal NC_NOERR in netcdf.h */
#define NCJ_ERR (-1) /* must equal NC_ERROR in netcdf.h */

/* Json object sorts (note use of term sort rather than e.g. type or discriminant) */
#define NCJ_UNDEF 0
#define NCJ_STRING 1
Expand All @@ -30,6 +35,10 @@

#define NCJ_NSORTS 8

/* Dump/text/unparse flags */
#define NCJFLAG_NONE 0
#define NCJFLAG_INDENTED 1

/* Define a struct to store primitive values as unquoted
strings. The sort will provide more info. Do not bother with
a union since the amount of saved space is minimal.
Expand All @@ -39,25 +48,25 @@ typedef struct NCjson {
int sort; /* of this object */
char* string; /* sort != DICT|ARRAY */
struct NCjlist {
size_t len;
struct NCjson** contents;
size_t alloc;
size_t len;
struct NCjson** contents;
} list; /* sort == DICT|ARRAY */
} NCjson;

/* Structure to hold result of convertinf one json sort to value of another type;
don't use union so we can know when to reclaim sval
*/
struct NCJconst {int bval; long long ival; double dval; char* sval;};
#define NCJconst_empty {0,0,0.0,NULL}

/**************************************************/
/* Extended API */

/* Return 0 if ok else -1 */
/* Return NCJ_OK if ok else NCJ_ERR */

#if defined(__cplusplus)
extern "C" {
#endif
#endif /*__cplusplus*/

/* Parse a string to NCjson*/
OPTEXPORT int NCJparse(const char* text, unsigned flags, NCjson** jsonp);
Expand All @@ -80,24 +89,35 @@ OPTEXPORT int NCJnewstringn(int sort, size_t len, const char* value, NCjson** js
/* Get dict key value by name */
OPTEXPORT int NCJdictget(const NCjson* dict, const char* key, const NCjson** valuep);

/* Functional version of NCJdictget */
OPTEXPORT NCjson* NCJdictlookup(const NCjson* dict, const char* key);

/* Convert one json sort to value of another type; don't use union so we can know when to reclaim sval */
OPTEXPORT int NCJcvt(const NCjson* value, int outsort, struct NCJconst* output);

/* Insert an atomic value to an array or dict object. */
/* Append an atomic value to an array or dict object. */
OPTEXPORT int NCJaddstring(NCjson* json, int sort, const char* s);

/* Append value to an array or dict object. */
OPTEXPORT int NCJappend(NCjson* object, NCjson* value);

/* Insert key-value pair into a dict object. key will be copied */
OPTEXPORT int NCJinsert(NCjson* object, const char* key, NCjson* value);
/* Append string value to an array or dict object. */
OPTEXPORT int NCJappendstring(NCjson* object, int sort, const char* s);

/* Insert key-value pair as strings into a dict object.
key and value will be copied */
/* Append int value to an array or dict object. */
OPTEXPORT int NCJappendint(NCjson* object, long long n);

/* Insert (string)key-(NCjson*)value pair into a dict object. key will be copied; jvalue will not */
OPTEXPORT int NCJinsert(NCjson* object, const char* key, NCjson* jvalue);

/* Insert key-value pair into a dict object. key and value will be copied */
OPTEXPORT int NCJinsertstring(NCjson* object, const char* key, const char* value);

/* Insert key-value pair where value is an int */
OPTEXPORT int NCJinsertint(NCjson* object, const char* key, long long ivalue);
/* Overwrite key-value pair in a dict object. Act like NCJinsert if key not found */
OPTEXPORT int NCJoverwrite(NCjson* object, const char* key, NCjson* value);

/* Insert key-value pair into a dict object. key and value will be copied */
OPTEXPORT int NCJinsertint(NCjson* object, const char* key, long long n);

/* Unparser to convert NCjson object to text in buffer */
OPTEXPORT int NCJunparse(const NCjson* json, unsigned flags, char** textp);
Expand All @@ -106,37 +126,57 @@ OPTEXPORT int NCJunparse(const NCjson* json, unsigned flags, char** textp);
OPTEXPORT int NCJclone(const NCjson* json, NCjson** clonep);

#ifndef NETCDF_JSON_H

/* dump NCjson* object to output file */
OPTEXPORT void NCJdump(const NCjson* json, unsigned flags, FILE*);

/* convert NCjson* object to output string */
OPTEXPORT const char* NCJtotext(const NCjson* json);
OPTEXPORT const char* NCJtotext(const NCjson* json, unsigned flags);

/* Sort a dictionary by key */
OPTEXPORT void NCJdictsort(NCjson* jdict);

#endif /*NETCDF_JSON_H*/

#if defined(__cplusplus)
}
#endif
#endif /*__cplusplus*/

/* Getters */
#define NCJsort(x) ((x)->sort)
#define NCJstring(x) ((x)->string)
#define NCJlength(x) ((x)==NULL ? 0 : (x)->list.len)
#define NCJdictlength(x) ((x)==NULL ? 0 : (x)->list.len/2)
#define NCJcontents(x) ((x)->list.contents)
#define NCJsort(x) ((x)==NULL?NCJ_UNDEF:(x)->sort)
#define NCJstring(x) ((x)==NULL?NULL:(x)->string)
#define NCJarraylength(x) ((x)==NULL ? 0 : (x)->list.len)
#define NCJdictlength(x) ((x)==NULL ? 0 : ((x)->list.len) / 2)
#define NCJcontents(x) ((x)==NULL?NULL:(x)->list.contents)
#define NCJith(x,i) ((x)->list.contents[i])
#define NCJdictith(x,i) ((x)->list.contents[2*i])
#define NCJdictkey(x,i) ((x)->list.contents[(i)*2])
#define NCJdictvalue(x,i) ((x)->list.contents[((i)*2)+1])

/* Setters */
#define NCJsetsort(x,s) (x)->sort=(s)
#define NCJsetstring(x,y) (x)->string=(y)
#define NCJsetcontents(x,c) (x)->list.contents=(c)
#define NCJsetlength(x,l) (x)->list.len=(l)
#define NCJsetarraylength(x,l) (x)->list.len=(l)
#define NCJsetdictlength(x,l) (x)->list.len=((l)*2)

/* Misc */
#define NCJisatomic(j) ((j)->sort != NCJ_ARRAY && (j)->sort != NCJ_DICT && (j)->sort != NCJ_NULL && (j)->sort != NCJ_UNDEF)

/**************************************************/
/* Error detection helper */
#undef NCJDEBUG
#ifdef NCJDEBUG
static int
NCJBREAKPOINT(int err)
{
(void)NCJBREAKPOINT;
return err;
}
#else
#define NCJBREAKPOINT(err) (err)
#endif /*NCJDEBUG*/
#define NCJcheck(expr) do{if((expr) < 0) {stat = NCJBREAKPOINT(NCJ_ERR); goto done;}}while(0)

#endif /*NCJSON_H*/


/**************************************************/

#endif /*!NCJSON_H*/ /* Leave the ! as a tag for sed */
76 changes: 51 additions & 25 deletions include/ncproplist.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@
/**************************************************/
/*
This is used to store a property list mapping a small number of
fixed-sized key strings to an arbitrary uintptr_t value. The
uintptr_t type is used to ensure that the value can be a pointer or a
small string upto sizeof(uintptr_t) - 1 (for trailing nul). The big
problem is reclaiming the value if it a pointer. The fact that the
number of keys is small makes it feasible to use linear search.
This is currently only used for plugins, but may be extended to other uses.
keys to objects. The uintptr_t type is used to ensure that the value can be a pointer or a
small string upto sizeof(uintptr_t) - 1 (for trailing nul) or an integer constant.

There are two operations that may be defined for the property:
1. reclaiming the value when proplist is free'd and property value points to allocated data of arbitrary complexity.
2. coping the value (for cloning) if it points to allocated data of arbitrary complexity.

The fact that the number of keys is small makes it feasible to use
linear search. This is currently only used for plugins, but may be
extended to other uses.
*/

/*! Proplist-related structs.
Expand All @@ -38,31 +42,48 @@ This is currently only used for plugins, but may be extended to other uses.
1. It is critical that |uintptr_t| == |void*|
*/

#define NCPROPSMAXKEY 31 /* characters assert (NCPROPSMAXKEY+1)/8 == 0*/
#define NCPROPSMAXKEY 31 /* characters; assert (NCPROPSMAXKEY+1)/8 == 0*/

/* Returns 0 => error; 1 => success */
typedef int (*NCPreclaimfcn)(uintptr_t userdata, const char* key, void* value, uintptr_t size);
/* Opaque forward */
struct NCPpair;

/* The property list proper is a sequence of these objects */
typedef struct NCProperty {
/* This function performs all of the following operations on a complex type */
typedef enum NCPtypeop {NCP_RECLAIM=1,NCP_COPY=2} NCPtypeop;

/* There are three possible types for a property value */
typedef enum NCPtype {
NCP_CONST=0, /* Value is a simple uintptr_t constant */
NCP_BYTES=2, /* Value points to a counted sequence of bytes; If a string,
then it includes the nul term character */
NCP_COMPLEX=3 /* Value points to an arbitraryily complex structure */
} NCPtype;

/* (Returns < 0 => error) (>= 0 => success) */
typedef int (*NCPtypefcn)(NCPtypeop op, struct NCPpair* input, struct NCPpair* output);

/* Expose this prefix of NCProperty; used in clone and lookup */
/* Hold just the key+value pair */
typedef struct NCPpair {
char key[NCPROPSMAXKEY+1]; /* copy of the key string; +1 for trailing nul */
uintptr_t flags;
# define NCPF_SIMPLE (1<<0) /* non-reclaimable */
# define NCPF_BYTES (1<<1) /* reclaimable bytes */
# define NCPF_COMPLEX (1<<2) /* extended case */
NCPtype sort;
uintptr_t value;
uintptr_t size; /* size = |value| as ptr to memory, if string, then include trailing nul */
uintptr_t userdata; /* extra data for following functions */
NCPreclaimfcn reclaim;
} NCProperty;
} NCPpair;

/* The property list proper is a sequence of these objects */
typedef struct NCPproperty {
NCPpair pair; /* Allowed by C language standard */
uintptr_t userdata; /* extra data for the type function */
NCPtypefcn typefcn; /* Process type operations */
} NCPproperty;

/*
The property list object.
*/
typedef struct NCproplist {
size_t alloc; /* allocated space to hold properties */
size_t count; /* # of defined properties */
NCProperty* properties;
NCPproperty* properties;
} NCproplist;

/**************************************************/
Expand All @@ -72,19 +93,24 @@ typedef struct NCproplist {
extern "C" {
#endif

/* All int valued functions return < 0 if error; >= 0 otherwise */


/* Create, free, etc. */
OPTEXPORT NCproplist* ncproplistnew(void);
OPTEXPORT int ncproplistfree(NCproplist*);

/* Locate a proplist entry */
OPTEXPORT int ncproplistadd(NCproplist* plist,const char* key, uintptr_t value); /* use when reclaim not needed */

/* Insert properties */
OPTEXPORT int ncproplistadd(NCproplist* plist,const char* key, uintptr_t value); /* use when reclaim not needed */
OPTEXPORT int ncproplistaddstring(NCproplist* plist, const char* key, const char* str); /* use when value is simple string (char*) */
OPTEXPORT int ncproplistaddbytes(NCproplist* plist, const char* key, void* value, uintptr_t size); /* use when value is simple ptr and reclaim is simple free function */
OPTEXPORT int ncproplistaddx(NCproplist* plist, const char* key, void* value, uintptr_t size, uintptr_t userdata, NCPreclaimfcn); /* fully extended case */

/* Insert an instance of type NCP_BYTES */
OPTEXPORT int ncproplistaddbytes(NCproplist* plist, const char* key, void* value, uintptr_t size);

/* Add instance of a complex type */
OPTEXPORT int ncproplistaddx(NCproplist* plist, const char* key, void* value, uintptr_t size, uintptr_t userdata, NCPtypefcn typefcn);

/* clone; keys are copies and values are copied using the NCPtypefcn */
OPTEXPORT int ncproplistclone(const NCproplist* src, NCproplist* clone);

/*
Expand All @@ -105,4 +131,4 @@ OPTEXPORT int ncproplistith(const NCproplist*, size_t i, char* const * keyp, uin
}
#endif

#endif /*NCPROPLIST_H*/
#endif /*!NCPROPLIST_H*/ /* WARNING: Do not remove the !; used in building netcdf_proplist.h */
Loading
Loading