1 /* Copyright 2018-2018 University Corporation for Atmospheric
2    Research/Unidata. */
3 /**
4  * @file
5  * @internal This header file contains macros, types and prototypes
6  * used to build and manipulate the netCDF metadata model.
7  *
8  * @author Ed Hartnett, Dennis Heimbigner, Ward Fisher
9  */
10 
11 #ifndef _NC4INTERNAL_
12 #define _NC4INTERNAL_
13 #include "netcdf.h"
14 
15 #include "config.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ctype.h>
19 #include <string.h>
20 
21 #include "nc_logging.h"
22 #include "ncindex.h"
23 #include "nc_provenance.h"
24 #include "nchashmap.h"
25 
26 #include "netcdf_f.h"
27 #include "netcdf_mem.h"
28 #include "netcdf_filter.h"
29 #ifdef USE_PARALLEL
30 #include "netcdf_par.h"
31 #endif /* USE_PARALLEL */
32 
33 /* Always needed */
34 #include "nc.h"
35 
36 /** The file ID is stored in the first two bytes of ncid. */
37 #define FILE_ID_MASK (0xffff0000)
38 
39 /** The group ID is stored in the last two bytes of ncid. */
40 #define GRP_ID_MASK (0x0000ffff)
41 
42 /** File and group IDs are each 16 bits of the ncid. */
43 #define ID_SHIFT (16)
44 
45 /* typedef enum {GET, PUT} NC_PG_T; */
46 /** These are the different objects that can be in our hash-lists. */
47 typedef enum {NCNAT, NCVAR, NCDIM, NCATT, NCTYP, NCFLD, NCGRP, NCFIL} NC_SORT;
48 
49 /** The netCDF V2 error code. */
50 #define NC_V2_ERR (-1)
51 
52 /** The name of the root group. */
53 #define NC_GROUP_NAME "/"
54 
55 /** One mega-byte. */
56 #define MEGABYTE 1048576
57 
58 /** The HDF5 ID for the szip filter. */
59 #define HDF5_FILTER_SZIP 4
60 
61 #define X_SCHAR_MIN     (-128)          /**< Minimum signed char value. */
62 #define X_SCHAR_MAX     127             /**< Maximum signed char value. */
63 #define X_UCHAR_MAX     255U            /**< Maximum unsigned char value. */
64 #define X_SHORT_MIN     (-32768)        /**< Minimum short value. */
65 #define X_SHRT_MIN      X_SHORT_MIN     /**< This alias is compatible with limits.h. */
66 #define X_SHORT_MAX     32767           /**< Maximum short value. */
67 #define X_SHRT_MAX      X_SHORT_MAX     /**< This alias is compatible with limits.h. */
68 #define X_USHORT_MAX    65535U          /**< Maximum unsigned short value. */
69 #define X_USHRT_MAX     X_USHORT_MAX    /**< This alias is compatible with limits.h. */
70 #define X_INT_MIN       (-2147483647-1) /**< Minimum int value. */
71 #define X_INT_MAX       2147483647      /**< Maximum int value. */
72 #define X_LONG_MIN      X_INT_MIN       /**< Minimum long value. */
73 #define X_LONG_MAX      X_INT_MAX       /**< Maximum long value. */
74 #define X_UINT_MAX      4294967295U     /**< Maximum unsigned int value. */
75 #define X_INT64_MIN     (-9223372036854775807LL-1LL)  /**< Minimum int64 value. */
76 #define X_INT64_MAX     9223372036854775807LL /**< Maximum int64 value. */
77 #define X_UINT64_MAX    18446744073709551615ULL /**< Maximum unsigned int64 value. */
78 #ifdef _WIN32 /* Windows, of course, has to be a *little* different. */
79 #define X_FLOAT_MAX     3.402823466e+38f
80 #else
81 #define X_FLOAT_MAX     3.40282347e+38f /**< Maximum float value. */
82 #endif /* _WIN32 */
83 #define X_FLOAT_MIN     (-X_FLOAT_MAX)  /**< Minimum float value. */
84 #define X_DOUBLE_MAX    1.7976931348623157e+308 /**< Maximum double value. */
85 #define X_DOUBLE_MIN    (-X_DOUBLE_MAX)         /**< Minimum double value. */
86 
87 /** This is the number of netCDF atomic types. */
88 #define NUM_ATOMIC_TYPES (NC_MAX_ATOMIC_TYPE + 1)
89 
90 /** Number of parameters needed for ZLIB filter. */
91 #define CD_NELEMS_ZLIB 1
92 
93 /** Get a pointer to the NC_FILE_INFO_T from dispatchdata field. */
94 #define NC4_DATA(nc) ((NC_FILE_INFO_T *)(nc)->dispatchdata)
95 
96 /** Set a pointer to the NC_FILE_INFO_T in the dispatchdata field. */
97 #define NC4_DATA_SET(nc,data) ((nc)->dispatchdata = (void *)(data))
98 
99 /* Reserved attribute flags: must be powers of 2. */
100 /** Hidden attributes; immutable and unreadable thru API. */
101 #define HIDDENATTRFLAG 1
102 
103 /** Readonly global attributes; readable, but immutable thru the
104  * API. */
105 #define READONLYFLAG 2
106 
107 /** Subset of readonly flags; readable by name only thru the API. */
108 #define NAMEONLYFLAG 4
109 
110 /** Subset of readonly flags; Value is actually in file. */
111 #define MATERIALIZEDFLAG 8
112 
113 /** Boolean type, to make the code easier to read. */
114 typedef enum {NC_FALSE = 0, NC_TRUE = 1} nc_bool_t;
115 
116 /* Forward declarations. */
117 struct NC_GRP_INFO;
118 struct NC_TYPE_INFO;
119 
120 /**
121  * This struct provides indexed Access to Meta-data objects. See the
122  * document docs/indexing.dox for detailed information.
123  *
124  * Basically it provides a common header and use NCindex instances
125  * instead of linked lists.
126  *
127  * WARNING: ALL OBJECTS THAT CAN BE INSERTED INTO AN NCindex MUST HAVE
128  * AN INSTANCE of NC_OBJ AS THE FIRST FIELD.
129 */
130 typedef struct NC_OBJ
131 {
132     NC_SORT sort; /**< Type of object. */
133     char* name;   /**< Name, assumed to be null terminated. */
134     size_t id;    /**< This objects ID. */
135 } NC_OBJ;
136 
137 /**
138  * This struct holds information about reserved attributes. These
139  * attributes cannot be created or read by the user (through the
140  * netCDF API).  */
141 typedef struct NC_reservedatt
142 {
143     const char *name; /**< Name of the reserved attribute. */
144     int flags;        /**< Flags that control handling of reserved attribute. */
145 } NC_reservedatt;
146 
147 /** This is a struct to handle the dimension metadata. */
148 typedef struct NC_DIM_INFO
149 {
150     NC_OBJ hdr;             /**< The hdr contains the name and ID. */
151     struct NC_GRP_INFO *container;  /**< Pointer to containing group. */
152     size_t len;             /**< Length of this dimension. */
153     nc_bool_t unlimited;    /**< True if the dimension is unlimited */
154     nc_bool_t extended;     /**< True if the dimension needs to be extended. */
155     nc_bool_t too_long;     /**< True if len is too big to fit in local size_t. */
156     void *format_dim_info;  /**< Pointer to format-specific dim info. */
157     struct NC_VAR_INFO *coord_var; /**< The coord var, if it exists. */
158 } NC_DIM_INFO_T;
159 
160 /** This is a struct to handle the attribute metadata. */
161 typedef struct NC_ATT_INFO
162 {
163     NC_OBJ hdr;             /**< The hdr contains the name and ID. */
164     struct NC_OBJ *container;    /**< Pointer to containing group|var. */
165     int len;                /**< Length of attribute data. */
166     nc_bool_t dirty;        /**< True if attribute modified. */
167     nc_bool_t created;      /**< True if attribute already created. */
168     nc_type nc_typeid;      /**< NetCDF type of attribute's data. */
169     void *format_att_info;  /**< Pointer to format-specific att info. */
170     void *data;             /**< The attribute data. */
171     nc_vlen_t *vldata;      /**< VLEN data (only used for vlen types). */
172     char **stdata;          /**< String data (only for string type). */
173 } NC_ATT_INFO_T;
174 
175 /** This is a struct to handle the var metadata. */
176 typedef struct NC_VAR_INFO
177 {
178     NC_OBJ hdr;                  /**< The hdr contains the name and ID. */
179     char *alt_name;              /**< Used if name in dispatcher must be different from hdr.name. */
180     struct NC_GRP_INFO *container; /**< Pointer to containing group. */
181     size_t ndims;                /**< Number of dims. */
182     int *dimids;                 /**< Dim IDs. */
183     NC_DIM_INFO_T **dim;         /**< Pointer to array of NC_DIM_INFO_T. */
184     nc_bool_t is_new_var;        /**< True if variable is newly created. */
185     nc_bool_t was_coord_var;     /**< True if variable was a coordinate var, but either the dim or var has been renamed. */
186     nc_bool_t became_coord_var;  /**< True if variable _became_ a coordinate var, because either the dim or var has been renamed. */
187     nc_bool_t fill_val_changed;  /**< True if variable's fill value changes after it has been created. */
188     nc_bool_t attr_dirty;        /**< True if variable's attributes are dirty and should be rewritten. */
189     nc_bool_t created;           /**< Variable has already been created (_not_ that it was just created). */
190     nc_bool_t written_to;        /**< True if variable has data written to it. */
191     struct NC_TYPE_INFO *type_info; /**< Contains info about the variable type. */
192     int atts_read;               /**< If true, the atts have been read. */
193     nc_bool_t meta_read;         /**< True if this vars metadata has been completely read. */
194     nc_bool_t coords_read;       /**< True if this var has hidden coordinates att, and it has been read. */
195     NCindex *att;                /**< List of NC_ATT_INFO_T. */
196     nc_bool_t no_fill;           /**< True if no fill value is defined for var. */
197     void *fill_value;            /**< Pointer to fill value, or NULL. */
198     size_t *chunksizes;          /**< For chunked storage, an array (size ndims) of chunksizes. */
199     int storage;                 /**< Storage of this var, compact, contiguous, or chunked. */
200     int endianness;              /**< What endianness for the var? */
201     int parallel_access;         /**< Type of parallel access for I/O on variable (collective or independent). */
202     nc_bool_t shuffle;           /**< True if var has shuffle filter applied. */
203     nc_bool_t fletcher32;        /**< True if var has fletcher32 filter applied. */
204     size_t chunk_cache_size;     /**< Size in bytes of the var chunk chache. */
205     size_t chunk_cache_nelems;   /**< Number of slots in var chunk cache. */
206     float chunk_cache_preemption; /**< Chunk cache preemtion policy. */
207     void *format_var_info;       /**< Pointer to any binary format info. */
208     void* filters;             /**< Record of the list of filters to be applied to var data; format dependent */
209 } NC_VAR_INFO_T;
210 
211 /** This is a struct to handle the field metadata from a user-defined
212  * type. */
213 typedef struct NC_FIELD_INFO
214 {
215     NC_OBJ hdr; /**< The hdr contains the name and ID. */
216     nc_type nc_typeid; /**< The type of this field. */
217     size_t offset;     /**< Offset in bytes of field. */
218     int ndims;         /**< Number of dims. */
219     int *dim_size;     /**< Dim sizes. */
220     void *format_field_info;  /**< Pointer to any binary format info for field. */
221 } NC_FIELD_INFO_T;
222 
223 /** This is a struct to handle metadata for a user-defined enum
224  * type. */
225 typedef struct NC_ENUM_MEMBER_INFO
226 {
227     char *name;  /**< Name of member. */
228     void *value; /**< Value of member. */
229 } NC_ENUM_MEMBER_INFO_T;
230 
231 /** This is a struct to handle metadata for a user-defined type. */
232 typedef struct NC_TYPE_INFO
233 {
234     NC_OBJ hdr;            /**< The hdr contains the name and ID. */
235     struct NC_GRP_INFO *container; /**< Containing group */
236     unsigned rc;                 /**< Ref. count of objects using this type */
237     int endianness;              /**< What endianness for the type? */
238     size_t size;                 /**< Size of the type in memory, in bytes */
239     nc_bool_t committed;         /**< True when datatype is committed in the file */
240     nc_type nc_type_class;       /**< NC_VLEN, NC_COMPOUND, NC_OPAQUE, NC_ENUM, NC_INT, NC_FLOAT, or NC_STRING. */
241     void *format_type_info;      /**< HDF5-specific type info. */
242 
243     /** Information for each type or class */
244     union {
245         struct {
246             NClist* enum_member;    /**< <! NClist<NC_ENUM_MEMBER_INFO_T*> */
247             nc_type base_nc_typeid; /**< Typeid of the base type. */
248         } e;                        /**< Enum */
249         struct Fields {
250             NClist* field;        /**< <! NClist<NC_FIELD_INFO_T*> */
251         } c;                      /**< Compound */
252         struct {
253             nc_type base_nc_typeid; /**< Typeid of the base type. */
254         } v;                     /**< Variable-length. */
255     } u;                         /**< Union of structs, for each type/class. */
256 } NC_TYPE_INFO_T;
257 
258 /** This holds information for one group. Groups reproduce with
259  * parthenogenesis. */
260 typedef struct NC_GRP_INFO
261 {
262     NC_OBJ hdr;                   /**< The hdr contains the name and ID. */
263     void *format_grp_info;        /**< Pointer to binary format info for group. */
264     struct NC_FILE_INFO *nc4_info; /**< Pointer containing NC_FILE_INFO_T. */
265     struct NC_GRP_INFO *parent;  /**< Pointer tp parent group. */
266     int atts_read;               /**< True if atts have been read for this group. */
267     NCindex* children;           /**< NCindex<struct NC_GRP_INFO*> */
268     NCindex* dim;                /**< NCindex<NC_DIM_INFO_T> * */
269     NCindex* att;                /**< NCindex<NC_ATT_INFO_T> * */
270     NCindex* type;               /**< NCindex<NC_TYPE_INFO_T> * */
271     /* Note that this is the list of vars with position == varid */
272     NCindex* vars;               /**< NCindex<NC_VAR_INFO_T> * */
273 } NC_GRP_INFO_T;
274 
275 /* These constants apply to the cmode parameter in the
276  * HDF5_FILE_INFO_T defined below. */
277 /* Make sure they do not conflict with defined flags in netcdf.h */
278 #define NC_CREAT 0x10002      /**< in create phase, cleared by ncendef */
279 #define NC_INDEF 0x10008      /**< in define mode, cleared by ncendef */
280 #define NC_NSYNC 0x10010   /**< synchronise numrecs on change */
281 #define NC_HSYNC 0x10020   /**< synchronise whole header on change */
282 #define NC_NDIRTY 0x10040  /**< numrecs has changed */
283 #define NC_HDIRTY 0x10080  /**< header info has changed */
284 
285 /** This is the metadata we need to keep track of for each
286   * netcdf-4/HDF5 file. */
287 
288 typedef struct  NC_FILE_INFO
289 {
290     NC_OBJ hdr;
291     NC *controller; /**< Pointer to containing NC. */
292 #ifdef USE_PARALLEL4
293     MPI_Comm comm;  /**< Copy of MPI Communicator used to open the file. */
294     MPI_Info info;  /**< Copy of MPI Information Object used to open the file. */
295 #endif
296     int flags;      /**< Flags used to open the file. */
297     int cmode;      /**< Create mode used to create the file. */
298     nc_bool_t parallel;   /**< True if file is open for parallel access */
299     nc_bool_t redef;      /**< True if redefining an existing file */
300     int fill_mode;        /**< Fill mode for vars - Unused internally currently */
301     nc_bool_t no_write;   /**< true if nc_open has mode NC_NOWRITE. */
302     NC_GRP_INFO_T *root_grp; /**< Pointer to root group. */
303     short next_nc_grpid;  /**< Next available group ID. */
304     int next_typeid;      /**< Next available type ID. */
305     int next_dimid;       /**< Next available dim ID. */
306     /* Provide convenience vectors indexed by the object id.  This
307        allows for direct conversion of e.g. an nc_type to the
308        corresponding NC_TYPE_INFO_T object. */
309     NClist *alldims;   /**< List of all dims. */
310     NClist *alltypes;  /**< List of all types. */
311     NClist *allgroups; /**< List of all groups, including root group. */
312     void *format_file_info; /**< Pointer to binary format info for file. */
313     NC4_Provenance provenance; /**< File provenence info. */
314     struct NC4_Memio
315     {
316         NC_memio memio; /**< What we sent to image_init and what comes back. */
317         int locked;     /**< Do not copy and do not free. */
318         int persist;    /**< Should file be persisted out on close? */
319         int inmemory;   /**< NC_INMEMORY flag was set. */
320         int diskless;   /**< NC_DISKLESS flag was set => inmemory. */
321         int created;    /**< 1 => create, 0 => open. */
322         unsigned int imageflags; /**< for H5LTopen_file_image. */
323         size_t initialsize;      /**< Initial size. */
324         void *udata;    /**< Extra memory allocated in NC4_image_init. */
325     } mem;
326 } NC_FILE_INFO_T;
327 
328 /** Variable Length Datatype struct in memory. Must be identical to
329  * HDF5 hvl_t. (This is only used for VL sequences, not VL strings,
330  * which are stored in char *'s) */
331 typedef struct
332 {
333     size_t len; /**< Length of VL data (in base type units) */
334     void *p;    /**< Pointer to VL data */
335 } nc_hvl_t;
336 
337 /* Misc functions */
338 extern int NC4_inq_atomic_type(nc_type typeid1, char *name, size_t *size);
339 extern int NC4_lookup_atomic_type(const char *name, nc_type* idp, size_t *sizep);
340 
341 /* These functions convert between netcdf and HDF5 types. */
342 extern int nc4_get_typelen_mem(NC_FILE_INFO_T *h5, nc_type xtype, size_t *len);
343 extern int nc4_convert_type(const void *src, void *dest, const nc_type src_type,
344                      const nc_type dest_type, const size_t len, int *range_error,
345                      const void *fill_value, int strict_nc3);
346 
347 /* These functions do HDF5 things. */
348 extern int nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
349 extern int nc4_read_atts(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
350 
351 /* Find items in the in-memory lists of metadata. */
352 extern int nc4_find_nc_grp_h5(int ncid, NC **nc, NC_GRP_INFO_T **grp,
353                        NC_FILE_INFO_T **h5);
354 extern int nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_FILE_INFO_T **h5);
355 extern int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp);
356 extern int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim,
357                  NC_GRP_INFO_T **dim_grp);
358 extern int nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var);
359 extern int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len);
360 extern int nc4_find_type(const NC_FILE_INFO_T *h5, int typeid1, NC_TYPE_INFO_T **type);
361 extern NC_TYPE_INFO_T *nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name);
362 extern NC_TYPE_INFO_T *nc4_rec_find_equal_type(NC_GRP_INFO_T *start_grp, int ncid1,
363                                         NC_TYPE_INFO_T *type);
364 extern int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
365                     NC_ATT_INFO_T **att);
366 extern int nc4_find_grp_h5_var(int ncid, int varid, NC_FILE_INFO_T **h5,
367                         NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var);
368 extern int nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name,
369                      int attnum, NC_ATT_INFO_T **att);
370 extern int nc4_get_typeclass(const NC_FILE_INFO_T *h5, nc_type xtype,
371                       int *type_class);
372 
373 /* Free various types */
374 extern int nc4_type_free(NC_TYPE_INFO_T *type);
375 
376 /* These list functions add and delete vars, atts. */
377 extern int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
378 extern int nc4_nc4f_list_del(NC_FILE_INFO_T *h5);
379 extern int nc4_file_list_add(int ncid, const char *path, int mode,
380                       void **dispatchdata);
381 extern int nc4_file_list_get(int ncid, char **path, int *mode,
382                       void **dispatchdata);
383 extern int nc4_file_list_del(int ncid);
384 extern int nc4_file_change_ncid(int ncid, unsigned short new_ncid_index);
385 extern int nc4_var_list_add(NC_GRP_INFO_T* grp, const char* name, int ndims,
386                      NC_VAR_INFO_T **var);
387 extern int nc4_var_list_add2(NC_GRP_INFO_T* grp, const char* name,
388                       NC_VAR_INFO_T **var);
389 extern int nc4_var_set_ndims(NC_VAR_INFO_T *var, int ndims);
390 extern int nc4_var_list_del(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
391 extern int nc4_dim_list_add(NC_GRP_INFO_T *grp, const char *name, size_t len,
392                      int assignedid, NC_DIM_INFO_T **dim);
393 extern int nc4_dim_list_del(NC_GRP_INFO_T *grp, NC_DIM_INFO_T *dim);
394 extern int nc4_type_new(size_t size, const char *name, int assignedid,
395                  NC_TYPE_INFO_T **type);
396 extern int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name,
397                       NC_TYPE_INFO_T **type);
398 extern int nc4_type_list_del(NC_GRP_INFO_T *grp, NC_TYPE_INFO_T *type);
399 extern int nc4_type_free(NC_TYPE_INFO_T *type);
400 extern int nc4_field_list_add(NC_TYPE_INFO_T* parent, const char *name,
401                        size_t offset, nc_type xtype, int ndims,
402                        const int *dim_sizesp);
403 extern int nc4_att_list_add(NCindex *list, const char *name, NC_ATT_INFO_T **att);
404 extern int nc4_att_list_del(NCindex *list, NC_ATT_INFO_T *att);
405 extern int nc4_grp_list_add(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *parent, char *name,
406                      NC_GRP_INFO_T **grp);
407 extern int nc4_build_root_grp(NC_FILE_INFO_T *h5);
408 extern int nc4_rec_grp_del(NC_GRP_INFO_T *grp);
409 extern int nc4_enum_member_add(NC_TYPE_INFO_T *type, size_t size, const char *name,
410                         const void *value);
411 extern int nc4_att_free(NC_ATT_INFO_T *att);
412 
413 /* Check and normalize names. */
414 extern int NC_check_name(const char *name);
415 extern int nc4_check_name(const char *name, char *norm_name);
416 extern int nc4_normalize_name(const char *name, char *norm_name);
417 extern int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name);
418 
419 /* Get the fill value for a var. */
420 extern int nc4_get_fill_value(NC_FILE_INFO_T *h5, NC_VAR_INFO_T *var, void **fillp);
421 
422 /* Find default fill value. */
423 extern int nc4_get_default_fill_value(nc_type typecode, void *fill_value);
424 
425 /* Get an att given pointers to file, group, and perhaps ver info. */
426 extern int nc4_get_att_ptrs(NC_FILE_INFO_T *h5, NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var,
427                      const char *name, nc_type *xtype, nc_type mem_type,
428                      size_t *lenp, int *attnum, void *data);
429 
430 /* Close the file. */
431 extern int nc4_close_netcdf4_file(NC_FILE_INFO_T *h5, int abort, NC_memio *memio);
432 
433 /* Compute default chunksizes */
434 extern int nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
435 extern int nc4_check_chunksizes(NC_GRP_INFO_T* grp, NC_VAR_INFO_T* var, const size_t* chunksizes);
436 
437 /* HDF5 initialization/finalization */
438 extern int nc4_hdf5_initialized;
439 extern void nc4_hdf5_initialize(void);
440 extern void nc4_hdf5_finalize(void);
441 
442 /* This is only included if --enable-logging is used for configure; it
443    prints info about the metadata to stderr. */
444 #ifdef LOGGING
445 extern int log_metadata_nc(NC_FILE_INFO_T *h5);
446 #endif
447 
448 /** @internal Names of atomic types. */
449 extern const char* nc4_atomic_name[NUM_ATOMIC_TYPES];
450 
451 /* Binary searcher for reserved attributes */
452 extern const NC_reservedatt* NC_findreserved(const char* name);
453 
454 /* Generic reserved Attributes */
455 #define NC_ATT_REFERENCE_LIST "REFERENCE_LIST"
456 #define NC_ATT_CLASS "CLASS"
457 #define NC_ATT_DIMENSION_LIST "DIMENSION_LIST"
458 #define NC_ATT_NAME "NAME"
459 #define NC_ATT_COORDINATES "_Netcdf4Coordinates" /*see hdf5internal.h:COORDINATES*/
460 #define NC_ATT_FORMAT "_Format"
461 #define NC_ATT_DIMID_NAME "_Netcdf4Dimid"
462 #define NC_ATT_NC3_STRICT_NAME "_nc3_strict"
463 #define NC_XARRAY_DIMS "_ARRAY_DIMENSIONS"
464 #define NC_NCZARR_ATTR "_NCZARR_ATTR"
465 
466 #endif /* _NC4INTERNAL_ */
467