mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-04-12 18:10:24 +08:00
This completes (for now) the refactoring of libsrc4.
The file docs/indexing.dox tries to provide design information for the refactoring. The primary change is to replace all walking of linked lists with the use of the NCindex data structure. Ncindex is a combination of a hash table (for name-based lookup) and a vector (for walking the elements in the index). Additionally, global vectors are added to NC_HDF5_FILE_INFO_T to support direct mapping of an e.g. dimid to the NC_DIM_INFO_T object. These global vectors exist for dimensions, types, and groups because they have globally unique id numbers. WARNING: 1. since libsrc4 and libsrchdf4 share code, there are also changes in libsrchdf4. 2. Any outstanding pull requests that change libsrc4 or libhdf4 are likely to cause conflicts with this code. 3. The original reason for doing this was for performance improvements, but as noted elsewhere, this may not be significant because the meta-data read performance apparently is being dominated by the hdf5 library because we do bulk meta-data reading rather than lazy reading.
This commit is contained in:
parent
74d9767ec0
commit
25f062528b
@ -1281,9 +1281,18 @@ CHECK_TYPE_SIZE("_Bool" SIZEOF__BOOL)
|
||||
|
||||
CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
|
||||
|
||||
|
||||
CHECK_TYPE_SIZE("ssize_t" HAVE_SSIZE_T)
|
||||
|
||||
CHECK_TYPE_SIZE("ssize_t" SIZEOF_SSIZE_T)
|
||||
IF(SIZEOF_SSIZE_T)
|
||||
SET(HAVE_SSIZE_T TRUE)
|
||||
ENDIF(SIZEOF_SSIZE_T)
|
||||
CHECK_TYPE_SIZE("ptrdiff_t" SIZEOF_PTRDIFF_T)
|
||||
IF(SIZEOF_PTRDIFF_T)
|
||||
SET(HAVE_PTRDIFF_T TRUE)
|
||||
ENDIF(SIZEOF_PTRDIFF_T)
|
||||
CHECK_TYPE_SIZE("uintptr_t" SIZEOF_UINTPTR_T)
|
||||
IF(SIZEOF_UINTPTR_T)
|
||||
SET(HAVE_UINTPTR_T TRUE)
|
||||
ENDIF(SIZEOF_UINTPTR_T)
|
||||
|
||||
# __int64 is used on Windows for large file support.
|
||||
CHECK_TYPE_SIZE("__int64" SIZEOF___INT_64)
|
||||
@ -1755,6 +1764,18 @@ STRING(REPLACE ";" " " LINKFLAGS "${LINKFLAGS}")
|
||||
LIST(REMOVE_DUPLICATES NC_LIBS)
|
||||
LIST(REMOVE_DUPLICATES LINKFLAGS)
|
||||
|
||||
IF(ENABLE_FILTER_TESTING)
|
||||
IF(ENABLE_EXAMPLES)
|
||||
MESSAGE(STATUS "copying filter plugin building files")
|
||||
FILE(COPY ${netCDF_SOURCE_DIR}/nc_test4/findplugin.in
|
||||
DESTINATION ${netCDF_BINARY_DIR}/examples/C/)
|
||||
FILE(GLOB PLUGINFILES ${netCDF_SOURCE_DIR}/nc_test4/hdf5plugins/*.c
|
||||
${netCDF_SOURCE_DIR}/nc_test4/hdf5plugins/*.h)
|
||||
FILE(COPY ${PLUGINFILES}
|
||||
DESTINATION ${netCDF_BINARY_DIR}/examples/C/hdf5plugins/)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
configure_file(
|
||||
${netCDF_SOURCE_DIR}/netcdf.pc.in
|
||||
${netCDF_BINARY_DIR}/netcdf.pc @ONLY)
|
||||
@ -1879,6 +1900,11 @@ configure_file(${CMAKE_SOURCE_DIR}/test_common.in ${CMAKE_BINARY_DIR}/test_commo
|
||||
SET(ISCMAKE "1")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/nc_test4/findplugin.in ${CMAKE_BINARY_DIR}/nc_test4/findplugin.sh @ONLY NEWLINE_STYLE LF)
|
||||
|
||||
IF(ENABLE_FILTER_TESTING)
|
||||
IF(ENABLE_EXAMPLES)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/nc_test4/findplugin.in ${CMAKE_BINARY_DIR}/examples/C/findplugin.sh @ONLY NEWLINE_STYLE LF)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
####
|
||||
# Export files
|
||||
|
2
Make0
2
Make0
@ -1,4 +1,4 @@
|
||||
T=t_dap3a
|
||||
T=tst_fileinfo
|
||||
|
||||
NCLIB=./liblib/.libs/libnetcdf.a
|
||||
D4LIB=./libdap4/.libs/libdap4.a
|
||||
|
13
cf
13
cf
@ -3,6 +3,7 @@
|
||||
DB=1
|
||||
#X=-x
|
||||
FAST=1
|
||||
#PROF=1
|
||||
|
||||
HDF5=1
|
||||
DAP=1
|
||||
@ -68,7 +69,7 @@ LD_LIBRARY_PATH="${stddir}/lib:$LD_LIBRARY_PATH"
|
||||
fi
|
||||
|
||||
if test "x$HDF4" = "x1" ; then
|
||||
LDFLAGS="$LDFLAGS -ljpeg"
|
||||
LDFLAGS="$LDFLAGS -lmfhdf -ldf -ljpeg"
|
||||
fi
|
||||
|
||||
if test "x$SZIP" = "x1" ; then
|
||||
@ -92,7 +93,6 @@ fi
|
||||
CXXFLAGS="$CPPFLAGS $CXXFLAGS"
|
||||
|
||||
FLAGS="--prefix ${PREFIX}"
|
||||
#FLAGS="$FLAGS --disable-f77 --disable-f90"
|
||||
#FLAGS="$FLAGS --disable-cxx"
|
||||
#FLAGS="$FLAGS --disable-examples"
|
||||
#FLAGS="$FLAGS --disable-utilities"
|
||||
@ -105,7 +105,7 @@ FLAGS="$FLAGS --enable-extreme-numbers"
|
||||
#FLAGS="$FLAGS --disable-testsets"
|
||||
#FLAGS="$FLAGS --disable-dap-remote-tests"
|
||||
#FLAGS="$FLAGS --enable-dap-auth-tests" -- requires a new remotetest server
|
||||
#FLAGS="$FLAGS --enable-doxygen --enable-internal-docs"
|
||||
FLAGS="$FLAGS --enable-doxygen --enable-internal-docs"
|
||||
FLAGS="$FLAGS --enable-logging"
|
||||
#FLAGS="$FLAGS --disable-diskless"
|
||||
#FLAGS="$FLAGS --enable-mmap"
|
||||
@ -117,7 +117,7 @@ FLAGS="$FLAGS --enable-logging"
|
||||
#FLAGS="$FLAGS --disable-properties-attribute"
|
||||
#FLAGS="$FLAGS --disable-silent-rules"
|
||||
#FLAGS="$FLAGS --with-testservers=remotestserver.localhost:8083"
|
||||
FLAGS="$FLAGS --enable-filter-testing"
|
||||
FLAGS="$FLAGS --disable-filter-testing"
|
||||
|
||||
if test "x$PAR4" != x1 ; then
|
||||
FLAGS="$FLAGS --disable-parallel4"
|
||||
@ -169,6 +169,11 @@ if test "x$MPIO" = x1 ; then
|
||||
FLAGS="$FLAGS --enable-parallel-tests"
|
||||
fi
|
||||
|
||||
if test "x${PROF}" = x1 ; then
|
||||
CFLAGS="${CFLAGS} -pg"
|
||||
LDFLAGS="${LDFLAGS} -pg"
|
||||
fi
|
||||
|
||||
#FLAGS="${FLAGS} --enable-stdio"
|
||||
|
||||
export PATH
|
||||
|
13
cf.cmake
13
cf.cmake
@ -1,16 +1,19 @@
|
||||
# Visual Studio
|
||||
|
||||
# Is netcdf-4 and/or DAP enabled?
|
||||
#NC4=1
|
||||
NC4=1
|
||||
DAP=1
|
||||
CDF5=1
|
||||
#HDF4=1
|
||||
|
||||
case "$1" in
|
||||
for arg in "$@" ; do
|
||||
case "$arg" in
|
||||
vs|VS) VS=1 ;;
|
||||
linux|nix|l|x) unset VS ;;
|
||||
nobuild|nb) NOBUILD=1 ;;
|
||||
*) echo "Must specify env: vs|linux"; exit 1; ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test "x$VS" = x1 ; then
|
||||
if test "x$2" = xsetup ; then
|
||||
@ -44,7 +47,7 @@ FLAGS="$FLAGS -DENABLE_EXAMPLES=false"
|
||||
FLAGS="$FLAGS -DENABLE_DYNAMIC_LOADING=false"
|
||||
FLAGS="$FLAGS -DENABLE_WINSOCK2=false"
|
||||
#FLAGS="$FLAGS -DENABLE_LARGE_FILE_TESTS=true"
|
||||
FLAGS="$FLAGS -DENABLE_FILTER_TESTING=true"
|
||||
#FLAGS="$FLAGS -DENABLE_FILTER_TESTING=true"
|
||||
|
||||
rm -fr build
|
||||
mkdir build
|
||||
@ -59,15 +62,19 @@ NCLIB="${NCLIB}/liblib"
|
||||
export PATH="${NCLIB}:${PATH}"
|
||||
#G=
|
||||
cmake "$G" -DCMAKE_BUILD_TYPE=${CFG} $FLAGS ..
|
||||
if test "x$NOBUILD" = x ; then
|
||||
cmake --build . --config ${CFG}
|
||||
cmake --build . --config ${CFG} --target RUN_TESTS
|
||||
fi
|
||||
else
|
||||
# GCC
|
||||
NCLIB="${NCLIB}/build/liblib"
|
||||
#G="-GUnix Makefiles"
|
||||
#T="--trace-expand"
|
||||
cmake "${G}" $FLAGS ..
|
||||
if test "x$NOBUILD" == x ; then
|
||||
make all
|
||||
make test
|
||||
fi
|
||||
fi
|
||||
exit
|
||||
|
@ -559,6 +559,9 @@ are set when opening a binary file on Windows. */
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#cmakedefine size_t unsigned int
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine ssize_t int
|
||||
|
||||
/* Define to `unsigned long if <sys/types.h> does not define. */
|
||||
#cmakedefine uintptr_t unsigned long
|
||||
|
||||
|
30
configure.ac
30
configure.ac
@ -794,6 +794,8 @@ AC_STRUCT_ST_BLKSIZE
|
||||
UD_CHECK_IEEE
|
||||
AC_CHECK_TYPES([size_t, ssize_t, schar, uchar, longlong, ushort, uint, int64, uint64])
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_UINTPTR_T
|
||||
AC_C_CHAR_UNSIGNED
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
###
|
||||
@ -978,7 +980,6 @@ if test "x$enable_netcdf_4" = xyes; then
|
||||
AC_CHECK_LIB([mfhdf], [SDcreate], [], [AC_MSG_ERROR([Can't find or link to the hdf4 mfhdf library. See config.log for errors.])])
|
||||
|
||||
AC_CHECK_LIB([jpeg], [jpeg_set_quality], [], [AC_MSG_ERROR([Can't find or link to the jpeg library (required by hdf4). See config.log for errors.])])
|
||||
|
||||
AC_DEFINE([USE_HDF4], [1], [if true, use HDF4 too])
|
||||
fi
|
||||
fi
|
||||
@ -1304,12 +1305,12 @@ AC_MSG_RESULT($enable_filter_testing)
|
||||
|
||||
if test "x$enable_netcdf_4" = xno ; then
|
||||
AC_MSG_WARN([netCDF-4 disabled => --disable-filter-testing])
|
||||
enable_filter_testing = no
|
||||
enable_filter_testing=no
|
||||
fi
|
||||
|
||||
if test "x$enable_shared" = xno ; then
|
||||
AC_MSG_WARN([Shared libraries are disabled => --disable-filter-testing])
|
||||
enable_filter_testing = no
|
||||
enable_filter_testing=no
|
||||
fi
|
||||
AM_CONDITIONAL(ENABLE_FILTER_TESTING, [test x$enable_filter_testing = xyes])
|
||||
|
||||
@ -1416,6 +1417,28 @@ AC_CONFIG_FILES(test_common.sh:test_common.in)
|
||||
AC_SUBST([ISCMAKE], [])
|
||||
AC_SUBST([MSVC], [])
|
||||
AC_CONFIG_FILES(nc_test4/findplugin.sh:nc_test4/findplugin.in)
|
||||
AC_CONFIG_FILES(examples/C/findplugin.sh:nc_test4/findplugin.in)
|
||||
|
||||
if test "x$enable_filter_testing" = xyes ; then
|
||||
if test "x$nc_build_examples" = xyes ; then
|
||||
AC_MSG_NOTICE([copying filter plugin building files])
|
||||
# Must be a simpler way; all my attempts to use some kind of wildcard failed,
|
||||
# so falling back on enumeration
|
||||
# WARNING: This enumeration must be kept consistent with the
|
||||
# HDF5PLUGINSRC list in nc_test4/hdf5plugins/Makefile.am
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/bzlib.h:nc_test4/hdf5plugins/bzlib.h])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/bzlib_private.h:nc_test4/hdf5plugins/bzlib_private.h])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/blocksort.c:nc_test4/hdf5plugins/blocksort.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/huffman.c:nc_test4/hdf5plugins/huffman.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/crctable.c:nc_test4/hdf5plugins/crctable.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/randtable.c:nc_test4/hdf5plugins/randtable.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/compress.c:nc_test4/hdf5plugins/compress.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/decompress.c:nc_test4/hdf5plugins/decompress.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/bzlib.c:nc_test4/hdf5plugins/bzlib.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/H5Zbzip2.c:nc_test4/hdf5plugins/H5Zbzip2.c])
|
||||
AC_CONFIG_LINKS([examples/C/hdf5plugins/h5bzip2.h:nc_test4/hdf5plugins/h5bzip2.h])
|
||||
fi
|
||||
fi
|
||||
|
||||
#####
|
||||
# End netcdf_meta.h definitions.
|
||||
@ -1462,6 +1485,7 @@ AC_CONFIG_FILES([Makefile
|
||||
dap4_test/Makefile
|
||||
],
|
||||
[test -f nc-config && chmod 755 nc-config])
|
||||
|
||||
AC_OUTPUT()
|
||||
|
||||
#mv -f ${abs_top_srcdir}/test_common.sh ${abs_top_builddir}/test_common.sh
|
||||
|
@ -750,6 +750,7 @@ INPUT = \
|
||||
@abs_top_srcdir@/docs/install-fortran.md \
|
||||
@abs_top_srcdir@/docs/types.dox \
|
||||
@abs_top_srcdir@/docs/internal.dox \
|
||||
@abs_top_srcdir@/docs/indexing.dox \
|
||||
@abs_top_srcdir@/docs/windows-binaries.md \
|
||||
@abs_top_srcdir@/docs/guide.dox \
|
||||
@abs_top_srcdir@/docs/OPeNDAP.dox \
|
||||
|
11
docs/auth.md
11
docs/auth.md
@ -4,10 +4,6 @@ netCDF Authorization Support
|
||||
|
||||
# netCDF Authorization Support {#Header}
|
||||
|
||||
__Author__: Dennis Heimbigner<br>
|
||||
__Initial Version__: 11/21/2014<br>
|
||||
__Last Revised__: 08/24/2017
|
||||
|
||||
[TOC]
|
||||
|
||||
## Introduction {#Introduction}
|
||||
@ -515,3 +511,10 @@ what you changed to the author so this document can be updated.
|
||||
yes | keytool -trustcacerts -storepass "$PWD" -v -keystore ./$TRUSTSTORE -alias $alias -importcert -file "${c}"
|
||||
done
|
||||
exit
|
||||
|
||||
## Provenance
|
||||
|
||||
__Author__: Dennis Heimbigner<br>
|
||||
__Initial Version__: 11/21/2014<br>
|
||||
__Last Revised__: 08/24/2017
|
||||
|
||||
|
@ -435,6 +435,14 @@ static const unsigned char b[4] = {0x0,0x0,0x0,0x1}; /* value 1 in big-endian*/
|
||||
int endianness = (1 == *(unsigned int*)b); /* 1=>big 0=>little endian
|
||||
````
|
||||
|
||||
Provenance
|
||||
================
|
||||
|
||||
__Author__: Dennis Heimbigner<br>
|
||||
__Email__: dmh at ucar dot edu
|
||||
__Initial Version__: 1/10/2018<br>
|
||||
__Last Revised__: 2/5/2018
|
||||
|
||||
References {#References}
|
||||
==========
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
The original internal representations of metadata in memory
|
||||
relied on linear searching of lists to locate various objects
|
||||
by name or by numeric id (e.g. varid or grpid).
|
||||
by name or by numeric id: e.g. _varid_ or _grpid_.
|
||||
|
||||
In recent years, the flaws in that approach have become obvious
|
||||
as users create files with extremely large numbers of objects:
|
||||
@ -16,37 +16,35 @@ group, variables, attributes, and dimensions. One case
|
||||
has 14 megabytes of metadata. Creating and (especially) later
|
||||
opening such files was exceedingly slow.
|
||||
|
||||
This problem was partially alleviated in both netcdfd-3 (libsrc)
|
||||
This problem was partially alleviated in both netcdf-3 (libsrc)
|
||||
and netcdf-4 (libsrc4) by adding name hashing tables.
|
||||
However, and especially for netcdf-4, linear search still prevailed.
|
||||
|
||||
A pervasive change has been made to try to remove (almost) all
|
||||
occurrences of linear search and replace it with either hashing
|
||||
(for name-based lookup) or vectors (for numeric id-based
|
||||
lookup). The cases left as linear search include these.
|
||||
|
||||
1. Enum constants for an enumeration
|
||||
2. Dimensions associated with a variable
|
||||
3. Fields of Compound types
|
||||
A pervasive change has been made to try to change searches by name
|
||||
or by id from O(n) to O(1).
|
||||
This uses hashing for name-based search
|
||||
and vectors for numeric id-based search.
|
||||
All other cases were left as O(n) searches.
|
||||
|
||||
This document describes the architecture and details of the netCDF
|
||||
internal object lookup mechanisms now in place.
|
||||
|
||||
\section S1 Indexed Searches
|
||||
\section Sindexed_searches Indexed Searches
|
||||
|
||||
There are, as a rule, two searches that are used to locate
|
||||
metadata object: (1) search by name and (2) search by
|
||||
externally visible id (e.g. dimid or varid).
|
||||
|
||||
Currently, and after all the metadata is read or created,
|
||||
hashing is used for locating objects by name. In all other
|
||||
cases -- apparently -- lookup is by linear search of some
|
||||
kind of linked list or a vector.
|
||||
It is currently the case that after all the metadata is read or
|
||||
created, hashing is used for locating objects by name. In all
|
||||
other cases -- apparently -- lookup is by linear search of a
|
||||
of linked list.
|
||||
|
||||
It is relevant that, once created, no metadata object -- except
|
||||
attributes -- can be deleted. They can be renamed, but that
|
||||
does not change the associated id. Deletion only occurs when an
|
||||
error occurs in creating an object or on invoking nc_close.
|
||||
does not change the associated structure or id. Deletion only
|
||||
occurs when an error occurs in creating an object or on invoking
|
||||
"nc_close()".
|
||||
|
||||
The numeric identifiers for dimensions, types, and groups are
|
||||
all globally unique across a file. But note that variable id's
|
||||
@ -63,12 +61,12 @@ with the same name (as with coordinate variables).
|
||||
Finally, attribute names are unique only with respect to each other
|
||||
and with respect to the containing object (a variable or a group).
|
||||
|
||||
\section S2 Basic Data Structures
|
||||
\section Sbasic_data_structures Basic Data Structures
|
||||
|
||||
The basic data structures used by the new lookup mechanisms
|
||||
are described in the following sections.
|
||||
|
||||
\subsection SS1_1 NClist
|
||||
\subsection Snclist NClist
|
||||
|
||||
With rare exceptions, vectors of objects are maintained as
|
||||
instances of NClist, which provides a dynamically extendible
|
||||
@ -77,7 +75,7 @@ It is possible to append new objects or insert at a specific
|
||||
vector offset, or overwrite an existing pointer at a specific
|
||||
offset.
|
||||
|
||||
The definition is as follows.
|
||||
The NClist structure definition is as follows.
|
||||
|
||||
\code
|
||||
typedef struct NClist {
|
||||
@ -87,16 +85,17 @@ typedef struct NClist {
|
||||
} NClist;
|
||||
\endcode
|
||||
|
||||
\subsection Snc_hashmap NC_hashmap
|
||||
|
||||
\subsection SS1_2 NC_hashmap
|
||||
|
||||
The NC_hashmap type is a hash table mapping a name to a pointer.
|
||||
As a rule, the pointer points to a metadata object. The current
|
||||
implementation supports table expansion when the # of entries in
|
||||
the table starts to get too large. Basically a simple linear
|
||||
rehash is used for collisions and no separate hash-chain is
|
||||
used. This means that when expanded, it must be completely
|
||||
rebuilt. The performance hit for this has yet to be determined.
|
||||
The NC_hashmap type is a hash table mapping a string
|
||||
(the key) to a data item. As a rule, the data item is a pointer to a
|
||||
metadata object. The current implementation supports table
|
||||
expansion when the # of entries in the table starts to get too
|
||||
large. A simple linear rehash is used for collisions
|
||||
and no separate hash-chain is used. This means that when
|
||||
expanded, it must be completely rebuilt. The performance hit for
|
||||
this has yet to be determined. The alternative is to move to some
|
||||
form of extendible hashing as used in databases.
|
||||
|
||||
The hashtable definition is as follows.
|
||||
|
||||
@ -115,104 +114,269 @@ a vector of entries of this form.
|
||||
\code
|
||||
typedef struct NC_hentry {
|
||||
int flags;
|
||||
void* data;
|
||||
size_t hashkey; /* Hash id */
|
||||
char* key; /* actual key; do not free */
|
||||
uintptr_t data;
|
||||
unsigned int hashkey;
|
||||
size_t keysize;
|
||||
char* key;
|
||||
} NC_hentry;
|
||||
\endcode
|
||||
|
||||
The flags indicate the state of the entry and can be one of three states:
|
||||
The _flags_ field indicates the state of the entry and can be
|
||||
in one of three disjoint states:
|
||||
|
||||
1. ACTIVE - there is an object referenced in this entry
|
||||
2. DELETED - an entry was deleted, but must be marked so
|
||||
that linear rehash will work.
|
||||
3. EMPTY - unused
|
||||
|
||||
There is an important WARNING with respect to the "key" field.
|
||||
The key is not a copy of the object's name, but in fact is a duplicate
|
||||
pointer to that same string. This means (1) that it should never be
|
||||
free()'d and (2) if the name of the metadata object is changed, then
|
||||
it must be removed and re-inserted into the table to that the key
|
||||
points to the current name.
|
||||
The "data" field is of type "uintptr_t". Note that we assume
|
||||
that sizeof(unintptr_t) == sizeof(void*). This is very
|
||||
important. It is supposed to be the case that a value of type
|
||||
uintptr_t is an integer of sufficient size to hold a void* pointer.
|
||||
|
||||
The "data" field is of type void*. Often it is a pointer to an instance
|
||||
of a variable, or dimension, or other object. When used as part of an
|
||||
NC_listmap (see below), then the key is an integer index into the
|
||||
associated vector. In order to do this correctly, we need to rely
|
||||
on the type "uintptr_t". It is supposed to be the case
|
||||
that a value of type uintptr_t is an integer of sufficient size to
|
||||
hold a void* pointer. Usually, but not always, this would be the same
|
||||
size as an "unsigned long" value. Using this allows the hashtable
|
||||
to store either pointers or integer indices.
|
||||
This means that the data field can hold an unsigned integer or a
|
||||
void* pointer. As a pointer, it often points to an instance of a
|
||||
variable, or dimension, or other object.
|
||||
|
||||
One further WARNING: any object that will be inserted into an NC_hashmap
|
||||
must have its name as the first field so it can be cast
|
||||
to char** for use with the hashtable.
|
||||
The hashkey field is a CRC32 hash of the key. Note that comparing
|
||||
hashkeys is not sufficient to ensure that the corresponding keys are
|
||||
the same because hash collisions are possible. Even moving to, say,
|
||||
64 bit keys, is probably not sufficient to avoid hash collisions.
|
||||
A 128 bit key (e.g. MD5) might be sufficient but mathematical
|
||||
investigation would be required.
|
||||
|
||||
\subsection SS1_3 NC_listmap
|
||||
Since comparing only hash keys is not sufficient, it is necessary to store
|
||||
a copy of the actual key. The key and keysize fields are used for this.
|
||||
|
||||
A listmap is a combination of an NClist and an NC_hashtable.
|
||||
It is used to provide name-based lookup with respect to a
|
||||
specific list of metadata objects. For example, the subgroups
|
||||
of a group are stored using a listmap, where the list is a
|
||||
vector of pointers to the subgroup objects and the hashmap
|
||||
maps the subgroup name (unique to that group, remember) to
|
||||
the corresponding index into the vector. In theory, only
|
||||
the hashmap is needed because it could be walked to get all
|
||||
of the metadata objects. However, the creation order is sometimes
|
||||
important, so that is maintained by the vector.
|
||||
This is especially important for attribute storage.
|
||||
\subsection Sncindex NCindex
|
||||
|
||||
Note that currently, NC_listmap is only used in libsrc4,
|
||||
but if performance issues warrant, it will also be used in
|
||||
An "index" \(aka instance of type "NCindex"\) is a combination
|
||||
of one NClist instance plus one NC_hashmap instance.
|
||||
The hashmap maps a name to the position of the correspondingly
|
||||
named object in the NClist part of the NCindex.
|
||||
|
||||
An index is used to provide several kinds of lookup with respect
|
||||
to a specific list of metadata objects. For example, the
|
||||
subgroups of a group are stored using a vector of pointers to
|
||||
the subgroup objects. This also provides information about
|
||||
creation order, which is sometimes important. However, we often
|
||||
need fast access to that vector by name so an NCindex object
|
||||
provides these capabilities. The NCindex object contains:
|
||||
|
||||
1. A vector into which the object pointers can be stored
|
||||
and iterated over.
|
||||
2. A map from name to the corresponding object index in the vector.
|
||||
|
||||
Note that currently, NCindex is only used in libsrc4 and libhdf4.
|
||||
But if performance issues warrant, it will also be used in
|
||||
libsrc.
|
||||
|
||||
\section S3 Global Object Access
|
||||
\section Sglobal_object_access Global Object Access
|
||||
|
||||
As mentioned, dimension, group, and type external id's (dimid,
|
||||
grpid, typeid) are unique across the whole file. It is therefore
|
||||
convenient to store in memory a per-file vector for each object
|
||||
type such that the external id of the object is the same as the
|
||||
position of that object in the corresponding per-file
|
||||
vector. This maked lookup by external id efficient.
|
||||
vector. This makes lookup by external id very efficient.
|
||||
Note that this is was already the case for netcdf-3 (libsrc) so
|
||||
this is a change for libsrc4 only.
|
||||
|
||||
The global set of dimensions, types, and groups is maintained by
|
||||
three instances of NClist in the NC_HDF5_FILE_INFO structure:
|
||||
alldims, alltypes, and allgroups.
|
||||
namely _alldims_, _alltypes_, and _allgroups_.
|
||||
The position of the object within the corresponding list determines
|
||||
the object's external id. Thus, a position of a dimension object within the
|
||||
"alldims" field of the file structure determines its dimid. Similarly
|
||||
for types and groups.
|
||||
|
||||
\section S4 Per-Group Object Access
|
||||
\section Sper_group_object_access Per-Group Object Access
|
||||
|
||||
Each group object (NC_GRP_INFO) contains four
|
||||
instances of NC_listmap. One is for dimensions, one is for
|
||||
types, one is for subgroups, and one is for variables. A
|
||||
listmap is used for two reasons. First, allows name-based lookup
|
||||
Each group object (NC_GRP_INFO_T) contains five instances of
|
||||
NCindex. One is for dimensions, one is for types, one is for
|
||||
subgroups, one is for variables, and one is for attributes. A
|
||||
index is used for two reasons. First, it allows name-based lookup
|
||||
for these items. Second, the declaration order is maintained by
|
||||
the list within the listmap's vector. Note that the position of
|
||||
an object in a group listmap vector has no necessary
|
||||
the list within the index's vector. Note that the position of
|
||||
an object in a group index vector has no necessary
|
||||
relationship to the position of that object within the global
|
||||
vectors. Note also that there is no global vector for variables
|
||||
because variable external ids are unique only within the
|
||||
group. In this special case, the external id for the variable is
|
||||
the same as its offset in the listmap's vector for the group.
|
||||
vectors.
|
||||
|
||||
Note however that the index vector for variables does define
|
||||
the variable id, which is unique only within a group.
|
||||
In this special case, the external id for the variable is
|
||||
the same as its offset in the index's vector for the group.
|
||||
|
||||
A note about typeids. Since user defined types have an external
|
||||
id starting at NC_FIRSTUSERTYPEID, we leave the global type
|
||||
vector entries 0..NC_FIRSTUSERTYPEID-1 empty.
|
||||
|
||||
\section S5 Exceptions
|
||||
\section Smetadata_object_header Metadata Object Header
|
||||
|
||||
NC_Listmap is currently not used for enum constants and compound fields.
|
||||
Additionally, it is not used for listing the dimensions associated
|
||||
with a variable.
|
||||
Each metadata object (e.g. NC_DIM_INFO_T, NC_VAR_INFO_T)
|
||||
now has what is called a "hdr" object as its first field.
|
||||
This provides a form of pseudo-inheritance for these objects
|
||||
because they can all be cast to "NC_OBJ" to get common information.
|
||||
The structure of the header is as follows.
|
||||
|
||||
References between meta-data objects (e.g. group parent or
|
||||
containing group) are stored directly and not using any kind
|
||||
of vector or hashtable.
|
||||
\code
|
||||
typedef struct NC_OBJ {
|
||||
NC_SORT sort;
|
||||
char* name; /* assumed to be null terminated */
|
||||
size_t id;
|
||||
unsigned int hashkey;
|
||||
} NC_OBJ;
|
||||
\endcode
|
||||
|
||||
The sort is one of the values _NCVAR_, _NCDIM_, _NCATT_, _NCTYP_, or _NCGRP_.
|
||||
The name is assumed to be nul terminated. The id is the assigned id
|
||||
for the object. The hashkey is the same hash value as used in nchashtable.c.
|
||||
|
||||
\section Scliches Programming cliches
|
||||
|
||||
\subsection Slookupname Lookup an Object by Name
|
||||
|
||||
In the original code, the following _cliche_ (code snippet)
|
||||
was common for looking up an object by name.
|
||||
\code
|
||||
NC_GRP_INFO_T* grp = ...;
|
||||
...
|
||||
NC_GRP_INFO_T* g;
|
||||
...
|
||||
for (g = grp->children; g; g = g->l.next) {
|
||||
if(strcmp(name,g->name)==0) {
|
||||
... code to process matching grp by name
|
||||
}
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
In this case, this loop is iterating across all the subgroups (children)
|
||||
of the grp. It does so by walking the linked list of child groups.
|
||||
It does a name comparison in order to find the group with the desired name.
|
||||
|
||||
In the new code, this iteration cliche is replaced by something
|
||||
that will look like this.
|
||||
\code
|
||||
NC_GRP_INFO_T* grp = ...;
|
||||
NC_GRP_INFO_T* g;
|
||||
...
|
||||
g = ncindexlookup(grp->children,name);
|
||||
if(g != NULL)
|
||||
... code to process matching grp by name
|
||||
}
|
||||
\endcode
|
||||
In this case, the iteration uses a hashtable.
|
||||
|
||||
\subsection Slookupid Lookup an Object by id
|
||||
|
||||
In the original code, the following _cliche_ (code snippet)
|
||||
was common for looking up an object by its id (dimid, varid, etc).
|
||||
\code
|
||||
NC_GRP_INFO_T* grp = ...;
|
||||
...
|
||||
NC_DIM_INFO_T* d;
|
||||
...
|
||||
for (d = grp->dim; d; d = d->l.next) {
|
||||
if(varid == d->dimid)
|
||||
... code to process matching dim by index
|
||||
}
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
In this case, this loop is iterating across all the dimension objects
|
||||
of the grp. It does so by walking the linked list of dimensions.
|
||||
It does an id comparison in order to find the group with the desired
|
||||
dimension.
|
||||
|
||||
In the new code, this iteration cliche is replaced by something
|
||||
that will look like this.
|
||||
\code
|
||||
NC_HDF5_FILE_INFO_T* h5 = ...;
|
||||
NC_DIM_INFO_T* d;;
|
||||
...
|
||||
d = nclistget(h5->alldims,id);
|
||||
if(d != NULL)
|
||||
... code to process matching dim by id
|
||||
}
|
||||
\endcode
|
||||
This shows how the alldims vector is used to map from a
|
||||
dimid directly to the matching dimension object.
|
||||
In this example, h5 is the NC_HDF5_FILE_INFO_T file object.
|
||||
This approach works for dimension ids, group ids, and type ids
|
||||
because they are globally unique.
|
||||
|
||||
For variables and attributes, we have to use the containing group's
|
||||
NCindex, such as grp->vars. In this case, the varid, is mapped using
|
||||
code like this.
|
||||
\code
|
||||
NC_GRP_INFO_T* grp = ...;
|
||||
NC_VAR_INFO_T* v;
|
||||
...
|
||||
v = ncindexith(grp->vars,id);
|
||||
if(v != NULL)
|
||||
... code to process matching variable by id
|
||||
}
|
||||
\endcode
|
||||
|
||||
\subsection Siterate Iterating over sets of objects
|
||||
|
||||
In the original code, the following _cliche_ (code snippet)
|
||||
was common.
|
||||
\code
|
||||
NC_GRP_INFO_T* grp;
|
||||
...
|
||||
NC_GRP_INFO_T* g;
|
||||
...
|
||||
for (g = grp->children; g; g = g->l.next)
|
||||
...
|
||||
\endcode
|
||||
In this case, this loop is iterating across all the subgroups (children)
|
||||
of the grp. It does so by walking the linked list of child groups.
|
||||
Similar loops are used to walk a list of dimensions, variables, types,
|
||||
or attributes.
|
||||
|
||||
In the new code, this iteration cliche is replaced by something
|
||||
that will look like this.
|
||||
\code
|
||||
NC_GRP_INFO_T* grp;
|
||||
...
|
||||
for(i=0;i<ncindexsize(grp->children);i++) {
|
||||
NC_GRP_INFO_T* g = nclistith(grp->children,i);
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
In this case, the iteration is by index into the underlying vector.
|
||||
|
||||
\section Snotes_and_warnings Notes and Warning
|
||||
|
||||
1. NCindex is currently not used for enum constants and compound fields.
|
||||
Additionally, it is not used for listing the dimensions associated
|
||||
with a variable.
|
||||
2. References between meta-data objects (e.g. group parent or
|
||||
containing group) are stored directly and not using any kind
|
||||
of vector or hashtable.
|
||||
3. Attribute deletion is still a costly operation because it causes
|
||||
the whole attribute index to be rebuilt.
|
||||
4. Renaming is still a costly operation because it causes
|
||||
the whole containing index to be rebuilt.
|
||||
5. As in the original code, object ids (dimid, etc) are assigned
|
||||
explicitly using counters within the NC_HDF5_FILE_INFO_T object.
|
||||
When stored into, for example, "alldims", the position of the
|
||||
object is forcibly made to match the value of the assigned id.
|
||||
6. The file nchashmap.c has a constant, SMALLTABLE, that controls
|
||||
the size of the default hash table. Setting this constant
|
||||
may be useful in debugging by reducing the default table size.
|
||||
7. The file ncindex.c has a constant, SMALLTABLE, that controls
|
||||
the size of the default hash table. Setting this constant
|
||||
may be useful in debugging by reducing the default table size.
|
||||
8. The file ncindex.c has a constant, NCNOHASH, that controls
|
||||
if the index uses that hash table versus just searching the
|
||||
index's vector. This is for experimental purposes.
|
||||
|
||||
\section Sprovenance Contact Information
|
||||
|
||||
__Author__: Dennis Heimbigner<br>
|
||||
__Initial Version__: 01/10/2018<br>
|
||||
__Last Revised__: 03/15/2018
|
||||
|
||||
*/
|
||||
|
@ -26,6 +26,7 @@ To date, at least the following dispatch tables are supported.
|
||||
- DAP2 to netcdf-3
|
||||
- DAP4 to netcdf-4
|
||||
- pnetcdf (parallel cdf5)
|
||||
- HDF4
|
||||
|
||||
Internal Dispatch Tables
|
||||
- \subpage adding_dispatch
|
||||
|
@ -12,7 +12,9 @@ SET_TESTS_PROPERTIES(C_tests_simple_xy_rd PROPERTIES DEPENDS C_tests_simple_xy_w
|
||||
SET_TESTS_PROPERTIES(C_tests_sfc_pres_temp_rd PROPERTIES DEPENDS C_tests_sfc_pres_temp_wr)
|
||||
SET_TESTS_PROPERTIES(C_tests_pres_temp_4D_rd PROPERTIES DEPENDS C_tests_pres_temp_4D_wr)
|
||||
|
||||
ADD_SUBDIRECTORY(hdf5plugins)
|
||||
IF(ENABLE_FILTER_TESTING)
|
||||
ADD_SUBDIRECTORY(hdf5plugins)
|
||||
ENDIF(ENABLE_FILTER_TESTING)
|
||||
|
||||
SET(CLEANFILES sfc_pres_temp.nc simple_xy.nc pres_temp_4D.nc simple_nc4.nc simple_xy_nc4.nc)
|
||||
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
|
||||
|
@ -31,6 +31,7 @@ SUBDIRS = hdf5plugins
|
||||
if ENABLE_FILTER_TESTING
|
||||
# filter_example.c should be same as nc_test4/test_filter.c
|
||||
check_PROGRAMS += filter_example
|
||||
TESTS += run_filter.sh
|
||||
endif
|
||||
|
||||
endif #USE_NETCDF4
|
||||
@ -53,10 +54,4 @@ CLEANFILES = *.nc
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt run_examples.sh run_examples4.sh
|
||||
|
||||
if ENABLE_FILTER_TESTING # => shared and netcdf-4
|
||||
BUILT_SOURCES = findplugin.sh
|
||||
findplugin.sh:
|
||||
cp ${top_builddir}/nc_test4/findplugin.sh ${builddir}
|
||||
endif
|
||||
|
||||
DISTCLEANFILES = findplugin.sh
|
||||
|
@ -7,22 +7,16 @@ PLUGINSRC = H5Zbzip2.c h5bzip2.h
|
||||
|
||||
TARGETS = ${PLUGINSRC} ${BZIP2SRC}
|
||||
|
||||
BUILT_SOURCES = ${TARGETS}
|
||||
|
||||
${TARGETS}:
|
||||
for x in ${TARGETS} ; do 'cp' -f ${top_srcdir}/nc_test4/hdf5plugins/$$x . ; done
|
||||
|
||||
CLEANFILES = ${TARGETS}
|
||||
HDF5PLUGINSRC=${PLUGINSRC} ${BZIP2SRC}
|
||||
|
||||
if ENABLE_FILTER_TESTING
|
||||
|
||||
DLLSRC=${PLUGINSRC} ${BZIP2SRC}
|
||||
|
||||
lib_LTLIBRARIES = libbzip2.la
|
||||
|
||||
libbzip2_la_SOURCES = ${DLLSRC}
|
||||
libbzip2_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined -rpath ${abs_builddir}
|
||||
libbzip2_la_SOURCES = ${HDF5PLUGINSRC}
|
||||
libbzip2_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined
|
||||
|
||||
endif #ENABLE_FILTER_TESTING
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt H5Zbzip2.c Makefile.am blocksort.c bzlib.c bzlib.h bzlib_private.h compress.c \
|
||||
crctable.c decompress.c h5bzip2.h huffman.c randtable.c bzip2.nc
|
||||
|
@ -16,24 +16,5 @@ echo "*** running simple_xy_nc4 examples..."
|
||||
${execdir}/simple_xy_nc4_wr
|
||||
${execdir}/simple_xy_nc4_rd
|
||||
|
||||
if test -f ${builddir}/findplugin.sh ; then
|
||||
echo "*** running test_filter example..."
|
||||
. ${builddir}/findplugin.sh
|
||||
|
||||
# Locate the plugin path and the library names; argument order is critical
|
||||
# Find bzip2 and capture
|
||||
findplugin bzip2
|
||||
BZIP2PATH="${HDF5_PLUGIN_PATH}/${HDF5_PLUGIN_LIB}"
|
||||
# Verify
|
||||
if ! test -f ${BZIP2PATH} ; then echo "Unable to locate ${BZIP2PATH}"; exit 1; fi
|
||||
export HDF5_PLUGIN_PATH
|
||||
|
||||
echo "*** running filter_example..."
|
||||
rm -f ./bzip2.nc
|
||||
${execdir}/filter_example
|
||||
#rm -f ./bzip2.nc
|
||||
|
||||
fi # Filter enabled
|
||||
|
||||
echo "*** Examples successful!"
|
||||
exit 0
|
||||
|
@ -5,25 +5,27 @@
|
||||
if test "x$srcdir" = x ; then srcdir=`pwd`; fi
|
||||
. ../../test_common.sh
|
||||
|
||||
echo "*** Running filter example for netCDF-4."
|
||||
set -e
|
||||
|
||||
echo "*** Running test_filter example..."
|
||||
echo "ISCYGWIN=${ISCYGWIN}"
|
||||
if test "x$ISCYGWIN" != x ; then
|
||||
PLUGIN=cygbzip2.dll
|
||||
else
|
||||
PLUGIN=libbzip2.so
|
||||
fi
|
||||
if test -f ${builddir}/findplugin.sh ; then
|
||||
echo "*** running test_filter example..."
|
||||
. ${builddir}/findplugin.sh
|
||||
|
||||
HDF5_PLUGIN_PATH=`pwd`
|
||||
HDF5_PLUGIN_PATH="${HDF5_PLUGIN_PATH}/plugins"
|
||||
if test -f "${HDF5_PLUGIN_PATH}/.libs/${PLUGIN}" ; then
|
||||
HDF5_PLUGIN_PATH="${HDF5_PLUGIN_PATH}/.libs"
|
||||
fi
|
||||
# Locate the plugin path and the library names; argument order is critical
|
||||
# Find bzip2 and capture
|
||||
findplugin bzip2
|
||||
BZIP2PATH="${HDF5_PLUGIN_PATH}/${HDF5_PLUGIN_LIB}"
|
||||
# Verify
|
||||
if ! test -f ${BZIP2PATH} ; then echo "Unable to locate ${BZIP2PATH}"; exit 1; fi
|
||||
export HDF5_PLUGIN_PATH
|
||||
|
||||
echo "*** running filter_example..."
|
||||
rm -f ./bzip2.nc
|
||||
${execdir}/test_filter
|
||||
${execdir}/filter_example
|
||||
#rm -f ./bzip2.nc
|
||||
|
||||
echo "*** Example successful!"
|
||||
fi # Filter enabled
|
||||
|
||||
echo "*** Filter example successful!"
|
||||
exit 0
|
||||
|
@ -19,9 +19,10 @@ endif
|
||||
noinst_HEADERS = nc_logging.h nc_tests.h fbits.h nc.h nclist.h \
|
||||
ncuri.h ncutf8.h ncdispatch.h ncdimscale.h netcdf_f.h err_macros.h \
|
||||
ncbytes.h nchashmap.h ceconstraints.h rnd.h nclog.h ncconfigure.h \
|
||||
nc4internal.h nctime.h nc3internal.h onstack.h nc_hashmap.h ncrc.h \
|
||||
nc4internal.h nctime.h nc3internal.h onstack.h ncrc.h \
|
||||
ncauth.h ncoffsets.h nctestserver.h nc4dispatch.h nc3dispatch.h \
|
||||
ncexternl.h ncwinpath.h ncfilter.h hdf4dispatch.h nclistmap.h
|
||||
ncexternl.h ncwinpath.h ncfilter.h ncindex.h hdf4dispatch.h \
|
||||
nc4xinternal.h
|
||||
|
||||
if USE_DAP
|
||||
noinst_HEADERS += ncdap.h
|
||||
|
@ -40,7 +40,6 @@ typedef struct {
|
||||
/* all xdr'd */
|
||||
size_t nchars;
|
||||
char *cp;
|
||||
|
||||
} NC_string;
|
||||
|
||||
/* Define functions that are used across multiple dispatchers */
|
||||
|
@ -25,6 +25,8 @@
|
||||
/* Always needed */
|
||||
#include "nc.h"
|
||||
|
||||
#include "nchashmap.h"
|
||||
|
||||
#ifndef NC_ARRAY_GROWBY
|
||||
#define NC_ARRAY_GROWBY 4
|
||||
#endif
|
||||
@ -55,25 +57,6 @@ typedef enum {
|
||||
NC_ATTRIBUTE = 12
|
||||
} NCtype;
|
||||
|
||||
#ifndef NEWHASHMAP /* temporary hack until new hash is complete */
|
||||
/*! Hashmap-related structs.
|
||||
NOTE: 'data' is the dimid or varid which is non-negative.
|
||||
we store the dimid+1 so a valid entry will have
|
||||
data > 0
|
||||
*/
|
||||
typedef struct {
|
||||
long data;
|
||||
int flags;
|
||||
unsigned long key;
|
||||
} hEntry;
|
||||
|
||||
typedef struct s_hashmap {
|
||||
hEntry* table;
|
||||
unsigned long size;
|
||||
unsigned long count;
|
||||
} NC_hashmap;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NC dimension structure
|
||||
*/
|
||||
@ -236,36 +219,6 @@ NC_lookupvar(NC3_INFO* ncp, int varid, NC_var **varp);
|
||||
|
||||
/* End defined in var.c */
|
||||
|
||||
/* defined in nc_hashmap.c */
|
||||
/** Creates a new hashmap near the given size. */
|
||||
extern NC_hashmap* NC_hashmapCreate(unsigned long startsize);
|
||||
|
||||
/** Inserts a new element into the hashmap. */
|
||||
extern void NC_hashmapAddDim(const NC_dimarray*, long data, const char *name);
|
||||
|
||||
/** Removes the storage for the element of the key and returns the element. */
|
||||
extern long NC_hashmapRemoveDim(const NC_dimarray*, const char *name);
|
||||
|
||||
/** Returns the element for the key. */
|
||||
extern long NC_hashmapGetDim(const NC_dimarray*, const char *name);
|
||||
|
||||
/** Inserts a new element into the hashmap. */
|
||||
extern void NC_hashmapAddVar(const NC_vararray*, long data, const char *name);
|
||||
|
||||
/** Removes the storage for the element of the key and returns the element. */
|
||||
extern long NC_hashmapRemoveVar(const NC_vararray*, const char *name);
|
||||
|
||||
/** Returns the element for the key. */
|
||||
extern long NC_hashmapGetVar(const NC_vararray*, const char *name);
|
||||
|
||||
/** Returns the number of saved elements. */
|
||||
extern unsigned long NC_hashmapCount(NC_hashmap*);
|
||||
|
||||
/** Removes the hashmap structure. */
|
||||
extern void NC_hashmapDelete(NC_hashmap*);
|
||||
|
||||
/* end defined in nc_hashmap.c */
|
||||
|
||||
#define IS_RECVAR(vp) \
|
||||
((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 )
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NCLOGLEVELENV "NETCDF_LOG_LEVEL"
|
||||
|
||||
extern int
|
||||
NC4_create(const char *path, int cmode,
|
||||
size_t initialsz, int basepe, size_t *chunksizehintp,
|
||||
|
@ -17,9 +17,9 @@
|
||||
#include <string.h>
|
||||
#include <hdf5.h>
|
||||
|
||||
|
||||
#include "ncdimscale.h"
|
||||
#include "nc_logging.h"
|
||||
#include "ncindex.h"
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
#include "netcdf_par.h"
|
||||
@ -39,7 +39,7 @@
|
||||
#define ID_SHIFT (16)
|
||||
|
||||
typedef enum {GET, PUT} NC_PG_T;
|
||||
typedef enum {VAR, DIM, ATT} NC_OBJ_T;
|
||||
typedef enum {NCNAT, NCVAR, NCDIM, NCATT, NCTYP, NCFLD, NCGRP} NC_SORT;
|
||||
|
||||
#define NC_MAX_HDF5_NAME (NC_MAX_NAME + 10)
|
||||
#define NC_V2_ERR (-1)
|
||||
@ -113,22 +113,34 @@ typedef enum {NC_FALSE = 0, NC_TRUE = 1} nc_bool_t;
|
||||
|
||||
/*Forward*/
|
||||
struct NCFILEINFO;
|
||||
struct NC_GRP_INFO;
|
||||
struct NC_TYPE_INFO;
|
||||
|
||||
/* Generic doubly-linked list node */
|
||||
typedef struct NC_LIST_NODE
|
||||
{
|
||||
void *next;
|
||||
void *prev;
|
||||
} NC_LIST_NODE_T;
|
||||
/*
|
||||
Indexed Access to Meta-data objects:
|
||||
|
||||
See the document docs/indexing.dox for detailed information.
|
||||
|
||||
Basically provide a common header and use NCindex instances
|
||||
instead of linked lists.
|
||||
|
||||
WARNING: ALL OBJECTS THAT CAN BE INSERTED INTO AN NCindex
|
||||
MUST HAVE AN INSTANCE of NC_OBJ AS THE FIRST FIELD.
|
||||
*/
|
||||
|
||||
typedef struct NC_OBJ {
|
||||
NC_SORT sort;
|
||||
char* name; /* assumed to be null terminated */
|
||||
size_t id;
|
||||
unsigned int hashkey; /* crc32(name) */
|
||||
} NC_OBJ;
|
||||
|
||||
/* This is a struct to handle the dim metadata. */
|
||||
typedef struct NC_DIM_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
NC_OBJ hdr;
|
||||
struct NC_GRP_INFO* container; /* containing group */
|
||||
size_t len;
|
||||
uint32_t hash;
|
||||
int dimid;
|
||||
nc_bool_t unlimited; /* True if the dimension is unlimited */
|
||||
nc_bool_t extended; /* True if the dimension needs to be extended */
|
||||
nc_bool_t too_long; /* True if len is too big to fit in local size_t. */
|
||||
@ -139,14 +151,13 @@ typedef struct NC_DIM_INFO
|
||||
|
||||
typedef struct NC_ATT_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
NC_OBJ hdr;
|
||||
struct NC_OBJ* container; /* containing group|var */
|
||||
int len;
|
||||
nc_bool_t dirty; /* True if attribute modified */
|
||||
nc_bool_t created; /* True if attribute already created */
|
||||
nc_type nc_typeid; /* netCDF type of attribute's data */
|
||||
hid_t native_hdf_typeid; /* Native HDF5 datatype for attribute's data */
|
||||
int attnum;
|
||||
void *data;
|
||||
nc_vlen_t *vldata; /* only used for vlen */
|
||||
char **stdata; /* only for string type. */
|
||||
@ -155,14 +166,12 @@ typedef struct NC_ATT_INFO
|
||||
/* This is a struct to handle the var metadata. */
|
||||
typedef struct NC_VAR_INFO
|
||||
{
|
||||
char *name;
|
||||
NC_OBJ hdr;
|
||||
char *hdf5_name; /* used if different from name */
|
||||
int ndims;
|
||||
struct NC_GRP_INFO* container; /* containing group */
|
||||
size_t ndims;
|
||||
int *dimids;
|
||||
NC_DIM_INFO_T **dim;
|
||||
int varid;
|
||||
int natts;
|
||||
uint32_t hash;
|
||||
NC_DIM_INFO_T** dim;
|
||||
nc_bool_t is_new_var; /* True if variable is newly created */
|
||||
nc_bool_t was_coord_var; /* True if variable was a coordinate var, but either the dim or var has been renamed */
|
||||
nc_bool_t became_coord_var; /* True if variable _became_ a coordinate var, because either the dim or var has been renamed */
|
||||
@ -172,7 +181,10 @@ typedef struct NC_VAR_INFO
|
||||
nc_bool_t written_to; /* True if variable has data written to it */
|
||||
struct NC_TYPE_INFO *type_info;
|
||||
hid_t hdf_datasetid;
|
||||
NC_ATT_INFO_T *att;
|
||||
#if 0
|
||||
int natts; /* Use explicit index because there may be gaps in numbers */
|
||||
#endif
|
||||
NCindex* att; /* NCindex<NC_ATT_INFO_T*> */
|
||||
nc_bool_t no_fill; /* True if no fill value is defined for var */
|
||||
void *fill_value;
|
||||
size_t *chunksizes;
|
||||
@ -196,39 +208,34 @@ typedef struct NC_VAR_INFO
|
||||
unsigned int filterid;
|
||||
size_t nparams;
|
||||
unsigned int* params;
|
||||
/* Stuff for diskless data files. */
|
||||
void *diskless_data;
|
||||
} NC_VAR_INFO_T;
|
||||
|
||||
typedef struct NC_FIELD_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
NC_OBJ hdr;
|
||||
nc_type nc_typeid;
|
||||
hid_t hdf_typeid;
|
||||
hid_t native_hdf_typeid;
|
||||
size_t offset;
|
||||
char *name;
|
||||
int fieldid; /* ID (index?) of field */
|
||||
int ndims;
|
||||
int *dim_size;
|
||||
} NC_FIELD_INFO_T;
|
||||
|
||||
typedef struct NC_ENUM_MEMBER_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
void *value;
|
||||
} NC_ENUM_MEMBER_INFO_T;
|
||||
|
||||
typedef struct NC_TYPE_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
nc_type nc_typeid; /* netCDF type ID, equivalent to a pre-defined type
|
||||
NC_OBJ hdr; /* contains netCDF type ID, equivalent to a pre-defined type
|
||||
* for atomic types, but a dynamically
|
||||
* defined value for user-defined types (stored
|
||||
* as named datatypes in the HDF5 file).
|
||||
*/
|
||||
|
||||
struct NC_GRP_INFO* container; /* Containing group */
|
||||
unsigned rc; /* Ref. count of objects using this type */
|
||||
hid_t hdf_typeid; /* HDF5 type ID, in the file */
|
||||
hid_t native_hdf_typeid; /* HDF5 type ID, in memory */
|
||||
@ -255,14 +262,12 @@ typedef struct NC_TYPE_INFO
|
||||
/* Information for each type or class */
|
||||
union {
|
||||
struct {
|
||||
int num_members;
|
||||
NC_ENUM_MEMBER_INFO_T *enum_member;
|
||||
NClist* enum_member; /* <! NClist<NC_ENUM_MEMBER_INFO_T*> */
|
||||
nc_type base_nc_typeid;
|
||||
hid_t base_hdf_typeid;
|
||||
} e; /* Enum */
|
||||
struct {
|
||||
int num_fields;
|
||||
NC_FIELD_INFO_T *field;
|
||||
struct Fields {
|
||||
NClist* field; /* <! NClist<NC_FIELD_INFO_T*> */
|
||||
} c; /* Compound */
|
||||
struct {
|
||||
nc_type base_nc_typeid;
|
||||
@ -271,29 +276,20 @@ typedef struct NC_TYPE_INFO
|
||||
} u; /* Union of structs, for each type/class */
|
||||
} NC_TYPE_INFO_T;
|
||||
|
||||
typedef struct NC_VAR_ARRAY_T {
|
||||
size_t nalloc; /* number allocated >= nelems */
|
||||
size_t nelems; /* length of the array */
|
||||
NC_VAR_INFO_T **value;
|
||||
} NC_VAR_ARRAY_T;
|
||||
|
||||
/* This holds information for one group. Groups reproduce with
|
||||
* parthenogenesis. */
|
||||
typedef struct NC_GRP_INFO
|
||||
{
|
||||
NC_LIST_NODE_T l; /* Use generic doubly-linked list (must be first) */
|
||||
char *name;
|
||||
NC_OBJ hdr;
|
||||
hid_t hdf_grpid;
|
||||
int nc_grpid;
|
||||
struct NC_HDF5_FILE_INFO *nc4_info;
|
||||
struct NC_GRP_INFO *parent;
|
||||
struct NC_GRP_INFO *children;
|
||||
NC_VAR_ARRAY_T vars;
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_ATT_INFO_T *att;
|
||||
NC_TYPE_INFO_T *type;
|
||||
int nvars;
|
||||
int natts;
|
||||
NCindex* children; /* NCindex<struct NC_GRP_INFO*> */
|
||||
NCindex* dim; /* NCindex<NC_DIM_INFO_T> * */
|
||||
NCindex* att; /* NCindex<NC_ATT_INFO_T> * */
|
||||
NCindex* type; /* NCindex<NC_TYPE_INFO_T> * */
|
||||
/* Note that this is the list of vars with position == varid */
|
||||
NCindex* vars; /* NCindex<NC_VAR_INFO_T> * */
|
||||
} NC_GRP_INFO_T;
|
||||
|
||||
/* These constants apply to the cmode parameter in the
|
||||
@ -305,7 +301,6 @@ typedef struct NC_GRP_INFO
|
||||
#define NC_NDIRTY 0x40 /* numrecs has changed */
|
||||
#define NC_HDIRTY 0x80 /* header info has changed */
|
||||
|
||||
|
||||
/* This is the metadata we need to keep track of for each
|
||||
netcdf-4/HDF5 file. */
|
||||
typedef struct NC_HDF5_FILE_INFO
|
||||
@ -323,10 +318,17 @@ typedef struct NC_HDF5_FILE_INFO
|
||||
int fill_mode; /* Fill mode for vars - Unused internally currently */
|
||||
nc_bool_t no_write; /* true if nc_open has mode NC_NOWRITE. */
|
||||
NC_GRP_INFO_T *root_grp;
|
||||
/* Track indices to assign to grps, types, and dims */
|
||||
short next_nc_grpid;
|
||||
NC_TYPE_INFO_T *type;
|
||||
int next_typeid;
|
||||
int next_dimid;
|
||||
/* Provide convenience vectors indexed by the object id.
|
||||
This allows for direct conversion of e.g. an nc_type to
|
||||
the corresponding NC_TYPE_INFO_T object.
|
||||
*/
|
||||
NClist* alldims;
|
||||
NClist* alltypes;
|
||||
NClist* allgroups; /* including root group */
|
||||
#ifdef USE_HDF4
|
||||
nc_bool_t hdf4; /* True for HDF4 file */
|
||||
int sdid;
|
||||
@ -335,12 +337,10 @@ typedef struct NC_HDF5_FILE_INFO
|
||||
} NC_HDF5_FILE_INFO_T;
|
||||
|
||||
|
||||
/* Defined in lookup3.c */
|
||||
extern uint32_t hash_fast(const void *key, size_t length);
|
||||
extern char* nc4_atomic_name[NC_MAX_ATOMIC_TYPE+1];
|
||||
|
||||
/* These functions convert between netcdf and HDF5 types. */
|
||||
int nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype,
|
||||
int is_long, size_t *len);
|
||||
int nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype, size_t *len);
|
||||
int nc4_convert_type(const void *src, void *dest,
|
||||
const nc_type src_type, const nc_type dest_type,
|
||||
const size_t len, int *range_error,
|
||||
@ -371,14 +371,14 @@ int nc4_find_nc_grp_h5(int ncid, NC **nc, NC_GRP_INFO_T **grp,
|
||||
int nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_HDF5_FILE_INFO_T **h5);
|
||||
int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp);
|
||||
NC_GRP_INFO_T *nc4_find_nc_grp(int ncid);
|
||||
NC_GRP_INFO_T *nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid);
|
||||
NC_GRP_INFO_T *nc4_rec_find_grp(NC_HDF5_FILE_INFO_T *h5, int target_nc_grpid);
|
||||
NC *nc4_find_nc_file(int ncid, NC_HDF5_FILE_INFO_T**);
|
||||
int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, NC_GRP_INFO_T **dim_grp);
|
||||
int nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var);
|
||||
int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len);
|
||||
int nc4_find_type(const NC_HDF5_FILE_INFO_T *h5, int typeid1, NC_TYPE_INFO_T **type);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_nc_type(const NC_GRP_INFO_T *start_grp, nc_type target_nc_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_nc_type(NC_HDF5_FILE_INFO_T *h5, nc_type target_nc_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_hdf_type(NC_HDF5_FILE_INFO_T* h5, hid_t target_hdf_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_equal_type(NC_GRP_INFO_T *start_grp, int ncid1, NC_TYPE_INFO_T *type);
|
||||
int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
|
||||
@ -397,23 +397,27 @@ int nc4_type_free(NC_TYPE_INFO_T *type);
|
||||
|
||||
/* These list functions add and delete vars, atts. */
|
||||
int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
|
||||
int nc4_var_add(NC_VAR_INFO_T **var);
|
||||
int nc4_var_del(NC_VAR_INFO_T *var);
|
||||
int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
int nc4_dim_list_add(NC_DIM_INFO_T **list, NC_DIM_INFO_T **dim);
|
||||
int nc4_dim_list_del(NC_DIM_INFO_T **list, NC_DIM_INFO_T *dim);
|
||||
int nc4_att_list_add(NC_ATT_INFO_T **list, NC_ATT_INFO_T **att);
|
||||
int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name,
|
||||
NC_TYPE_INFO_T **type);
|
||||
int nc4_field_list_add(NC_FIELD_INFO_T **list, int fieldid, const char *name,
|
||||
void nc4_file_list_del(NC *nc);
|
||||
int nc4_var_list_add(NC_GRP_INFO_T* grp, const char* name, int ndims, NC_VAR_INFO_T **var);
|
||||
int nc4_var_list_del(NC_GRP_INFO_T* grp, NC_VAR_INFO_T *var);
|
||||
int nc4_var_free(NC_VAR_INFO_T *var);
|
||||
int nc4_dim_list_add(NC_GRP_INFO_T* grp, const char* name, size_t len, int assignedid, NC_DIM_INFO_T **dim);
|
||||
int nc4_dim_list_del(NC_GRP_INFO_T* grp, NC_DIM_INFO_T *dim);
|
||||
int nc4_dim_free(NC_DIM_INFO_T *dim);
|
||||
int nc4_type_new(NC_GRP_INFO_T *grp, size_t size, const char *name, int assignedid, NC_TYPE_INFO_T **type);
|
||||
int nc4_type_list_add(NC_GRP_INFO_T *grp, size_t size, const char *name, NC_TYPE_INFO_T **type);
|
||||
int nc4_type_list_del(NC_GRP_INFO_T* grp, NC_TYPE_INFO_T *type);
|
||||
int nc4_type_free(NC_TYPE_INFO_T *type);
|
||||
int nc4_field_list_add(NC_TYPE_INFO_T* parent, const char *name,
|
||||
size_t offset, hid_t field_hdf_typeid, hid_t native_typeid,
|
||||
nc_type xtype, int ndims, const int *dim_sizesp);
|
||||
void nc4_file_list_del(NC *nc);
|
||||
int nc4_att_list_del(NC_ATT_INFO_T **list, NC_ATT_INFO_T *att);
|
||||
int nc4_grp_list_add(NC_GRP_INFO_T **list, int new_nc_grpid, NC_GRP_INFO_T *parent_grp,
|
||||
NC *nc, char *name, NC_GRP_INFO_T **grp);
|
||||
int nc4_rec_grp_del(NC_GRP_INFO_T **list, NC_GRP_INFO_T *grp);
|
||||
int nc4_enum_member_add(NC_ENUM_MEMBER_INFO_T **list, size_t size,
|
||||
int nc4_att_list_add(NCindex* list, const char* name, NC_ATT_INFO_T **att);
|
||||
int nc4_att_list_del(NCindex* list, NC_ATT_INFO_T *att);
|
||||
int nc4_att_free(NC_ATT_INFO_T *att);
|
||||
int nc4_grp_list_add(NC_GRP_INFO_T *parent, char *name, NC_GRP_INFO_T **grp);
|
||||
int nc4_build_root_grp(NC_HDF5_FILE_INFO_T* h5);
|
||||
int nc4_rec_grp_del(NC_GRP_INFO_T *grp);
|
||||
int nc4_enum_member_add(NC_TYPE_INFO_T *type, size_t size,
|
||||
const char *name, const void *value);
|
||||
|
||||
/* Break & reform coordinate variables */
|
||||
@ -440,10 +444,24 @@ int log_metadata_nc(NC *nc);
|
||||
#define NC4_DATA(nc) ((NC_HDF5_FILE_INFO_T*)(nc)->dispatchdata)
|
||||
#define NC4_DATA_SET(nc,data) ((nc)->dispatchdata = (void*)(data))
|
||||
|
||||
/* Reserved Attributes */
|
||||
extern const char* NC_RESERVED_VARATT_LIST[];
|
||||
extern const char* NC_RESERVED_ATT_LIST[];
|
||||
extern const char* NC_RESERVED_SPECIAL_LIST[];
|
||||
/* Reserved Attributes Info */
|
||||
typedef struct NC_reservedatt {
|
||||
const char* name;
|
||||
int flags;
|
||||
} NC_reservedatt;
|
||||
|
||||
/* Reserved attribute flags: must be powers of 2*/
|
||||
/* Hidden dimscale-related, per-variable attributes; immutable and unreadable thru API */
|
||||
#define DIMSCALEFLAG 1
|
||||
/* Readonly global attributes; readable, but immutable thru the API */
|
||||
#define READONLYFLAG 2
|
||||
/* Subset of readonly flags; readable by name only thru the API*/
|
||||
#define NAMEONLYFLAG 4
|
||||
|
||||
/* Binary searcher for reserved attributes */
|
||||
extern const NC_reservedatt* NC_findreserved(const char* name);
|
||||
|
||||
/* Generic reserved Attributes */
|
||||
#define NC_ATT_REFERENCE_LIST "REFERENCE_LIST"
|
||||
#define NC_ATT_CLASS "CLASS"
|
||||
#define NC_ATT_DIMENSION_LIST "DIMENSION_LIST"
|
||||
|
521
include/nc4xinternal.h
Normal file
521
include/nc4xinternal.h
Normal file
@ -0,0 +1,521 @@
|
||||
/** \file
|
||||
This header file contains the definitions of structs used to hold
|
||||
netCDF file metadata in memory.
|
||||
|
||||
Copyright 2005-2011 University Corporation for Atmospheric
|
||||
Research/Unidata.
|
||||
*/
|
||||
|
||||
#ifndef _NC4INTERNAL_
|
||||
#define _NC4INTERNAL_
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <hdf5.h>
|
||||
|
||||
#include "ncdimscale.h"
|
||||
#include "nc_logging.h"
|
||||
#include "ncindex.h"
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
#include "netcdf_par.h"
|
||||
#endif /* USE_PARALLEL */
|
||||
#include "netcdf.h"
|
||||
#include "netcdf_f.h"
|
||||
|
||||
/* Always needed */
|
||||
#include "nc.h"
|
||||
|
||||
#ifdef USE_HDF4
|
||||
#include <mfhdf.h>
|
||||
#endif
|
||||
|
||||
#define FILE_ID_MASK (0xffff0000)
|
||||
#define GRP_ID_MASK (0x0000ffff)
|
||||
#define ID_SHIFT (16)
|
||||
|
||||
typedef enum {GET, PUT} NC_PG_T;
|
||||
typedef enum {NCNAT, NCVAR, NCDIM, NCATT, NCTYP, NCGRP} NC_SORT;
|
||||
|
||||
#define NC_MAX_HDF5_NAME (NC_MAX_NAME + 10)
|
||||
#define NC_V2_ERR (-1)
|
||||
|
||||
/* The name of the root group. */
|
||||
#define NC_GROUP_NAME "/"
|
||||
|
||||
#define MEGABYTE 1048576
|
||||
|
||||
/*
|
||||
* limits of the external representation
|
||||
*/
|
||||
#define X_SCHAR_MIN (-128)
|
||||
#define X_SCHAR_MAX 127
|
||||
#define X_UCHAR_MAX 255U
|
||||
#define X_SHORT_MIN (-32768)
|
||||
#define X_SHRT_MIN X_SHORT_MIN /* alias compatible with limits.h */
|
||||
#define X_SHORT_MAX 32767
|
||||
#define X_SHRT_MAX X_SHORT_MAX /* alias compatible with limits.h */
|
||||
#define X_USHORT_MAX 65535U
|
||||
#define X_USHRT_MAX X_USHORT_MAX /* alias compatible with limits.h */
|
||||
#define X_INT_MIN (-2147483647-1)
|
||||
#define X_INT_MAX 2147483647
|
||||
#define X_LONG_MIN X_INT_MIN
|
||||
#define X_LONG_MAX X_INT_MAX
|
||||
#define X_UINT_MAX 4294967295U
|
||||
#define X_INT64_MIN (-9223372036854775807LL-1LL)
|
||||
#define X_INT64_MAX 9223372036854775807LL
|
||||
#define X_UINT64_MAX 18446744073709551615ULL
|
||||
#ifdef WIN32 /* Windows, of course, has to be a *little* different. */
|
||||
#define X_FLOAT_MAX 3.402823466e+38f
|
||||
#else
|
||||
#define X_FLOAT_MAX 3.40282347e+38f
|
||||
#endif /* WIN32 */
|
||||
#define X_FLOAT_MIN (-X_FLOAT_MAX)
|
||||
#define X_DOUBLE_MAX 1.7976931348623157e+308
|
||||
#define X_DOUBLE_MIN (-X_DOUBLE_MAX)
|
||||
|
||||
/* These have to do with creating chuncked datasets in HDF5. */
|
||||
#define NC_HDF5_UNLIMITED_DIMSIZE (0)
|
||||
#define NC_HDF5_CHUNKSIZE_FACTOR (10)
|
||||
#define NC_HDF5_MIN_CHUNK_SIZE (2)
|
||||
|
||||
#define NC_EMPTY_SCALE "NC_EMPTY_SCALE"
|
||||
|
||||
/* This is an attribute I had to add to handle multidimensional
|
||||
* coordinate variables. */
|
||||
#define COORDINATES "_Netcdf4Coordinates"
|
||||
#define COORDINATES_LEN (NC_MAX_NAME * 5)
|
||||
|
||||
/* This is used when the user defines a non-coordinate variable with
|
||||
* same name as a dimension. */
|
||||
#define NON_COORD_PREPEND "_nc4_non_coord_"
|
||||
|
||||
/* An attribute in the HDF5 root group of this name means that the
|
||||
* file must follow strict netCDF classic format rules. */
|
||||
#define NC3_STRICT_ATT_NAME "_nc3_strict"
|
||||
|
||||
/* If this attribute is present on a dimscale variable, use the value
|
||||
* as the netCDF dimid. */
|
||||
#define NC_DIMID_ATT_NAME "_Netcdf4Dimid"
|
||||
|
||||
/** This is the name of the class HDF5 dimension scale attribute. */
|
||||
#define HDF5_DIMSCALE_CLASS_ATT_NAME "CLASS"
|
||||
|
||||
/** This is the name of the name HDF5 dimension scale attribute. */
|
||||
#define HDF5_DIMSCALE_NAME_ATT_NAME "NAME"
|
||||
|
||||
/* Boolean type, to make the code easier to read */
|
||||
typedef enum {NC_FALSE = 0, NC_TRUE = 1} nc_bool_t;
|
||||
|
||||
/*Forward*/
|
||||
struct NCFILEINFO;
|
||||
struct NC_GRP_INFO;
|
||||
struct NC_TYPE_INFO;
|
||||
|
||||
/*
|
||||
Indexed Access to Meta-data objects:
|
||||
|
||||
See the document docs/indexing.dox for detailed information.
|
||||
|
||||
WARNING: ALL OBJECTS THAT CAN BE INSERTED INTO AN NC_LISTMAP
|
||||
MUST HAVE AN INSTANCE of NC_OBJ AS THE FIRST FIELD.
|
||||
*/
|
||||
|
||||
typedef struct NC_OBJ {
|
||||
NC_SORT sort;
|
||||
char* name; /* assumed to be null terminated */
|
||||
size_t id;
|
||||
/* Consider adding |name| and the hashkey for the name */
|
||||
} NC_OBJ;
|
||||
|
||||
/* This is a struct to handle the dim metadata. */
|
||||
typedef struct NC_DIM_INFO
|
||||
{
|
||||
NC_OBJ hdr;
|
||||
size_t len;
|
||||
nc_bool_t unlimited; /* True if the dimension is unlimited */
|
||||
nc_bool_t extended; /* True if the dimension needs to be extended */
|
||||
nc_bool_t too_long; /* True if len is too big to fit in local size_t. */
|
||||
hid_t hdf_dimscaleid; /* Non-zero if a DIM_WITHOUT_VARIABLE dataset is in use (no coord var). */
|
||||
HDF5_OBJID_T hdf5_objid;
|
||||
struct NC_VAR_INFO *coord_var; /* The coord var, if it exists. */
|
||||
} NC_DIM_INFO_T;
|
||||
|
||||
typedef struct NC_ATT_INFO
|
||||
{
|
||||
NC_OBJ hdr;
|
||||
int len;
|
||||
nc_bool_t dirty; /* True if attribute modified */
|
||||
nc_bool_t created; /* True if attribute already created */
|
||||
struct NC_TYPE_INFO* type; /* netCDF type of attribute's data */
|
||||
hid_t native_hdf_typeid; /* Native HDF5 datatype for attribute's data */
|
||||
void *data;
|
||||
nc_vlen_t *vldata; /* only used for vlen */
|
||||
char **stdata; /* only for string type. */
|
||||
} NC_ATT_INFO_T;
|
||||
|
||||
/* This is a struct to handle the var metadata. */
|
||||
typedef struct NC_VAR_INFO
|
||||
{
|
||||
NC_OBJ hdr;
|
||||
char *hdf5_name; /* used if different from name */
|
||||
struct NC_GRP_INFO* container; /* containing group */
|
||||
struct {
|
||||
size_t ndims;
|
||||
NC_DIM_INFO_T** dims;
|
||||
int *dimids;
|
||||
} dim;
|
||||
nc_bool_t is_new_var; /* True if variable is newly created */
|
||||
nc_bool_t was_coord_var; /* True if variable was a coordinate var, but either the dim or var has been renamed */
|
||||
nc_bool_t became_coord_var; /* True if variable _became_ a coordinate var, because either the dim or var has been renamed */
|
||||
nc_bool_t fill_val_changed; /* True if variable's fill value changes after it has been created */
|
||||
nc_bool_t attr_dirty; /* True if variable's attributes are dirty and should be rewritten */
|
||||
nc_bool_t created; /* Variable has already been created (_not_ that it was just created) */
|
||||
nc_bool_t written_to; /* True if variable has data written to it */
|
||||
struct NC_TYPE_INFO *type_info;
|
||||
hid_t hdf_datasetid;
|
||||
NCindex* att; /* NCindex<NC_ATT_INFO_T*> */
|
||||
int endianness; /* What endianness for the base type of this variable? */
|
||||
/* (Set for integer types as well as "complex"
|
||||
* types, like compound/enum/vlen, used for the
|
||||
* endianness of the fields and/or base type)
|
||||
*/
|
||||
nc_bool_t no_fill; /* True if no fill value is defined for var */
|
||||
void *fill_value;
|
||||
size_t *chunksizes;
|
||||
nc_bool_t contiguous; /* True if variable is stored contiguously in HDF5 file */
|
||||
int parallel_access; /* Type of parallel access for I/O on variable (collective or independent) */
|
||||
nc_bool_t dimscale; /* True if var is a dimscale */
|
||||
nc_bool_t *dimscale_attached; /* Array of flags that are true if dimscale is attached for that dim index */
|
||||
HDF5_OBJID_T *dimscale_hdf5_objids;
|
||||
nc_bool_t deflate; /* True if var has deflate filter applied */
|
||||
int deflate_level;
|
||||
nc_bool_t shuffle; /* True if var has shuffle filter applied */
|
||||
nc_bool_t fletcher32; /* True if var has fletcher32 filter applied */
|
||||
size_t chunk_cache_size, chunk_cache_nelems;
|
||||
float chunk_cache_preemption;
|
||||
#ifdef USE_HDF4
|
||||
/* Stuff below is for hdf4 files. */
|
||||
int sdsid;
|
||||
int hdf4_data_type;
|
||||
#endif /* USE_HDF4 */
|
||||
/* Stuff for arbitrary filters */
|
||||
unsigned int filterid;
|
||||
size_t nparams;
|
||||
unsigned int* params;
|
||||
} NC_VAR_INFO_T;
|
||||
|
||||
typedef struct NC_FIELD_INFO
|
||||
{
|
||||
NC_OBJ hdr;
|
||||
#if 0
|
||||
nc_type nc_typeid;
|
||||
#else
|
||||
struct NC_TYPE_INFO* type;
|
||||
#endif
|
||||
hid_t hdf_typeid;
|
||||
hid_t native_hdf_typeid;
|
||||
size_t offset;
|
||||
struct {
|
||||
int ndims;
|
||||
int *dim_size;
|
||||
} dims;
|
||||
} NC_FIELD_INFO_T;
|
||||
|
||||
typedef struct NC_ENUM_MEMBER_INFO
|
||||
{
|
||||
char *name;
|
||||
void *value;
|
||||
} NC_ENUM_MEMBER_INFO_T;
|
||||
|
||||
typedef struct NC_TYPE_INFO
|
||||
{
|
||||
NC_OBJ hdr; /* contains netCDF type ID, equivalent to a pre-defined type
|
||||
* for atomic types, but a dynamically
|
||||
* defined value for user-defined types (stored
|
||||
* as named datatypes in the HDF5 file).
|
||||
*/
|
||||
|
||||
struct NC_GRP_INFO* container; /* Containing group */
|
||||
unsigned rc; /* Ref. count of objects using this type */
|
||||
hid_t hdf_typeid; /* HDF5 type ID, in the file */
|
||||
hid_t native_hdf_typeid; /* HDF5 type ID, in memory */
|
||||
size_t size; /* Size of the type in memory, in bytes */
|
||||
nc_bool_t committed; /* True when datatype is committed in the file */
|
||||
nc_type nc_type_class; /* NC_VLEN, NC_COMPOUND, NC_OPAQUE, or NC_ENUM
|
||||
* NOTE: NC_INT is used for all integer types,
|
||||
* NC_FLOAT is used for all floating-point
|
||||
* types, and NC_STRING is also used for
|
||||
* fixed- and variable-length strings.
|
||||
* (NC_CHAR is used for characters though)
|
||||
*
|
||||
* This is somewhat redundant with the
|
||||
* nc_type field, but allows the code to
|
||||
* have a single location to look at for
|
||||
* the "kind" of a type.
|
||||
*/
|
||||
|
||||
/* Information for each type or class */
|
||||
union {
|
||||
struct {
|
||||
NClist* members; /* <! NClist<NC_ENUM_MEMBER_INFO_T*> */
|
||||
struct NC_TYPE_INFO* base_type;
|
||||
hid_t base_hdf_typeid;
|
||||
} e; /* Enum */
|
||||
struct Fields {
|
||||
NClist* fields; /* <! NClist<NC_FIELD_INFO_T*> */
|
||||
} c; /* Compound */
|
||||
struct {
|
||||
struct NC_TYPE_INFO* base_type;
|
||||
hid_t base_hdf_typeid;
|
||||
} v; /* Variable-length */
|
||||
} u; /* Union of structs, for each type/class */
|
||||
} NC_TYPE_INFO_T;
|
||||
|
||||
/* This holds information for one group. Groups reproduce with
|
||||
* parthenogenesis. */
|
||||
typedef struct NC_GRP_INFO
|
||||
{
|
||||
NC_OBJ hdr;
|
||||
hid_t hdf_grpid;
|
||||
struct NC_HDF5_FILE_INFO *nc4_info;
|
||||
struct NC_GRP_INFO *parent;
|
||||
NCindex* children; /* NCindex<struct NC_GRP_INFO*> */
|
||||
NCindex* dim; /* NCindex<NC_DIM_INFO_T> * */
|
||||
NCindex* att; /* NCindex<NC_ATT_INFO_T> * */
|
||||
NCindex* type; /* NCindex<NC_TYPE_INFO_T> * */
|
||||
/* Note that this is the list of vars with position == varid */
|
||||
NCindex* vars; /* NCindex<NC_VAR_INFO_T> * */
|
||||
} NC_GRP_INFO_T;
|
||||
|
||||
/* These constants apply to the cmode parameter in the
|
||||
* HDF5_FILE_INFO_T defined below. */
|
||||
#define NC_CREAT 2 /* in create phase, cleared by ncendef */
|
||||
#define NC_INDEF 8 /* in define mode, cleared by ncendef */
|
||||
#define NC_NSYNC 0x10 /* synchronise numrecs on change */
|
||||
#define NC_HSYNC 0x20 /* synchronise whole header on change */
|
||||
#define NC_NDIRTY 0x40 /* numrecs has changed */
|
||||
#define NC_HDIRTY 0x80 /* header info has changed */
|
||||
|
||||
/* This is the metadata we need to keep track of for each
|
||||
netcdf-4/HDF5 file. */
|
||||
typedef struct NC_HDF5_FILE_INFO
|
||||
{
|
||||
NC* controller;
|
||||
hid_t hdfid;
|
||||
#ifdef USE_PARALLEL4
|
||||
MPI_Comm comm; /* Copy of MPI Communicator used to open the file */
|
||||
MPI_Info info; /* Copy of MPI Information Object used to open the file */
|
||||
#endif
|
||||
int flags;
|
||||
int cmode;
|
||||
nc_bool_t parallel; /* True if file is open for parallel access */
|
||||
nc_bool_t redef; /* True if redefining an existing file */
|
||||
int fill_mode; /* Fill mode for vars - Unused internally currently */
|
||||
nc_bool_t no_write; /* true if nc_open has mode NC_NOWRITE. */
|
||||
NC_GRP_INFO_T *root_grp;
|
||||
/* Dim,type, and group ids define position of the object in these vectors */
|
||||
NClist* alldims;
|
||||
NClist* alltypes;
|
||||
NClist* allgroups; /* including root group */
|
||||
#ifdef USE_HDF4
|
||||
nc_bool_t hdf4; /* True for HDF4 file */
|
||||
int sdid;
|
||||
#endif /* USE_HDF4 */
|
||||
struct NCFILEINFO* fileinfo;
|
||||
} NC_HDF5_FILE_INFO_T;
|
||||
|
||||
/* These functions convert between netcdf and HDF5 types. */
|
||||
int nc4_get_typelen_mem(NC_HDF5_FILE_INFO_T *h5, nc_type xtype,
|
||||
int is_long, size_t *len);
|
||||
int nc4_convert_type(const void *src, void *dest,
|
||||
const nc_type src_type, const nc_type dest_type,
|
||||
const size_t len, int *range_error,
|
||||
const void *fill_value, int strict_nc3, int src_long,
|
||||
int dest_long);
|
||||
|
||||
/* These functions do HDF5 things. */
|
||||
int rec_detach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid);
|
||||
int rec_reattach_scales(NC_GRP_INFO_T *grp, int dimid, hid_t dimscaleid);
|
||||
int delete_existing_dimscale_dataset(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T *dim);
|
||||
int nc4_open_var_grp2(NC_GRP_INFO_T *grp, int varid, hid_t *dataset);
|
||||
int nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, nc_type xtype, int is_long, void *op);
|
||||
int nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
const size_t *countp, nc_type xtype, int is_long, void *op);
|
||||
int nc4_rec_match_dimscales(NC_GRP_INFO_T *grp);
|
||||
int nc4_rec_detect_need_to_preserve_dimids(NC_GRP_INFO_T *grp, nc_bool_t *bad_coord_orderp);
|
||||
int nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order);
|
||||
int nc4_rec_write_groups_types(NC_GRP_INFO_T *grp);
|
||||
int nc4_enddef_netcdf4_file(NC_HDF5_FILE_INFO_T *h5);
|
||||
int nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
int nc4_adjust_var_cache(NC_GRP_INFO_T *grp, NC_VAR_INFO_T * var);
|
||||
|
||||
/* The following functions manipulate the in-memory linked list of
|
||||
metadata, without using HDF calls. */
|
||||
int nc4_find_nc_grp_h5(int ncid, NC **nc, NC_GRP_INFO_T **grp,
|
||||
NC_HDF5_FILE_INFO_T **h5);
|
||||
int nc4_find_grp_h5(int ncid, NC_GRP_INFO_T **grp, NC_HDF5_FILE_INFO_T **h5);
|
||||
int nc4_find_nc4_grp(int ncid, NC_GRP_INFO_T **grp);
|
||||
NC_GRP_INFO_T *nc4_find_nc_grp(int ncid);
|
||||
NC_GRP_INFO_T *nc4_rec_find_grp(NC_GRP_INFO_T *start_grp, int target_nc_grpid);
|
||||
NC *nc4_find_nc_file(int ncid, NC_HDF5_FILE_INFO_T**);
|
||||
int nc4_find_dim(NC_GRP_INFO_T *grp, int dimid, NC_DIM_INFO_T **dim, NC_GRP_INFO_T **dim_grp);
|
||||
int nc4_find_var(NC_GRP_INFO_T *grp, const char *name, NC_VAR_INFO_T **var);
|
||||
int nc4_find_dim_len(NC_GRP_INFO_T *grp, int dimid, size_t **len);
|
||||
int nc4_find_type(const NC_HDF5_FILE_INFO_T *h5, int typeid1, NC_TYPE_INFO_T **type);
|
||||
int nc4_find_any_type(const NC_HDF5_FILE_INFO_T *h5, int xtype, NC_TYPE_INFO_T **typep);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_nc_type(NC_GRP_INFO_T *start_grp, nc_type target_nc_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_hdf_type(NC_GRP_INFO_T *start_grp, hid_t target_hdf_typeid);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_named_type(NC_GRP_INFO_T *start_grp, char *name);
|
||||
NC_TYPE_INFO_T *nc4_rec_find_equal_type(NC_GRP_INFO_T *start_grp, int ncid1, NC_TYPE_INFO_T *type);
|
||||
int nc4_find_nc_att(int ncid, int varid, const char *name, int attnum,
|
||||
NC_ATT_INFO_T **att);
|
||||
int nc4_find_g_var_nc(NC *nc, int ncid, int varid,
|
||||
NC_GRP_INFO_T **grp, NC_VAR_INFO_T **var);
|
||||
int nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
|
||||
NC_ATT_INFO_T **att);
|
||||
int nc4_get_hdf_typeid(NC_HDF5_FILE_INFO_T *h5, nc_type xtype,
|
||||
hid_t *hdf_typeid, int endianness);
|
||||
int nc4_get_typeclass(const NC_HDF5_FILE_INFO_T *h5, nc_type xtype,
|
||||
int *type_class);
|
||||
|
||||
/* These functions create various kinds of object */
|
||||
int nc4_grp_new(NC_GRP_INFO_T* parent, const char *name, NC_GRP_INFO_T **grpp);
|
||||
int nc4_dim_new(const char* name, NC_DIM_INFO_T **);
|
||||
int nc4_type_new(nc_type typeclass, size_t size, const char *name, NC_TYPE_INFO_T **);
|
||||
int nc4_var_new(const char* name, NC_TYPE_INFO_T*, int ndims, NC_VAR_INFO_T **var);
|
||||
int nc4_att_new(const char* name, NC_TYPE_INFO_T*, NC_ATT_INFO_T **attp); /* Does not set value */
|
||||
int nc4_enum_member_new(size_t size, const char *name, const void *value, NC_ENUM_MEMBER_INFO_T**);
|
||||
int nc4_field_new(NC_TYPE_INFO_T* parent, const char *name,
|
||||
size_t offset, hid_t field_hdf_typeid, hid_t native_typeid,
|
||||
nc_type xtype, int ndims, const int *dim_sizesp, NC_FIELD_INFO_T**);
|
||||
|
||||
/* These functions reclaim various kinds of object */
|
||||
int nc4_grp_free(NC_GRP_INFO_T*);
|
||||
int nc4_grp_clear(NC_GRP_INFO_T*);
|
||||
int nc4_dim_free(NC_DIM_INFO_T*);
|
||||
int nc4_type_free(NC_TYPE_INFO_T*);
|
||||
int nc4_var_free(NC_VAR_INFO_T*);
|
||||
int nc4_att_free(NC_ATT_INFO_T*);
|
||||
int nc4_enum_member_free(NC_ENUM_MEMBER_INFO_T*);
|
||||
int nc4_field_free(NC_FIELD_INFO_T*);
|
||||
|
||||
/* These list functions add and delete vars, atts. */
|
||||
/* Delete functions only exist when the deletion has complications */
|
||||
int nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var);
|
||||
int nc4_nc4f_list_add(NC *nc, const char *path, int mode);
|
||||
int nc4_dim_list_add(NC_GRP_INFO_T*, NC_DIM_INFO_T *dim);
|
||||
int nc4_att_list_add(NCindex* list, NC_ATT_INFO_T *att);
|
||||
int nc4_att_list_del(NCindex* list, NC_ATT_INFO_T *att);
|
||||
int nc4_type_list_add(NC_HDF5_FILE_INFO_T*, NC_GRP_INFO_T* grp, NC_TYPE_INFO_T *type);
|
||||
int nc4_field_list_add(NC_TYPE_INFO_T*, NC_FIELD_INFO_T*);
|
||||
int nc4_member_list_add(NC_TYPE_INFO_T*, NC_ENUM_MEMBER_INFO_T*);
|
||||
int nc4_grp_list_add(struct NC_HDF5_FILE_INFO*, NC_GRP_INFO_T *grp);
|
||||
int nc4_rec_grp_del(NC_GRP_INFO_T* list);
|
||||
void nc4_file_list_del(NC *nc);
|
||||
|
||||
/* Break & reform coordinate variables */
|
||||
int nc4_break_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T *dim);
|
||||
int nc4_reform_coord_var(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *coord_var, NC_DIM_INFO_T *dim);
|
||||
|
||||
/* Check and normalize names. */
|
||||
int NC_check_name(const char *name);
|
||||
int nc4_check_name(const char *name, char *norm_name);
|
||||
int nc4_normalize_name(const char *name, char *norm_name);
|
||||
int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name);
|
||||
|
||||
/* HDF5 initialization */
|
||||
extern int nc4_hdf5_initialized;
|
||||
extern void nc4_hdf5_initialize(void);
|
||||
|
||||
/* This is only included if --enable-logging is used for configure; it
|
||||
prints info about the metadata to stderr. */
|
||||
#ifdef LOGGING
|
||||
int log_metadata_nc(NC *nc);
|
||||
#endif
|
||||
|
||||
/* Define accessors for the dispatchdata */
|
||||
#define NC4_DATA(nc) ((NC_HDF5_FILE_INFO_T*)(nc)->dispatchdata)
|
||||
#define NC4_DATA_SET(nc,data) ((nc)->dispatchdata = (void*)(data))
|
||||
|
||||
/* Reserved Attributes Info */
|
||||
typedef struct NC_reservedatt {
|
||||
const char* name;
|
||||
int flags;
|
||||
} NC_reservedatt;
|
||||
|
||||
/* Reserved attribute flags: must be powers of 2*/
|
||||
/* Hidden dimscale-related, per-variable attributes; immutable and unreadable thru API */
|
||||
#define DIMSCALEFLAG 1
|
||||
/* Readonly global attributes; readable, but immutable thru the API */
|
||||
#define READONLYFLAG 2
|
||||
/* Subset of readonly flags; readable by name only thru the API*/
|
||||
#define NAMEONLYFLAG 4
|
||||
|
||||
/* Binary searcher for reserved attributes */
|
||||
extern const NC_reservedatt* NC_findreserved(const char* name);
|
||||
|
||||
/* Generic reserved Attributes */
|
||||
#define NC_ATT_REFERENCE_LIST "REFERENCE_LIST"
|
||||
#define NC_ATT_CLASS "CLASS"
|
||||
#define NC_ATT_DIMENSION_LIST "DIMENSION_LIST"
|
||||
#define NC_ATT_NAME "NAME"
|
||||
#define NC_ATT_COORDINATES COORDINATES /*defined above*/
|
||||
#define NC_ATT_FORMAT "_Format"
|
||||
|
||||
/**************************************************/
|
||||
/**
|
||||
For netcdf4 files, capture state information about the following:
|
||||
1. Global: netcdf library version
|
||||
2. Global: hdf5 library version
|
||||
3. Per file: superblock version
|
||||
4. Per File: was it created by netcdf-4?
|
||||
5. Per file: _NCProperties attribute
|
||||
*/
|
||||
|
||||
#define NCPROPS "_NCProperties"
|
||||
#define NCPROPS_VERSION (1)
|
||||
#define NCPROPSSEP '|'
|
||||
|
||||
/* Currently used properties */
|
||||
#define NCPVERSION "version" /* Of the properties format */
|
||||
#define NCPHDF5LIBVERSION "hdf5libversion"
|
||||
#define NCPNCLIBVERSION "netcdflibversion"
|
||||
|
||||
/* Other hidden attributes */
|
||||
#define ISNETCDF4ATT "_IsNetcdf4"
|
||||
#define SUPERBLOCKATT "_SuperblockVersion"
|
||||
|
||||
struct NCFILEINFO {
|
||||
int superblockversion;
|
||||
/* Following is filled from NCPROPS attribute or from global version */
|
||||
struct NCPROPINFO {
|
||||
int version; /* 0 => not defined */
|
||||
char hdf5ver[NC_MAX_NAME+1];
|
||||
char netcdfver[NC_MAX_NAME+1];
|
||||
} propattr;
|
||||
};
|
||||
|
||||
extern struct NCPROPINFO globalpropinfo;
|
||||
|
||||
hid_t nc4_h5_native_type_constant_g[NC_MAX_ATOMIC_TYPE];
|
||||
|
||||
extern int NC4_fileinfo_init(void); /*libsrc4/ncinfo.c*/
|
||||
extern int NC4_get_fileinfo(struct NC_HDF5_FILE_INFO* info, struct NCPROPINFO*); /*libsrc4/ncinfo.c*/
|
||||
extern int NC4_put_propattr(struct NC_HDF5_FILE_INFO* info); /*libsrc4/ncinfo.c*/
|
||||
extern int NC4_buildpropinfo(struct NCPROPINFO* info,char** propdatap);
|
||||
|
||||
extern int NC4_hdf5get_libversion(unsigned*,unsigned*,unsigned*);/*libsrc4/nc4hdf.c*/
|
||||
extern int NC4_hdf5get_superblock(struct NC_HDF5_FILE_INFO*, int*);/*libsrc4/nc4hdf.c*/
|
||||
extern int NC4_isnetcdf4(struct NC_HDF5_FILE_INFO*); /*libsrc4/nc4hdf.c*/
|
||||
|
||||
extern int nc4_init_type_vector(NC_HDF5_FILE_INFO_T* h5);
|
||||
extern void nc4_init_native_type_ids(void);
|
||||
extern int nc4_set_atomic_type_hdf5_info(NC_HDF5_FILE_INFO_T* h5, NC_TYPE_INFO_T* type_info);
|
||||
|
||||
#endif /* _NETCDF4_ */
|
@ -19,23 +19,16 @@ This is included in bottom
|
||||
of config.h. It is where,
|
||||
typically, alternatives to
|
||||
missing functions should be
|
||||
defined.
|
||||
defined and missing types defined.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
extern char* strdup(const char*);
|
||||
#endif
|
||||
|
||||
/* #if HAVE_BASETSD_H */
|
||||
/* #ifndef ssize_t */
|
||||
/* #ifndef SSIZE_T */
|
||||
/* #include <BaseTsd.h> */
|
||||
/* #endif */
|
||||
/* #define ssize_t SSIZE_T */
|
||||
/* #endif */
|
||||
/* #endif */
|
||||
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
#define ssize_t long
|
||||
#endif
|
||||
|
||||
/* handle null arguments */
|
||||
#ifndef nulldup
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
/* Given a filename, check its magic number */
|
||||
/* Change magic number size from 4 to 8 to be more precise for HDF5 */
|
||||
#define MAGIC_NUMBER_LEN 8
|
||||
#define MAGIC_NUMBER_LEN ((size_t)8)
|
||||
#define MAGIC_HDF5_FILE 1
|
||||
#define MAGIC_HDF4_FILE 2
|
||||
#define MAGIC_CDF1_FILE 1 /* std classic format */
|
||||
|
@ -7,23 +7,37 @@
|
||||
#define NCHASHMAP_H
|
||||
|
||||
/*
|
||||
Data is presumed to be an index into some other table
|
||||
Assume it can be compared using simple ==
|
||||
The key is some hash of some null terminated string.
|
||||
This hashmap is optimized to assume null-terminated strings as the
|
||||
key.
|
||||
|
||||
Data is presumed to be an index into some other table Assume it
|
||||
can be compared using simple == The key is some hash of some
|
||||
null terminated string.
|
||||
|
||||
One problem here is that we need to do a final equality check on
|
||||
the name string to avoid an accidental hash collision. It would
|
||||
be nice if we had a large enough hashkey that was known to have
|
||||
an extremely low probability of collisions so we could compare
|
||||
the hashkeys to determine exact match. A quick internet search
|
||||
indicates that this is rather more tricky than just using
|
||||
e.g. crc64 or such. Needs some thought.
|
||||
*/
|
||||
|
||||
/*! Hashmap-related structs.
|
||||
NOTES:
|
||||
1. 'data' is the dimid or varid which is non-negative.
|
||||
2. 'key' is a copy of the name (char*) of the corresponding object
|
||||
(e.g. dim or var)
|
||||
3. hashkey is a hash of key.
|
||||
1. 'data' is the an arbitrary uintptr_t integer or void* pointer.
|
||||
2. hashkey is a crc32 hash of key
|
||||
|
||||
WARNINGS:
|
||||
1. It is critical that |uintptr_t| == |void*|
|
||||
*/
|
||||
|
||||
typedef struct NC_hentry {
|
||||
int flags;
|
||||
void* data;
|
||||
size_t hashkey; /* Hash id */
|
||||
char* key; /* actual key; do not free */
|
||||
uintptr_t data;
|
||||
unsigned int hashkey; /* Hash id */
|
||||
size_t keysize;
|
||||
char* key; /* copy of the key string; kept as unsigned char */
|
||||
} NC_hentry;
|
||||
|
||||
/*
|
||||
@ -31,34 +45,40 @@ The hashmap object must give us the hash table (table),
|
||||
the |table| size, and the # of defined entries in the table
|
||||
*/
|
||||
typedef struct NC_hashmap {
|
||||
size_t size; /* allocated */
|
||||
size_t count;
|
||||
size_t alloc; /* allocated # of entries */
|
||||
size_t active; /* # of active entries */
|
||||
NC_hentry* table;
|
||||
} NC_hashmap;
|
||||
|
||||
/* defined in nc_hashmap.c */
|
||||
/* defined in nchashmap.c */
|
||||
|
||||
/*
|
||||
There are two "kinds" of functions:
|
||||
1. those that take the key+size -- they compute the hashkey internally.
|
||||
2. those that take the hashkey directly
|
||||
*/
|
||||
|
||||
/** Creates a new hashmap near the given size. */
|
||||
extern NC_hashmap* NC_hashmapnew(size_t startsize);
|
||||
|
||||
/** Inserts a new element into the hashmap. */
|
||||
/* Note we pass the NC_hobjecty struct by value */
|
||||
extern int NC_hashmapadd(NC_hashmap*, void* data, const char* name);
|
||||
/** Inserts a new element into the hashmap; takes key+size */
|
||||
/* key points to size bytes to convert to hash key */
|
||||
extern int NC_hashmapadd(NC_hashmap*, uintptr_t data, const char* key, size_t keysize);
|
||||
|
||||
/** Removes the storage for the element of the key.
|
||||
/** Removes the storage for the element of the key; takes key+size.
|
||||
Return 1 if found, 0 otherwise; returns the data in datap if !null
|
||||
*/
|
||||
extern int NC_hashmapremove(NC_hashmap*, const char* name, void** datap);
|
||||
extern int NC_hashmapremove(NC_hashmap*, const char* key, size_t keysize, uintptr_t* datap);
|
||||
|
||||
/** Returns the data for the key.
|
||||
/** Returns the data for the key; takes key+size.
|
||||
Return 1 if found, 0 otherwise; returns the data in datap if !null
|
||||
*/
|
||||
extern int NC_hashmapget(NC_hashmap*, const char*, void** datap);
|
||||
extern int NC_hashmapget(NC_hashmap*, const char* key, size_t keysize, uintptr_t* datap);
|
||||
|
||||
/** Change the data for the specified key
|
||||
/** Change the data for the specified key; takes hashkey.
|
||||
Return 1 if found, 0 otherwise
|
||||
*/
|
||||
extern int NC_hashmapsetdata(NC_hashmap*, const char*, void* newdata);
|
||||
extern int NC_hashmapsetdata(NC_hashmap*, const char* key, size_t keylen, uintptr_t newdata);
|
||||
|
||||
/** Returns the number of saved elements. */
|
||||
extern size_t NC_hashmapcount(NC_hashmap*);
|
||||
@ -66,5 +86,8 @@ extern size_t NC_hashmapcount(NC_hashmap*);
|
||||
/** Reclaims the hashmap structure. */
|
||||
extern int NC_hashmapfree(NC_hashmap*);
|
||||
|
||||
/* Return the hash key for specified key; takes key+size*/
|
||||
extern unsigned int NC_hashmapkey(const char* key, size_t size);
|
||||
|
||||
#endif /*NCHASHMAP_H*/
|
||||
|
||||
|
110
include/ncindex.h
Normal file
110
include/ncindex.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
|
||||
See LICENSE.txt for license information.
|
||||
*/
|
||||
|
||||
#ifndef NCINDEX_H
|
||||
#define NCINDEX_H
|
||||
|
||||
/* If defined, then the hashmap is used.
|
||||
This for performance experimentation
|
||||
*/
|
||||
#undef NCNOHASH
|
||||
|
||||
#undef NCINDEXDEBUG
|
||||
|
||||
#include "nclist.h"
|
||||
#include "nchashmap.h" /* Also includes name map and id map */
|
||||
|
||||
/* Forward (see nc4internal.h)*/
|
||||
struct NC_OBJ;
|
||||
|
||||
/*
|
||||
This index data structure is an ordered list of objects. It is
|
||||
used pervasively in libsrc4 to store metadata relationships.
|
||||
The goal is to provide by-name and i'th indexed access (via
|
||||
NClist) to the objects in the index. Using NCindex might be
|
||||
overkill for some relationships, but we can sort that out later.
|
||||
As a rule, we use this to store definitional relationships such
|
||||
as (in groups) dimension definitions, variable definitions, type
|
||||
defs and subgroup defs. We do not, as a rule, use this to store
|
||||
reference relationships such as the list of dimensions for a
|
||||
variable.
|
||||
|
||||
See docs/indexind.dox for more detailed documentation
|
||||
|
||||
*/
|
||||
|
||||
/* Generic list + matching hashtable */
|
||||
typedef struct NCindex {
|
||||
NClist* list;
|
||||
#ifndef NCNOHASH
|
||||
NC_hashmap* map;
|
||||
#endif
|
||||
} NCindex;
|
||||
|
||||
/* Locate object by name in an NCindex */
|
||||
extern struct NC_OBJ* ncindexlookup(NCindex* index, const char* name);
|
||||
|
||||
/* Get ith object in the index vector */
|
||||
extern struct NC_OBJ* ncindexith(NCindex* index, size_t i);
|
||||
|
||||
/* See if x is contained in the index and return its vector permission*/
|
||||
extern int ncindexfind(NCindex* index, struct NC_OBJ* o);
|
||||
|
||||
/* Add object to the end of the vector, also insert into the hashmaps; */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int ncindexadd(NCindex* index, struct NC_OBJ* obj);
|
||||
|
||||
/* Insert object at ith position of the vector, also insert into the hashmaps; */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int ncindexset(NCindex* index, size_t i, struct NC_OBJ* obj);
|
||||
|
||||
/* Get a copy of the vector contents */
|
||||
extern struct NC_OBJ** ncindexdup(NCindex* index);
|
||||
|
||||
/* Count the non-null entries in an NCindex */
|
||||
extern int ncindexcount(NCindex* index);
|
||||
|
||||
/* Rebuild index using all objects in the vector */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int ncindexrebuild(NCindex* index);
|
||||
|
||||
/* "Remove" ith object from the index;
|
||||
WARNING: Replaces it with NULL in the list.
|
||||
*/
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int ncindexidel(NCindex* index,size_t i);
|
||||
|
||||
/* Free an index. */
|
||||
/* Return 1 if ok; 0 otherwise */
|
||||
extern int ncindexfree(NCindex* index);
|
||||
|
||||
/* Create an index: size == 0 => use defaults */
|
||||
/* Return index if ok; NULL otherwise */
|
||||
extern NCindex* ncindexnew(size_t initsize);
|
||||
|
||||
extern int ncindexverify(NCindex* lm, int dump);
|
||||
|
||||
/* Lookup object in index; return NULL if not found */
|
||||
extern struct NC_OBJ* ncindexlookup(NCindex*, const char* name);
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
/* Test if index has been initialized */
|
||||
#define ncindexinitialized(index) ((index) != NULL && (index)->list != NULL)
|
||||
|
||||
/* Get number of entries in an index */
|
||||
#ifdef NCINDEXDEBUG
|
||||
static int ncindexsize(NCindex* index)
|
||||
{
|
||||
int i;
|
||||
if(index == NULL) return 0;
|
||||
i = nclistlength(index->list);
|
||||
return i;
|
||||
}
|
||||
#else
|
||||
#define ncindexsize(index) ((index)==NULL?0:(nclistlength((index)->list)))
|
||||
#endif
|
||||
|
||||
#endif /*ncindexH*/
|
@ -23,7 +23,7 @@ extern int nclistfreeall(NClist*);
|
||||
extern int nclistsetalloc(NClist*,size_t);
|
||||
extern int nclistsetlength(NClist*,size_t);
|
||||
|
||||
/* Set the ith element */
|
||||
/* Set the ith element; will overwrite previous contents; expand if needed */
|
||||
extern int nclistset(NClist*,size_t,void*);
|
||||
/* Get value at position i */
|
||||
extern void* nclistget(NClist*,size_t);/* Return the ith element of l */
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
|
||||
See LICENSE.txt for license information.
|
||||
*/
|
||||
|
||||
#ifndef NCLISTMAP_H
|
||||
#define NCLISTMAP_H
|
||||
|
||||
#include "nclist.h"
|
||||
#include "nchashmap.h"
|
||||
|
||||
/*
|
||||
This listmap datastructure is an ordered list of objects. It is
|
||||
used pervasively in libsrc to store metadata relationships. The
|
||||
goal is to provide both by-name (via nc_hashmap) and indexed
|
||||
access (via NClist) to the objects in the listmap. Using
|
||||
hashmap might be overkill for some relationships, but we can
|
||||
sort that out later.
|
||||
As a rule, we use this to store definitional relationships
|
||||
such as (in groups) dimension definitions, variable definitions, type defs
|
||||
and subgroup defs. We do not, as a rule, use this to store reference relationships
|
||||
such as the list of dimensions for a variable.
|
||||
*/
|
||||
|
||||
/* Generic list + matching hashtable */
|
||||
typedef struct NC_listmap {
|
||||
NClist* list;
|
||||
NC_hashmap* map;
|
||||
} NC_listmap;
|
||||
|
||||
/* Locate object by name in an NC_listmap */
|
||||
extern void* NC_listmap_get(NC_listmap* listmap, const char* name);
|
||||
|
||||
/* Locate object by index in an NC_listmap */
|
||||
extern void* NC_listmap_iget(NC_listmap* listmap, size_t index);
|
||||
|
||||
/* Get the index of an object; if not present, return 0
|
||||
(=> you have to do your own presence check to avoid ambiguity)
|
||||
*/
|
||||
extern size_t NC_listmap_index(NC_listmap* listmap, void* obj);
|
||||
|
||||
/* Add object to the end of an index; assume cast (char**)obj is defined */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int NC_listmap_add(NC_listmap* listmap, void* obj);
|
||||
|
||||
/* Remove object from listmap; assume cast (char**)target is defined */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int NC_listmap_del(NC_listmap* listmap, void* target);
|
||||
|
||||
/* Remove object from listmap by index; assume cast (char**)target is defined */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int NC_listmap_idel(NC_listmap* listmap, size_t index);
|
||||
|
||||
/* Rehash object after it has been given a new name */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int NC_listmap_move(NC_listmap* listmap, void* obj, const char* oldname);
|
||||
|
||||
/* Change data associated with a key */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
extern int NC_listmap_setdata(NC_listmap* listmap, void* obj, void* data);
|
||||
|
||||
/* Pseudo iterator; start index at 0, return 1 if more data, 0 if done.
|
||||
Usage:
|
||||
size_t iter;
|
||||
void* data;
|
||||
for(iter=0;NC_listmap_next(listmap,iter,&data);iter++) {f(data);}
|
||||
*/
|
||||
extern size_t NC_listmap_next(NC_listmap*, size_t iter, void** datap);
|
||||
|
||||
/* Reverse pseudo iterator; start index at 0, return 1 if more data, 0 if done.
|
||||
Differs from NC_listmap_next in that it iterates from last to first.
|
||||
This means that the iter value cannot be directly used as an index
|
||||
for e.g. NC_listmap_iget().
|
||||
Usage:
|
||||
size_t iter;
|
||||
void* data;
|
||||
for(iter=0;NC_listmap_prev(listmap,iter,&data);iter++) {f(data);}
|
||||
*/
|
||||
extern size_t NC_listmap_prev(NC_listmap* listmap, size_t iter, void** datap);
|
||||
|
||||
/* Reset a list map without free'ing the map itself */
|
||||
/* Return 1 if ok; 0 otherwise */
|
||||
extern int NC_listmap_clear(NC_listmap* listmap);
|
||||
|
||||
/* Initialize a list map without malloc'ing the map itself */
|
||||
/* Return 1 if ok; 0 otherwise */
|
||||
extern int NC_listmap_init(NC_listmap* listmap, size_t initsize);
|
||||
|
||||
extern int NC_listmap_verify(NC_listmap* lm, int dump);
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
/* Test if map has been initialized */
|
||||
#define NC_listmap_initialized(listmap) ((listmap)->list != NULL)
|
||||
|
||||
/* Get number of entries in a listmap */
|
||||
/* size_t NC_listmap_size(NC_listmap* listmap) */
|
||||
#define NC_listmap_size(listmap) ((listmap)==NULL?0:(nclistlength((listmap)->list)))
|
||||
|
||||
#endif /*NCLISTMAP_H*/
|
@ -1957,8 +1957,7 @@ ncrecget(int ncid, long recnum, void **datap);
|
||||
EXTERNL int
|
||||
ncrecput(int ncid, long recnum, void *const *datap);
|
||||
|
||||
EXTERNL int
|
||||
nc_finalize();
|
||||
EXTERNL int nc_finalize();
|
||||
|
||||
/* End v2.4 backward compatibility */
|
||||
#endif /*!NO_NETCDF_2*/
|
||||
|
@ -55,7 +55,7 @@ NCerror
|
||||
dapmapconstraints(DCEconstraint* constraint,
|
||||
CDFnode* root)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
NCerror ncstat = NC_NOERR;
|
||||
NClist* nodes = root->tree->nodes;
|
||||
NClist* dceprojections = constraint->projections;
|
||||
@ -86,7 +86,7 @@ NCerror
|
||||
dapqualifyconstraints(DCEconstraint* constraint)
|
||||
{
|
||||
NCerror ncstat = NC_NOERR;
|
||||
int i;
|
||||
size_t i;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"ncqualifyconstraints.before: %s\n",
|
||||
dumpconstraint(constraint));
|
||||
@ -137,7 +137,7 @@ fprintf(stderr,"%s\n",
|
||||
static NCerror
|
||||
qualifyprojectionsizes(DCEprojection* proj)
|
||||
{
|
||||
int i,j;
|
||||
size_t i,j;
|
||||
ASSERT(proj->discrim == CES_VAR);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"qualifyprojectionsizes.before: %s\n",
|
||||
@ -174,10 +174,9 @@ fprintf(stderr,"qualifyprojectionsizes.after: %s\n",
|
||||
static void
|
||||
completesegments(NClist* fullpath, NClist* segments)
|
||||
{
|
||||
int i,delta;
|
||||
size_t i,delta;
|
||||
/* add path nodes to segments to create full path */
|
||||
delta = (nclistlength(fullpath) - nclistlength(segments));
|
||||
ASSERT((delta >= 0));
|
||||
for(i=0;i<delta;i++) {
|
||||
DCEsegment* seg = (DCEsegment*)dcecreate(CES_SEGMENT);
|
||||
CDFnode* node = (CDFnode*)nclistget(fullpath,i);
|
||||
@ -232,7 +231,7 @@ Additional constraints (4/12/2010):
|
||||
static NCerror
|
||||
matchpartialname(NClist* nodes, NClist* segments, CDFnode** nodep)
|
||||
{
|
||||
int i,nsegs;
|
||||
size_t i,nsegs;
|
||||
NCerror ncstat = NC_NOERR;
|
||||
DCEsegment* lastseg = NULL;
|
||||
NClist* namematches = nclistnew();
|
||||
|
@ -505,7 +505,8 @@ movetor(NCDAPCOMMON* nccomm,
|
||||
if(xnode->etype == NC_STRING || xnode->etype == NC_URL) hasstringdim = 1;
|
||||
|
||||
/* Get the mode */
|
||||
mode = oc_data_mode(conn,currentcontent);
|
||||
ocstat = oc_data_mode(conn,currentcontent,&mode);
|
||||
if(ocstat != OC_NOERR) {THROWCHK(ocstat); goto done;}
|
||||
|
||||
#ifdef DEBUG2
|
||||
fprintf(stderr,"moveto: nctype=%d depth=%d dimindex=%d mode=%s",
|
||||
|
@ -1,4 +1,4 @@
|
||||
SET(libdispatch_SOURCES dparallel.c dcopy.c dfile.c ddim.c datt.c dattinq.c dattput.c dattget.c derror.c dvar.c dvarget.c dvarput.c dvarinq.c ddispatch.c nclog.c dstring.c dutf8.c dinternal.c doffsets.c ncuri.c nclist.c ncbytes.c nchashmap.c nctime.c nc.c nclistmgr.c utf8proc.h utf8proc.c dwinpath.c dutil.c drc.c dauth.c)
|
||||
SET(libdispatch_SOURCES dparallel.c dcopy.c dfile.c ddim.c datt.c dattinq.c dattput.c dattget.c derror.c dvar.c dvarget.c dvarput.c dvarinq.c ddispatch.c nclog.c dstring.c dutf8.c dinternal.c doffsets.c ncuri.c nclist.c ncbytes.c nchashmap.c nctime.c nc.c nclistmgr.c utf8proc.h utf8proc.c dwinpath.c dutil.c drc.c dauth.c crc32.c)
|
||||
|
||||
IF(USE_NETCDF4)
|
||||
SET(libdispatch_SOURCES ${libdispatch_SOURCES} dgroup.c dvlen.c dcompound.c dtype.c denum.c dopaque.c ncaux.c dfilter.c)
|
||||
|
@ -20,7 +20,8 @@ dattinq.c dattput.c dattget.c derror.c dvar.c dvarget.c dvarput.c \
|
||||
dvarinq.c dinternal.c ddispatch.c dutf8.c \
|
||||
nclog.c dstring.c \
|
||||
ncuri.c nclist.c ncbytes.c nchashmap.c nctime.c \
|
||||
nc.c nclistmgr.c drc.c dauth.c doffsets.c dwinpath.c dutil.c
|
||||
nc.c nclistmgr.c drc.c dauth.c doffsets.c dwinpath.c dutil.c \
|
||||
crc32.c crc32.h
|
||||
|
||||
# Add the utf8 codebase
|
||||
libdispatch_la_SOURCES += utf8proc.c utf8proc.h
|
||||
|
506
libdispatch/crc32.c
Normal file
506
libdispatch/crc32.c
Normal file
@ -0,0 +1,506 @@
|
||||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.2.11, January 15th, 2017
|
||||
|
||||
Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
The data format used by the zlib library is described by RFCs (Request for
|
||||
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
||||
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
|
||||
*/
|
||||
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/**
|
||||
Modified to make it standalone.
|
||||
Dennis Heimbigner
|
||||
UCAR
|
||||
*/
|
||||
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
||||
*/
|
||||
|
||||
/* Prototype for the crc32 function
|
||||
extern unsigned int NC_crc32(unsigned int crc, const unsigned char* buf, unsigned int len);
|
||||
*/
|
||||
|
||||
/* Define some of the macros used here */
|
||||
#define FAR
|
||||
#define ZEXPORT
|
||||
#define local static
|
||||
#define OF(x) x
|
||||
#define uLong unsigned long
|
||||
#define uInt unsigned int
|
||||
#define z_off64_t long long
|
||||
#define z_off_t long
|
||||
#define z_crc_t unsigned long
|
||||
#define z_size_t size_t
|
||||
#define Z_NULL NULL
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#if !defined(NOBYFOUR) && defined(Z_U4)
|
||||
# define BYFOUR
|
||||
#endif
|
||||
#ifdef BYFOUR
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, z_size_t));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, z_size_t));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local z_crc_t FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const z_crc_t FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
z_crc_t c;
|
||||
int n, k;
|
||||
z_crc_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (z_crc_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const z_crc_t FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const z_crc_t FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
|
||||
(unsigned long)(table[n]),
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const z_crc_t FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32_z(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
z_crc_t endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned int ZEXPORT NC_crc32(unsigned int crc, const unsigned char* buf, unsigned int len)
|
||||
{
|
||||
unsigned long value = (unsigned long)crc;
|
||||
value = crc32_z(value, buf, len);
|
||||
return (unsigned int)(value & 0xFFFFFFFF); /* in case |long| is 64 bits */
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/*
|
||||
This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
|
||||
integer pointer type. This violates the strict aliasing rule, where a
|
||||
compiler can assume, for optimization purposes, that two pointers to
|
||||
fundamentally different types won't ever point to the same memory. This can
|
||||
manifest as a problem only if one of the pointers is written to. This code
|
||||
only reads from those pointers. So long as this code remains isolated in
|
||||
this compilation unit, there won't be a problem. For this reason, this code
|
||||
should not be copied and pasted into a compilation unit in which other code
|
||||
writes to the buffer that is passed to these routines.
|
||||
*/
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = (z_crc_t)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *buf4++; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = ZSWAP32((z_crc_t)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(ZSWAP32(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong crc32_combine_(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
441
libdispatch/crc32.h
Normal file
441
libdispatch/crc32.h
Normal file
@ -0,0 +1,441 @@
|
||||
/* crc32.h -- tables for rapid CRC calculation
|
||||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const z_crc_t FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||
0x2d02ef8dUL
|
||||
#ifdef BYFOUR
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
|
||||
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
|
||||
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
|
||||
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
|
||||
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
|
||||
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
|
||||
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
|
||||
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
|
||||
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
|
||||
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
|
||||
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
|
||||
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
|
||||
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
|
||||
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
|
||||
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
|
||||
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
|
||||
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
|
||||
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
|
||||
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
|
||||
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
|
||||
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
|
||||
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
|
||||
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
|
||||
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
|
||||
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
|
||||
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
|
||||
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
|
||||
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
|
||||
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
|
||||
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
|
||||
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
|
||||
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
|
||||
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
|
||||
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
|
||||
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
|
||||
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
|
||||
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
|
||||
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
|
||||
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
|
||||
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
|
||||
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
|
||||
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
|
||||
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
|
||||
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
|
||||
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
|
||||
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
|
||||
0x9324fd72UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
|
||||
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
|
||||
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
|
||||
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
|
||||
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
|
||||
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
|
||||
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
|
||||
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
|
||||
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
|
||||
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
|
||||
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
|
||||
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
|
||||
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
|
||||
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
|
||||
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
|
||||
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
|
||||
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
|
||||
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
|
||||
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
|
||||
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
|
||||
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
|
||||
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
|
||||
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
|
||||
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
|
||||
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
|
||||
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
|
||||
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
|
||||
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
|
||||
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
|
||||
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
|
||||
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
|
||||
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
|
||||
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
|
||||
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
|
||||
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
|
||||
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
|
||||
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
|
||||
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
|
||||
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
|
||||
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
|
||||
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
|
||||
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
|
||||
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
|
||||
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
|
||||
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
|
||||
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
|
||||
0xbe9834edUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
|
||||
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
|
||||
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
|
||||
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
|
||||
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
|
||||
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
|
||||
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
|
||||
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
|
||||
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
|
||||
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
|
||||
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
|
||||
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
|
||||
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
|
||||
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
|
||||
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
|
||||
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
|
||||
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
|
||||
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
|
||||
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
|
||||
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
|
||||
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
|
||||
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
|
||||
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
|
||||
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
|
||||
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
|
||||
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
|
||||
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
|
||||
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
|
||||
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
|
||||
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
|
||||
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
|
||||
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
|
||||
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
|
||||
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
|
||||
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
|
||||
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
|
||||
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
|
||||
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
|
||||
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
|
||||
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
|
||||
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
|
||||
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
|
||||
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
|
||||
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
|
||||
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
|
||||
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
|
||||
0xde0506f1UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
|
||||
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
|
||||
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
|
||||
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
|
||||
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
|
||||
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
|
||||
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
|
||||
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
|
||||
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
|
||||
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
|
||||
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
|
||||
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
|
||||
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
|
||||
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
|
||||
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
|
||||
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
|
||||
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
|
||||
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
|
||||
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
|
||||
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
|
||||
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
|
||||
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
|
||||
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
|
||||
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
|
||||
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
|
||||
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
|
||||
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
|
||||
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
|
||||
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
|
||||
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
|
||||
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
|
||||
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
|
||||
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
|
||||
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
|
||||
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
|
||||
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
|
||||
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
|
||||
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
|
||||
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
|
||||
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
|
||||
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
|
||||
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
|
||||
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
|
||||
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
|
||||
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
|
||||
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
|
||||
0x8def022dUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
|
||||
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
|
||||
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
|
||||
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
|
||||
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
|
||||
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
|
||||
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
|
||||
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
|
||||
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
|
||||
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
|
||||
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
|
||||
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
|
||||
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
|
||||
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
|
||||
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
|
||||
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
|
||||
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
|
||||
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
|
||||
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
|
||||
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
|
||||
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
|
||||
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
|
||||
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
|
||||
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
|
||||
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
|
||||
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
|
||||
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
|
||||
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
|
||||
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
|
||||
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
|
||||
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
|
||||
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
|
||||
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
|
||||
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
|
||||
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
|
||||
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
|
||||
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
|
||||
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
|
||||
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
|
||||
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
|
||||
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
|
||||
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
|
||||
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
|
||||
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
|
||||
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
|
||||
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
|
||||
0x72fd2493UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
|
||||
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
|
||||
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
|
||||
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
|
||||
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
|
||||
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
|
||||
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
|
||||
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
|
||||
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
|
||||
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
|
||||
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
|
||||
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
|
||||
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
|
||||
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
|
||||
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
|
||||
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
|
||||
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
|
||||
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
|
||||
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
|
||||
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
|
||||
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
|
||||
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
|
||||
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
|
||||
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
|
||||
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
|
||||
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
|
||||
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
|
||||
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
|
||||
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
|
||||
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
|
||||
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
|
||||
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
|
||||
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
|
||||
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
|
||||
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
|
||||
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
|
||||
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
|
||||
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
|
||||
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
|
||||
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
|
||||
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
|
||||
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
|
||||
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
|
||||
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
|
||||
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
|
||||
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
|
||||
0xed3498beUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
|
||||
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
|
||||
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
|
||||
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
|
||||
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
|
||||
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
|
||||
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
|
||||
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
|
||||
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
|
||||
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
|
||||
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
|
||||
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
|
||||
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
|
||||
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
|
||||
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
|
||||
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
|
||||
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
|
||||
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
|
||||
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
|
||||
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
|
||||
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
|
||||
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
|
||||
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
|
||||
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
|
||||
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
|
||||
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
|
||||
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
|
||||
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
|
||||
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
|
||||
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
|
||||
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
|
||||
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
|
||||
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
|
||||
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
|
||||
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
|
||||
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
|
||||
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
|
||||
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
|
||||
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
|
||||
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
|
||||
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
|
||||
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
|
||||
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
|
||||
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
|
||||
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
|
||||
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
|
||||
0xf10605deUL
|
||||
#endif
|
||||
}
|
||||
};
|
@ -2281,12 +2281,12 @@ readmagic(struct MagicFile* file, long pos, char* magic)
|
||||
}
|
||||
#endif /* USE_PARALLEL */
|
||||
{
|
||||
size_t count;
|
||||
int count;
|
||||
int i = fseek(file->fp,pos,SEEK_SET);
|
||||
if(i < 0)
|
||||
{status = errno; goto done;}
|
||||
for(i=0;i<MAGIC_NUMBER_LEN;) {/* make sure to read proper # of bytes */
|
||||
count=fread(&magic[i],1,(MAGIC_NUMBER_LEN-i),file->fp);
|
||||
count=fread(&magic[i],1,(size_t)(MAGIC_NUMBER_LEN-i),file->fp);
|
||||
if(count == 0 || ferror(file->fp))
|
||||
{status = errno; goto done;}
|
||||
i += count;
|
||||
|
@ -426,7 +426,7 @@ NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim)
|
||||
* Find the length of a type. This is how much space is required by
|
||||
* the in memory to hold one element of this type.
|
||||
*
|
||||
* @parm type A netCDF atomic type.
|
||||
* @param type A netCDF atomic type.
|
||||
*
|
||||
* @return Length of the type in bytes, or -1 if type not found.
|
||||
* @author Ed Hartnett
|
||||
@ -1016,6 +1016,9 @@ same as the default endianness of the platform. But with
|
||||
nc_def_var_endianness the endianness can be explicitly set for a
|
||||
variable.
|
||||
|
||||
Warning: this function is only defined if the type of the variable
|
||||
is an atomic integer or float type.
|
||||
|
||||
This function may only be called after the variable is defined, but
|
||||
before nc_enddef is called.
|
||||
|
||||
|
@ -3,8 +3,6 @@ Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
|
||||
See LICENSE.txt for license information.
|
||||
*/
|
||||
|
||||
#define NEWHASHMAP
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -18,19 +16,50 @@ See LICENSE.txt for license information.
|
||||
#include "nchashmap.h"
|
||||
#include "nc3internal.h"
|
||||
|
||||
#define VERIFY
|
||||
#undef DEBUG
|
||||
#undef DEBUGTRACE
|
||||
#undef ASSERTIONS
|
||||
|
||||
#ifdef VERIFY
|
||||
/**
|
||||
@Internal
|
||||
|
||||
This hashmap is optimized to use counted strings as its
|
||||
key value. It is assumed in most cases that a string plus its
|
||||
length are passed in for doing lookups.
|
||||
|
||||
When an entry is added, a copy of the string is kept in the hash table
|
||||
entry. Since we also keep the hashkey, the probability is high that
|
||||
we will only do string comparisons when they will match.
|
||||
*/
|
||||
|
||||
/* Prototype for the crc32 function */
|
||||
extern unsigned int NC_crc32(unsigned int crc, const char* buf, unsigned int len);
|
||||
|
||||
#undef SMALLTABLE
|
||||
|
||||
#ifdef ASSERTIONS
|
||||
#define ASSERT(x) assert(x)
|
||||
#else
|
||||
#define ASSERT(x)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
#define TRACE(x) {fprintf(stderr,"NC_hashmap: %s\n",x); fflush(stderr);}
|
||||
#else
|
||||
#define TRACE(x)
|
||||
#endif
|
||||
|
||||
#define SEED 37
|
||||
|
||||
/* See lookup3.c */
|
||||
extern unsigned int hash_fast(const void* key, size_t length);
|
||||
extern unsigned int hash_fast(const char*, size_t length);
|
||||
|
||||
/* this should be prime */
|
||||
#define TABLE_STARTSIZE 1021
|
||||
#ifdef SMALLTABLE
|
||||
#define MINTABLESIZE 7U
|
||||
#else
|
||||
#define MINTABLESIZE 131U
|
||||
#endif
|
||||
|
||||
/* Flags must be powers of 2 */
|
||||
/* Slot has data */
|
||||
@ -47,64 +76,65 @@ static unsigned int NC_nprimes;
|
||||
static unsigned int NC_primes[16386];
|
||||
static unsigned int findPrimeGreaterThan(size_t val);
|
||||
|
||||
extern void printhashmapstats(NC_hashmap* hm);
|
||||
extern void printhashmap(NC_hashmap* hm);
|
||||
|
||||
static void
|
||||
rehash(NC_hashmap* hm)
|
||||
{
|
||||
size_t size = hm->size;
|
||||
size_t count = hm->count;
|
||||
size_t alloc = hm->alloc;
|
||||
#ifdef ASSERTIONS
|
||||
size_t active = hm->active;
|
||||
#endif
|
||||
NC_hentry* oldtable = hm->table;
|
||||
|
||||
hm->size = findPrimeGreaterThan(size<<1);
|
||||
hm->table = (NC_hentry*)calloc(sizeof(NC_hentry), hm->size);
|
||||
hm->count = 0;
|
||||
TRACE("rehash");
|
||||
|
||||
while(size > 0) {
|
||||
--size;
|
||||
if(oldtable[size].flags == ACTIVE) {
|
||||
void* data = oldtable[size].data;
|
||||
char* key = oldtable[size].key;
|
||||
NC_hashmapadd(hm, data, key);
|
||||
#ifdef VERIFY
|
||||
{ void* data2;
|
||||
ASSERT(NC_hashmapget(hm, key, &data2) == 1);
|
||||
ASSERT(data == data2);
|
||||
}
|
||||
#endif
|
||||
hm->alloc = findPrimeGreaterThan(alloc<<1);
|
||||
hm->table = (NC_hentry*)calloc(sizeof(NC_hentry), hm->alloc);
|
||||
hm->active = 0;
|
||||
|
||||
while(alloc > 0) {
|
||||
NC_hentry* h = &oldtable[--alloc];
|
||||
if(h->flags == ACTIVE) {
|
||||
NC_hashmapadd(hm, h->data, h->key, h->keysize);
|
||||
if(h->key) free(h->key);
|
||||
}
|
||||
}
|
||||
free(oldtable);
|
||||
ASSERT(count == hm->count);
|
||||
ASSERT(active == hm->active);
|
||||
}
|
||||
|
||||
/* Locate where given object is or should be placed in indexp.
|
||||
if fail to find spot return 0 else 1.
|
||||
If deletok then a deleted slot is ok to return;
|
||||
If hashkeyp is non-null, then return hashkey
|
||||
return invariant: return == 0 || *indexp is defined
|
||||
*/
|
||||
static int
|
||||
locate(NC_hashmap* hash, const char* key, size_t* indexp, size_t* hashkeyp, int deletedok)
|
||||
locate(NC_hashmap* hash, unsigned int hashkey, const char* key, size_t keysize, size_t* indexp, int deletedok)
|
||||
{
|
||||
size_t i;
|
||||
size_t keylen = strlen(key);
|
||||
size_t hashkey = hash_fast(key, keylen);
|
||||
size_t index = hashkey % hash->size;
|
||||
size_t index;
|
||||
size_t step = 1; /* simple linear probe */
|
||||
int deletefound = 0;
|
||||
size_t deletedindex = 0; /* first deleted entry encountered */
|
||||
|
||||
if(hashkeyp) *hashkeyp = hashkey;
|
||||
TRACE("locate");
|
||||
/* Compute starting point */
|
||||
index = (size_t)(hashkey % hash->alloc);
|
||||
|
||||
/* Search table using linear probing */
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
NC_hentry entry = hash->table[index];
|
||||
if(entry.flags & ACTIVE) {
|
||||
if(entry.hashkey == hashkey
|
||||
&& strncmp(key,entry.key,keylen)==0) {
|
||||
if(indexp) *indexp = index;
|
||||
return 1;
|
||||
for (i = 0; i < hash->alloc; i++) {
|
||||
NC_hentry* entry = &hash->table[index];
|
||||
if(entry->flags & ACTIVE) {
|
||||
if(indexp) *indexp = index; /* assume a match */
|
||||
if(entry->hashkey == hashkey && entry->keysize == keysize) {
|
||||
/* Check content */
|
||||
if(memcmp(entry->key,key,keysize)==0)
|
||||
return 1;
|
||||
}
|
||||
/* Keep looking */
|
||||
} else if(entry.flags & DELETED) {
|
||||
} else if(entry->flags & DELETED) {
|
||||
if(!deletefound) {/* save this position */
|
||||
deletefound = 1;
|
||||
deletedindex = index;
|
||||
@ -115,7 +145,7 @@ locate(NC_hashmap* hash, const char* key, size_t* indexp, size_t* hashkeyp, int
|
||||
return 1;
|
||||
}
|
||||
/* linear probe */
|
||||
index = (index + step) % hash->size;
|
||||
index = (index + step) % hash->alloc;
|
||||
}
|
||||
if(deletedok && deletefound) {
|
||||
if(indexp) *indexp = deletedindex;
|
||||
@ -124,47 +154,71 @@ locate(NC_hashmap* hash, const char* key, size_t* indexp, size_t* hashkeyp, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the hash key for specified key; takes key+size*/
|
||||
/* Wrapper for crc32 */
|
||||
unsigned int
|
||||
NC_hashmapkey(const char* key, size_t size)
|
||||
{
|
||||
return NC_crc32(0,(unsigned char*)key,(unsigned int)size);
|
||||
}
|
||||
|
||||
NC_hashmap*
|
||||
NC_hashmapnew(size_t startsize)
|
||||
{
|
||||
NC_hashmap* hm = (NC_hashmap*)malloc(sizeof(NC_hashmap));
|
||||
NC_hashmap* hm = NULL;
|
||||
|
||||
if(startsize == 0)
|
||||
startsize = TABLE_STARTSIZE;
|
||||
TRACE("NC_hashmapnew");
|
||||
|
||||
hm = (NC_hashmap*)malloc(sizeof(NC_hashmap));
|
||||
|
||||
if(startsize == 0 || startsize < MINTABLESIZE)
|
||||
startsize = MINTABLESIZE;
|
||||
else {
|
||||
startsize *= 4;
|
||||
startsize /= 3;
|
||||
startsize = findPrimeGreaterThan(startsize);
|
||||
}
|
||||
hm->table = (NC_hentry*)calloc(sizeof(NC_hentry), (size_t)startsize);
|
||||
hm->size = startsize;
|
||||
hm->count = 0;
|
||||
hm->alloc = startsize;
|
||||
hm->active = 0;
|
||||
return hm;
|
||||
}
|
||||
|
||||
int
|
||||
NC_hashmapadd(NC_hashmap* hash, void* data, const char* key)
|
||||
NC_hashmapadd(NC_hashmap* hash, uintptr_t data, const char* key, size_t keysize)
|
||||
{
|
||||
if(hash->size*3/4 <= hash->count)
|
||||
rehash(hash);
|
||||
unsigned int hashkey;
|
||||
|
||||
TRACE("NC_hashmapadd");
|
||||
|
||||
if(key == NULL || keysize == 0)
|
||||
return 0;
|
||||
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
|
||||
|
||||
if(hash->alloc*3/4 <= hash->active)
|
||||
rehash(hash);
|
||||
for(;;) {
|
||||
size_t index, hashkey;
|
||||
if(!locate(hash,key,&index,&hashkey,1)) {
|
||||
size_t index;
|
||||
if(!locate(hash,hashkey,key,keysize,&index,1)) {
|
||||
rehash(hash);
|
||||
continue; /* try on larger table */
|
||||
}
|
||||
NC_hentry* entry = &hash->table[index];
|
||||
if(entry->flags & ACTIVE) {
|
||||
/* key already exists in table => overwrite */
|
||||
/* key already exists in table => overwrite data */
|
||||
entry->data = data;
|
||||
return 1;
|
||||
} else { /* !ACTIVE || DELETED */
|
||||
entry->flags = ACTIVE;
|
||||
entry->data = data;
|
||||
entry->hashkey = hashkey;
|
||||
entry->key = (char*)key;
|
||||
++hash->count;
|
||||
entry->keysize = keysize;
|
||||
entry->key = malloc(keysize+1);
|
||||
if(entry->key == NULL)
|
||||
return 0;
|
||||
memcpy(entry->key,key,keysize);
|
||||
entry->key[keysize] = '\0'; /* ensure null terminated */
|
||||
++hash->active;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -172,35 +226,51 @@ NC_hashmapadd(NC_hashmap* hash, void* data, const char* key)
|
||||
}
|
||||
|
||||
int
|
||||
NC_hashmapremove(NC_hashmap* hash, const char* key, void** datap)
|
||||
NC_hashmapremove(NC_hashmap* hash, const char* key, size_t keysize, uintptr_t* datap)
|
||||
{
|
||||
unsigned int hashkey;
|
||||
size_t index;
|
||||
NC_hentry entry;
|
||||
if(!locate(hash,key,&index,NULL,0))
|
||||
return 0; /* not present */
|
||||
entry = hash->table[index];
|
||||
NC_hentry* h;
|
||||
|
||||
if(entry.flags & ACTIVE) { /* matching entry found */
|
||||
hash->table[index].flags = DELETED; /* also turn off ACTIVE */
|
||||
hash->table[index].key = NULL;
|
||||
--hash->count;
|
||||
if(datap) *datap = hash->table[index].data;
|
||||
TRACE("NC_hashmapremove");
|
||||
|
||||
if(key == NULL || keysize == 0)
|
||||
return 0;
|
||||
|
||||
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
|
||||
if(!locate(hash,hashkey,key,keysize,&index,0))
|
||||
return 0; /* not present */
|
||||
h = &hash->table[index];
|
||||
if(h->flags & ACTIVE) { /* matching entry found */
|
||||
h->flags = DELETED; /* also turn off ACTIVE */
|
||||
if(h->key) free(h->key);
|
||||
h->key = NULL;
|
||||
h->keysize = 0;
|
||||
--hash->active;
|
||||
if(datap) *datap = h->data;
|
||||
return 1;
|
||||
} else /* !ACTIVE && !DELETED => not in table*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NC_hashmapget(NC_hashmap* hash, const char* key, void** datap)
|
||||
NC_hashmapget(NC_hashmap* hash, const char* key, size_t keysize, uintptr_t* datap)
|
||||
{
|
||||
if(hash->count) {
|
||||
unsigned int hashkey;
|
||||
|
||||
TRACE("NC_hashmapget");
|
||||
|
||||
if(key == NULL || keysize == 0)
|
||||
return 0;
|
||||
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
|
||||
if(hash->active) {
|
||||
size_t index;
|
||||
NC_hentry entry;
|
||||
if(!locate(hash,key,&index,NULL,0))
|
||||
NC_hentry* h;
|
||||
if(!locate(hash,hashkey,key,keysize,&index,0))
|
||||
return 0; /* not present */
|
||||
entry = hash->table[index];
|
||||
if(entry.flags & ACTIVE) {
|
||||
if(datap) *datap = entry.data;
|
||||
h = &hash->table[index];
|
||||
if(h->flags & ACTIVE) {
|
||||
if(datap) *datap = h->data;
|
||||
return 1;
|
||||
} else /* Not found */
|
||||
return 0;
|
||||
@ -212,36 +282,79 @@ NC_hashmapget(NC_hashmap* hash, const char* key, void** datap)
|
||||
Return 1 if found, 0 otherwise
|
||||
*/
|
||||
int
|
||||
NC_hashmapsetdata(NC_hashmap* hash, const char* key, void* newdata)
|
||||
NC_hashmapsetdata(NC_hashmap* hash, const char* key, size_t keysize, uintptr_t newdata)
|
||||
{
|
||||
size_t index;
|
||||
NC_hentry* entry;
|
||||
if(hash == NULL || hash->count == 0 || key == NULL)
|
||||
NC_hentry* h;
|
||||
unsigned int hashkey;
|
||||
|
||||
TRACE("NC_hashmapsetdata");
|
||||
|
||||
if(key == NULL || keysize == 0)
|
||||
return 0;
|
||||
hashkey = NC_crc32(0,(unsigned char*)key,(unsigned int)keysize);
|
||||
if(hash == NULL || hash->active == 0)
|
||||
return 0; /* no such entry */
|
||||
if(!locate(hash,key,&index,NULL,0))
|
||||
if(!locate(hash,hashkey,key,keysize,&index,0))
|
||||
return 0; /* not present */
|
||||
entry = &hash->table[index];
|
||||
assert((entry->flags & ACTIVE) == ACTIVE);
|
||||
entry->data = newdata;
|
||||
h = &hash->table[index];
|
||||
assert((h->flags & ACTIVE) == ACTIVE);
|
||||
h->data = newdata;
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t
|
||||
NC_hashmapcount(NC_hashmap* hash)
|
||||
{
|
||||
return hash->count;
|
||||
TRACE("NC_hashmapcount");
|
||||
return hash->active;
|
||||
}
|
||||
|
||||
int
|
||||
NC_hashmapfree(NC_hashmap* hash)
|
||||
{
|
||||
TRACE("NC_hashmapfree");
|
||||
if(hash) {
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printhashmapstats(hash);
|
||||
#endif
|
||||
for(i=0;i<hash->alloc;i++) {
|
||||
NC_hentry* he = &hash->table[i];
|
||||
if((he->flags & ACTIVE) && he->key != NULL)
|
||||
free(he->key);
|
||||
}
|
||||
free(hash->table);
|
||||
free(hash);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Friend: ncindex.c
|
||||
Only used by ncindex.c.
|
||||
Allows a hack by ncindex.
|
||||
*/
|
||||
|
||||
int
|
||||
NC_hashmapdeactivate(NC_hashmap* map, uintptr_t data)
|
||||
{
|
||||
size_t i;
|
||||
NC_hentry* h;
|
||||
for(h=map->table,i=0;i<map->alloc;i++,h++) {
|
||||
if((h->flags & ACTIVE) && h->data == data) {
|
||||
h->flags = DELETED;
|
||||
if(h->key) free(h->key);
|
||||
h->key = NULL;
|
||||
h->keysize = 0;
|
||||
--map->active;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* Prime table */
|
||||
|
||||
@ -1929,20 +2042,33 @@ static unsigned int NC_nprimes = (sizeof(NC_primes) / sizeof(unsigned int));
|
||||
|
||||
/**************************************************/
|
||||
/* Debug support */
|
||||
void
|
||||
printhstring(NC_string* s)
|
||||
{
|
||||
size_t n;
|
||||
char ss[256];
|
||||
|
||||
n = (s == NULL?0:s->nchars);
|
||||
strcpy(ss,"NULL");
|
||||
if(s != NULL)
|
||||
strncpy(ss,s->cp,sizeof(ss)-1);
|
||||
ss[255] = '\0';
|
||||
if(n == 0 || n > 256)
|
||||
strcpy(ss,"<undefined>");
|
||||
fprintf(stderr,"%lx %ld |%s|\n",(unsigned long)s,(unsigned long)n,ss);
|
||||
void
|
||||
printhashmapstats(NC_hashmap* hm)
|
||||
{
|
||||
size_t n,i;
|
||||
size_t step = 1;
|
||||
size_t maxchain = 0;
|
||||
for(n=0;n<hm->alloc;n++) {
|
||||
size_t chainlen = 0;
|
||||
size_t index = n;
|
||||
/* Follow chain at this index */
|
||||
for(i=0;i<hm->alloc;i++) {
|
||||
NC_hentry* entry = &hm->table[index];
|
||||
switch (entry->flags) {
|
||||
case ACTIVE: chainlen++; break; /* Keep looking */
|
||||
case DELETED: chainlen++; break; /* Keep looking */
|
||||
default: /* empty slot, stop walking */
|
||||
if(chainlen > maxchain) maxchain = chainlen;
|
||||
goto next;
|
||||
}
|
||||
/* linear probe */
|
||||
index = (index + step) % hm->alloc;
|
||||
}
|
||||
next: continue;
|
||||
}
|
||||
fprintf(stderr,"hashmap: alloc=%lu active=%lu maxchain=%lu\n",
|
||||
(unsigned long)hm->alloc,(unsigned long)hm->active,(unsigned long)maxchain);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
@ -1950,32 +2076,32 @@ void
|
||||
printhashmap(NC_hashmap* hm)
|
||||
{
|
||||
size_t i;
|
||||
int running;
|
||||
|
||||
if(hm == NULL) {fprintf(stderr,"NULL"); fflush(stderr); return;}
|
||||
fprintf(stderr,"{size=%lu count=%lu table=0x%lx}\n",
|
||||
(unsigned long)hm->size,(unsigned long)hm->count,(unsigned long)((uintptr_t)hm->table));
|
||||
if(hm->size > 4000) {
|
||||
(unsigned long)hm->alloc,(unsigned long)hm->active,(unsigned long)((uintptr_t)hm->table));
|
||||
if(hm->alloc > 4000) {
|
||||
fprintf(stderr,"MALFORMED\n");
|
||||
return;
|
||||
}
|
||||
for(i=0;i<hm->size;i++) {
|
||||
running = 0;
|
||||
for(i=0;i<hm->alloc;i++) {
|
||||
NC_hentry e = hm->table[i];
|
||||
if(e.flags == ACTIVE && e.key == NULL) {
|
||||
fprintf(stderr,"[%ld] flags=ACTIVE hashkey=%lu data=%p key=NULL\n",
|
||||
(unsigned long)i,(unsigned long)e.hashkey,e.data);
|
||||
} else if(e.flags == ACTIVE && e.key != NULL) {
|
||||
char nm[64];
|
||||
int elided = 0;
|
||||
size_t len = strlen(e.key);
|
||||
if(len > 63) {elided = 1; len = 63;}
|
||||
memcpy(nm,e.key,len);
|
||||
nm[63] = '\0';
|
||||
fprintf(stderr,"[%ld] flags=ACTIVE hashkey=%lu data=%p key=0x%lx |%s|%s\n",
|
||||
(unsigned long)i, (unsigned long)e.hashkey, e.data,(unsigned long)((uintptr_t)nm),e.key,(elided?"...":""));
|
||||
if(e.flags == ACTIVE) {
|
||||
fprintf(stderr,"[%ld] flags=ACTIVE hashkey=%lu data=%p keysize=%u key=|%s|\n",
|
||||
(unsigned long)i,(unsigned long)e.hashkey,(void*)e.data,(unsigned)e.keysize,e.key);
|
||||
running = 0;
|
||||
} else if(e.flags == DELETED) {
|
||||
fprintf(stderr,"[%ld] flags=DELETED hashkey=%lu\n",
|
||||
(unsigned long)i,(unsigned long)e.hashkey);
|
||||
running = 0;
|
||||
} else {/*empty*/
|
||||
fprintf(stderr,"[%ld] flags=EMPTY\n",(unsigned long)i);
|
||||
if(running == 0)
|
||||
fprintf(stderr,"[%ld] flags=EMPTY\n",(unsigned long)i);
|
||||
else if(running == 1)
|
||||
fprintf(stderr,"...\n");
|
||||
running++;
|
||||
}
|
||||
}
|
||||
fflush(stderr);
|
||||
|
@ -43,13 +43,18 @@ close_hdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
|
||||
/* Delete all the list contents for vars, dims, and atts, in each
|
||||
* group. */
|
||||
if ((retval = nc4_rec_grp_del(&h5->root_grp, h5->root_grp)))
|
||||
if ((retval = nc4_rec_grp_del(h5->root_grp)))
|
||||
return retval;
|
||||
|
||||
/* Close hdf file. */
|
||||
if (SDend(h5->sdid))
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Misc. Cleanup */
|
||||
nclistfree(h5->alldims);
|
||||
nclistfree(h5->allgroups);
|
||||
nclistfree(h5->alltypes);
|
||||
|
||||
/* Free the nc4_info struct; above code should have reclaimed
|
||||
everything else */
|
||||
free(h5);
|
||||
@ -60,10 +65,10 @@ close_hdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
#define NUM_TYPES 12 /**< Number of netCDF atomic types. */
|
||||
|
||||
/** @internal NetCDF atomic type names. */
|
||||
static const char nc_type_name_g[NUM_TYPES][NC_MAX_NAME + 1] = {"char", "byte", "short",
|
||||
"int", "float", "double", "ubyte",
|
||||
"ushort", "uint", "int64",
|
||||
"uint64", "string"};
|
||||
static const char* nc_type_name_g[NUM_TYPES] = {"char", "byte", "short",
|
||||
"int", "float", "double", "ubyte",
|
||||
"ushort", "uint", "int64",
|
||||
"uint64", "string"};
|
||||
|
||||
/** @internal NetCDF atomic type sizes. */
|
||||
static const int nc_type_size_g[NUM_TYPES] = {sizeof(char), sizeof(char), sizeof(short),
|
||||
@ -112,9 +117,10 @@ HDF4_create(const char* path, int cmode, size_t initialsz, int basepe,
|
||||
*/
|
||||
static int
|
||||
get_netcdf_type_from_hdf4(NC_HDF5_FILE_INFO_T *h5, int32 hdf4_typeid,
|
||||
nc_type *xtype, NC_TYPE_INFO_T *type_info)
|
||||
nc_type* xtypep, NC_TYPE_INFO_T **typep)
|
||||
{
|
||||
int t = 0;
|
||||
nc_type xtype;
|
||||
|
||||
/* Added this variable in the course of fixing NCF-332.
|
||||
* Prior to the fix, all data types were assigned
|
||||
@ -123,107 +129,116 @@ get_netcdf_type_from_hdf4(NC_HDF5_FILE_INFO_T *h5, int32 hdf4_typeid,
|
||||
* I can hazard a guess or two.
|
||||
*/
|
||||
int endianness = NC_ENDIAN_BIG;
|
||||
assert(h5 && xtype);
|
||||
assert(h5);
|
||||
|
||||
switch(hdf4_typeid)
|
||||
{
|
||||
case DFNT_CHAR:
|
||||
*xtype = NC_CHAR;
|
||||
xtype = NC_CHAR;
|
||||
t = 0;
|
||||
break;
|
||||
case DFNT_UCHAR:
|
||||
case DFNT_UINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
break;
|
||||
case DFNT_LUINT8:
|
||||
*xtype = NC_UBYTE;
|
||||
xtype = NC_UBYTE;
|
||||
t = 6;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT8:
|
||||
*xtype = NC_BYTE;
|
||||
xtype = NC_BYTE;
|
||||
t = 1;
|
||||
break;
|
||||
case DFNT_LINT8:
|
||||
*xtype = NC_BYTE;
|
||||
xtype = NC_BYTE;
|
||||
t = 1;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT16:
|
||||
*xtype = NC_SHORT;
|
||||
xtype = NC_SHORT;
|
||||
t = 2;
|
||||
break;
|
||||
case DFNT_LINT16:
|
||||
*xtype = NC_SHORT;
|
||||
xtype = NC_SHORT;
|
||||
t = 2;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT16:
|
||||
*xtype = NC_USHORT;
|
||||
xtype = NC_USHORT;
|
||||
t = 7;
|
||||
break;
|
||||
case DFNT_LUINT16:
|
||||
*xtype = NC_USHORT;
|
||||
xtype = NC_USHORT;
|
||||
t = 7;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_INT32:
|
||||
*xtype = NC_INT;
|
||||
xtype = NC_INT;
|
||||
t = 3;
|
||||
break;
|
||||
case DFNT_LINT32:
|
||||
*xtype = NC_INT;
|
||||
xtype = NC_INT;
|
||||
t = 3;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_UINT32:
|
||||
*xtype = NC_UINT;
|
||||
xtype = NC_UINT;
|
||||
t = 8;
|
||||
break;
|
||||
case DFNT_LUINT32:
|
||||
*xtype = NC_UINT;
|
||||
xtype = NC_UINT;
|
||||
t = 8;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
break;
|
||||
case DFNT_LFLOAT32:
|
||||
*xtype = NC_FLOAT;
|
||||
xtype = NC_FLOAT;
|
||||
t = 4;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
case DFNT_FLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
break;
|
||||
case DFNT_LFLOAT64:
|
||||
*xtype = NC_DOUBLE;
|
||||
xtype = NC_DOUBLE;
|
||||
t = 5;
|
||||
endianness = NC_ENDIAN_LITTLE;
|
||||
break;
|
||||
default:
|
||||
*xtype = NC_NAT;
|
||||
if(xtypep) *xtypep = NC_NAT;
|
||||
return NC_EBADTYPID;
|
||||
}
|
||||
if(xtypep) *xtypep = xtype;
|
||||
|
||||
if (type_info)
|
||||
if (typep)
|
||||
{
|
||||
if (hdf4_typeid == DFNT_FLOAT32)
|
||||
type_info->nc_type_class = NC_FLOAT;
|
||||
else if (hdf4_typeid == DFNT_FLOAT64)
|
||||
type_info->nc_type_class = NC_DOUBLE;
|
||||
else if (hdf4_typeid == DFNT_CHAR)
|
||||
type_info->nc_type_class = NC_STRING;
|
||||
else
|
||||
type_info->nc_type_class = NC_INT;
|
||||
type_info->endianness = endianness;
|
||||
type_info->nc_typeid = *xtype;
|
||||
type_info->size = nc_type_size_g[t];
|
||||
if (!(type_info->name = strdup(nc_type_name_g[t])))
|
||||
NC_TYPE_INFO_T* type = NULL;
|
||||
|
||||
if (!(type = calloc(1, sizeof(NC_TYPE_INFO_T))))
|
||||
return NC_ENOMEM;
|
||||
type->hdr.sort = NCTYP;
|
||||
if (hdf4_typeid == DFNT_FLOAT32)
|
||||
type->nc_type_class = NC_FLOAT;
|
||||
else if (hdf4_typeid == DFNT_FLOAT64)
|
||||
type->nc_type_class = NC_DOUBLE;
|
||||
else if (hdf4_typeid == DFNT_CHAR)
|
||||
type->nc_type_class = NC_STRING;
|
||||
else
|
||||
type->nc_type_class = NC_INT;
|
||||
type->endianness = endianness;
|
||||
type->size = nc_type_size_g[t];
|
||||
type->hdr.id = xtype;
|
||||
type->hdr.name = strdup(nc_type_name_g[t]);
|
||||
if(type->hdr.name == NULL)
|
||||
return NC_ENOMEM;
|
||||
type->hdr.hashkey = NC_hashmapkey(type->hdr.name,strlen(type->hdr.name));
|
||||
if(typep) *typep = type;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
@ -245,11 +260,13 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_ATT_INFO_T *att;
|
||||
NC_VAR_INFO_T *var = NULL;
|
||||
int32 num_datasets, num_gatts;
|
||||
int32 rank;
|
||||
int v, d, a;
|
||||
int retval;
|
||||
int retval = NC_NOERR;
|
||||
NC_HDF5_FILE_INFO_T* nc4_info = NULL;
|
||||
int32 *dimsize = NULL;
|
||||
|
||||
LOG((3, "%s: path %s mode %d", __func__, path, mode));
|
||||
assert(path && nc);
|
||||
@ -281,25 +298,23 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&h5->root_grp->att, &att)))
|
||||
return retval;
|
||||
att->attnum = grp->natts++;
|
||||
att->created = NC_TRUE;
|
||||
char name[NC_MAX_HDF4_NAME+1];
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char))))
|
||||
return NC_ENOMEM;
|
||||
if (SDattrinfo(h5->sdid, a, att->name, &att_data_type, &att_count))
|
||||
if (SDattrinfo(h5->sdid, a, name, &att_data_type, &att_count))
|
||||
return NC_EATTMETA;
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL)))
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(h5->root_grp->att, name, &att)))
|
||||
return retval;
|
||||
att->created = NC_TRUE;
|
||||
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type, &att->nc_typeid, NULL)))
|
||||
return retval;
|
||||
att->len = att_count;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, &att_type_size)))
|
||||
return retval;
|
||||
if (!(att->data = malloc(att_type_size * att->len)))
|
||||
return NC_ENOMEM;
|
||||
@ -312,8 +327,9 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
/* Read each dataset. */
|
||||
for (v = 0; v < num_datasets; v++)
|
||||
{
|
||||
NC_VAR_INFO_T *var;
|
||||
int32 data_type, num_atts;
|
||||
int sdsid;
|
||||
|
||||
/* Problem: Number of dims is returned by the call that requires
|
||||
a pre-allocated array, 'dimsize'.
|
||||
From SDS_SD website:
|
||||
@ -322,75 +338,47 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
|
||||
int32 dimsize[MAX_VAR_DIMS];
|
||||
*/
|
||||
int32 *dimsize = NULL;
|
||||
size_t var_type_size;
|
||||
int a;
|
||||
|
||||
/* Add a variable. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
return retval;
|
||||
|
||||
var->varid = grp->nvars++;
|
||||
var->created = NC_TRUE;
|
||||
var->written_to = NC_TRUE;
|
||||
|
||||
/* Add a var to the variable array, growing it as needed. */
|
||||
if ((retval = nc4_vararray_add(grp, var)))
|
||||
return retval;
|
||||
char name[NC_MAX_HDF4_NAME+1];
|
||||
|
||||
/* Open this dataset in HDF4 file. */
|
||||
if ((var->sdsid = SDselect(h5->sdid, v)) == FAIL)
|
||||
return NC_EVARMETA;
|
||||
|
||||
/* Get shape, name, type, and attribute info about this dataset. */
|
||||
if (!(var->name = malloc(NC_MAX_HDF4_NAME + 1)))
|
||||
return NC_ENOMEM;
|
||||
if ((sdsid = SDselect(h5->sdid, v)) == FAIL)
|
||||
{retval = NC_EVARMETA; goto fail;}
|
||||
|
||||
/* Invoke SDgetInfo with null dimsize to get rank. */
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, NULL, &data_type, &num_atts))
|
||||
return NC_EVARMETA;
|
||||
|
||||
var->hash = hash_fast(var->name, strlen(var->name));
|
||||
if (SDgetinfo(sdsid, name, &rank, NULL, &data_type, &num_atts))
|
||||
{retval = NC_EVARMETA; goto fail;}
|
||||
|
||||
if(!(dimsize = (int32*)malloc(sizeof(int32)*rank)))
|
||||
return NC_ENOMEM;
|
||||
{retval = NC_ENOMEM; goto fail;}
|
||||
|
||||
if (SDgetinfo(var->sdsid, var->name, &rank, dimsize, &data_type, &num_atts)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EVARMETA;
|
||||
}
|
||||
if (SDgetinfo(sdsid, name, &rank, dimsize, &data_type, &num_atts))
|
||||
{retval = NC_EVARMETA; goto fail;}
|
||||
|
||||
var->ndims = rank;
|
||||
/* Add a variable. */
|
||||
if ((retval = nc4_var_list_add(grp,name,rank,&var)))
|
||||
return retval;
|
||||
var->created = NC_TRUE;
|
||||
var->written_to = NC_TRUE;
|
||||
var->hdf4_data_type = data_type;
|
||||
var->sdsid = sdsid;
|
||||
|
||||
/* Fill special type_info struct for variable type information. */
|
||||
if (!(var->type_info = calloc(1, sizeof(NC_TYPE_INFO_T)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, data_type, &var->type_info->nc_typeid, var->type_info))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, data_type, NULL, &var->type_info)))
|
||||
goto fail;
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->type_info->hdr.id, &var_type_size)))
|
||||
goto fail;
|
||||
|
||||
/* Indicate that the variable has a pointer to the type */
|
||||
var->type_info->rc++;
|
||||
|
||||
if ((retval = nc4_get_typelen_mem(h5, var->type_info->nc_typeid, 0, &var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
var->type_info->size = var_type_size;
|
||||
LOG((3, "reading HDF4 dataset %s, rank %d netCDF type %d", var->name,
|
||||
rank, var->type_info->nc_typeid));
|
||||
LOG((3, "reading HDF4 dataset %s, rank %d netCDF type %d", var->hdr.name,
|
||||
rank, var->type_info->hdr.id));
|
||||
|
||||
/* Get the fill value. */
|
||||
if (!(var->fill_value = malloc(var_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if (!(var->fill_value = malloc(var_type_size)))
|
||||
{retval = NC_ENOMEM; goto fail;}
|
||||
|
||||
if (SDgetfillvalue(var->sdsid, var->fill_value))
|
||||
{
|
||||
@ -402,63 +390,47 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
/* Allocate storage for dimension info in this variable. */
|
||||
if (var->ndims)
|
||||
{
|
||||
if (!(var->dim = malloc(sizeof(NC_DIM_INFO_T *) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
if (!(var->dimids = malloc(sizeof(int) * var->ndims))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if (!(var->dim = malloc(sizeof(NC_DIM_INFO_T *) * var->ndims)))
|
||||
{retval = NC_ENOMEM; goto fail;}
|
||||
if (!(var->dimids = malloc(sizeof(int) * var->ndims)))
|
||||
{retval = NC_ENOMEM; goto fail;}
|
||||
}
|
||||
|
||||
|
||||
/* Find its dimensions. */
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
int i;
|
||||
int32 dimid, dim_len, dim_data_type, dim_num_attrs;
|
||||
char dim_name[NC_MAX_NAME + 1];
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_DIM_INFO_T *dim = NULL;
|
||||
|
||||
if ((dimid = SDgetdimid(var->sdsid, d)) == FAIL) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
if (SDdiminfo(dimid, dim_name, &dim_len, &dim_data_type,
|
||||
&dim_num_attrs))
|
||||
{
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EDIMMETA;
|
||||
}
|
||||
if ((dimid = SDgetdimid(var->sdsid, d)) == FAIL)
|
||||
{retval = NC_EDIMMETA; goto fail;}
|
||||
if (SDdiminfo(dimid, dim_name, &dim_len, &dim_data_type, &dim_num_attrs))
|
||||
{retval = NC_EDIMMETA; goto fail;}
|
||||
if (strlen(dim_name) > NC_MAX_HDF4_NAME)
|
||||
{retval = NC_EMAXNAME; goto fail;}
|
||||
|
||||
/* Do we already have this dimension? HDF4 explicitly uses
|
||||
* the name to tell. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (!strcmp(dim->name, dim_name))
|
||||
for(i=0;i<ncindexsize(grp->dim);i++) {
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if (!strcmp(dim->hdr.name, dim_name))
|
||||
break;
|
||||
dim = NULL;
|
||||
}
|
||||
|
||||
/* If we didn't find this dimension, add one. */
|
||||
if (!dim)
|
||||
{
|
||||
LOG((4, "adding dimension %s for HDF4 dataset %s",
|
||||
dim_name, var->name));
|
||||
if ((retval = nc4_dim_list_add(&grp->dim, &dim)))
|
||||
dim_name, var->hdr.name));
|
||||
if ((retval = nc4_dim_list_add(grp, dim_name, (dim_len?dim_len:*dimsize), -1, &dim)))
|
||||
return retval;
|
||||
dim->dimid = grp->nc4_info->next_dimid++;
|
||||
if (strlen(dim_name) > NC_MAX_HDF4_NAME)
|
||||
return NC_EMAXNAME;
|
||||
if (!(dim->name = strdup(dim_name)))
|
||||
return NC_ENOMEM;
|
||||
if (dim_len)
|
||||
dim->len = dim_len;
|
||||
else
|
||||
dim->len = *dimsize;
|
||||
dim->hash = hash_fast(dim_name, strlen(dim_name));
|
||||
}
|
||||
|
||||
/* Tell the variable the id of this dimension. */
|
||||
var->dimids[d] = dim->dimid;
|
||||
var->dimids[d] = dim->hdr.id;
|
||||
var->dim[d] = dim;
|
||||
}
|
||||
|
||||
@ -467,49 +439,31 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
{
|
||||
int32 att_data_type, att_count;
|
||||
size_t att_type_size;
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&var->att, &att))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
att->attnum = var->natts++;
|
||||
att->created = NC_TRUE;
|
||||
char name[NC_MAX_HDF4_NAME+1];
|
||||
|
||||
/* Learn about this attribute. */
|
||||
if (!(att->name = malloc(NC_MAX_HDF4_NAME * sizeof(char)))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if (SDattrinfo(var->sdsid, a, att->name, &att_data_type, &att_count)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EATTMETA;
|
||||
}
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type,
|
||||
&att->nc_typeid, NULL))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (SDattrinfo(var->sdsid, a, name, &att_data_type, &att_count))
|
||||
{retval = NC_EATTMETA; goto fail;}
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(var->att, name, &att)))
|
||||
goto fail;
|
||||
att->created = NC_TRUE;
|
||||
att->len = att_count;
|
||||
|
||||
if ((retval = get_netcdf_type_from_hdf4(h5, att_data_type, &att->nc_typeid, NULL)))
|
||||
goto fail;
|
||||
|
||||
/* Allocate memory to hold the data. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, 0, &att_type_size))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return retval;
|
||||
}
|
||||
if (!(att->data = malloc(att_type_size * att->len))) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
if ((retval = nc4_get_typelen_mem(h5, att->nc_typeid, &att_type_size)))
|
||||
goto fail;
|
||||
if (!(att->data = malloc(att_type_size * att->len)))
|
||||
{retval = NC_ENOMEM; goto fail;}
|
||||
|
||||
/* Read the data. */
|
||||
if (SDreadattr(var->sdsid, a, att->data)) {
|
||||
if(dimsize) free(dimsize);
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
if (SDreadattr(var->sdsid, a, att->data))
|
||||
{retval = NC_EHDFERR; goto fail;}
|
||||
}
|
||||
if(dimsize) free(dimsize);
|
||||
if(dimsize) {free(dimsize); dimsize = NULL;}
|
||||
|
||||
{
|
||||
/* HDF4 files can be chunked */
|
||||
@ -528,7 +482,6 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* next var */
|
||||
|
||||
#ifdef LOGGING
|
||||
@ -536,7 +489,12 @@ nc4_open_hdf4_file(const char *path, int mode, NC *nc)
|
||||
atts in the file, if the logging level is 2 or greater. */
|
||||
log_metadata_nc(h5->root_grp->nc4_info->controller);
|
||||
#endif
|
||||
return NC_NOERR;
|
||||
return retval;
|
||||
|
||||
fail:
|
||||
if(dimsize) free(dimsize);
|
||||
if(var) nc4_var_list_del(grp,var);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -711,3 +669,4 @@ HDF4_close(int ncid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -309,7 +309,7 @@ nc4_get_hdf4_vara(NC *nc, int ncid, int varid, const size_t *startp,
|
||||
if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))
|
||||
return retval;
|
||||
h5 = NC4_DATA(nc);
|
||||
assert(grp && h5 && var && var->name);
|
||||
assert(grp && h5 && var && var->hdr.name);
|
||||
|
||||
for (d = 0; d < var->ndims; d++)
|
||||
{
|
||||
|
@ -62,12 +62,8 @@ endif # ENABLE_DAP4
|
||||
if USE_NETCDF4
|
||||
|
||||
AM_CPPFLAGS += -I${top_srcdir}/libsrc4
|
||||
|
||||
libnetcdf_la_LIBADD += ${top_builddir}/libsrc4/libnetcdf4.la
|
||||
|
||||
# Not ready for prime time yet
|
||||
# libnetcdf_la_LIBADD += ${top_builddir}/libdiskless/libdiskless.la
|
||||
|
||||
endif #USE_NETCDF4
|
||||
|
||||
if ISCYGWIN
|
||||
|
@ -10,7 +10,7 @@ foreach (f ${m4_SOURCES})
|
||||
endforeach(f)
|
||||
|
||||
SET(libsrc_SOURCES v1hpg.c putget.c attr.c nc3dispatch.c
|
||||
nc3internal.c var.c dim.c ncx.c lookup3.c ncio.c nc_hashmap.c)
|
||||
nc3internal.c var.c dim.c ncx.c lookup3.c ncio.c)
|
||||
|
||||
SET(libsrc_SOURCES ${libsrc_SOURCES} pstdint.h ncio.h ncx.h)
|
||||
|
||||
|
@ -10,7 +10,7 @@ libnetcdf3_la_CPPFLAGS = ${AM_CPPFLAGS}
|
||||
|
||||
# These files comprise the netCDF-3 classic library code.
|
||||
libnetcdf3_la_SOURCES = v1hpg.c \
|
||||
putget.c attr.c nc3dispatch.c nc3internal.c var.c dim.c ncx.c nc_hashmap.c \
|
||||
putget.c attr.c nc3dispatch.c nc3internal.c var.c dim.c ncx.c \
|
||||
ncx.h lookup3.c pstdint.h ncio.c ncio.h
|
||||
|
||||
if BUILD_DISKLESS
|
||||
|
142
libsrc/attr.m4
142
libsrc/attr.m4
@ -118,29 +118,29 @@ new_NC_attr(
|
||||
nc_type type,
|
||||
size_t nelems)
|
||||
{
|
||||
NC_string *strp;
|
||||
NC_attr *attrp;
|
||||
char *name;
|
||||
int stat;
|
||||
NC_string *strp = NULL;
|
||||
NC_attr *attrp = NULL;
|
||||
char *name = NULL;
|
||||
int stat = NC_NOERR;
|
||||
|
||||
stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return NULL;
|
||||
goto done;
|
||||
assert(name != NULL && *name != 0);
|
||||
|
||||
strp = new_NC_string(strlen(name), name);
|
||||
free(name);
|
||||
if(strp == NULL)
|
||||
return NULL;
|
||||
goto done;
|
||||
|
||||
attrp = new_x_NC_attr(strp, type, nelems);
|
||||
if(attrp == NULL)
|
||||
{
|
||||
free_NC_string(strp);
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return(attrp);
|
||||
done:
|
||||
if(name) free(name);
|
||||
return (attrp);
|
||||
}
|
||||
|
||||
|
||||
@ -151,8 +151,8 @@ dup_NC_attr(const NC_attr *rattrp)
|
||||
rattrp->type, rattrp->nelems);
|
||||
if(attrp == NULL)
|
||||
return NULL;
|
||||
if(attrp->xvalue != NULL && rattrp->xvalue != NULL)
|
||||
(void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
|
||||
if(attrp->xvalue != NULL && rattrp->xvalue != NULL)
|
||||
(void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
|
||||
return attrp;
|
||||
}
|
||||
|
||||
@ -345,36 +345,34 @@ NC_attrarray0(NC3_INFO* ncp, int varid)
|
||||
NC_attr **
|
||||
NC_findattr(const NC_attrarray *ncap, const char *uname)
|
||||
{
|
||||
NC_attr **attrpp;
|
||||
NC_attr **attrpp = NULL;
|
||||
size_t attrid;
|
||||
size_t slen;
|
||||
char *name;
|
||||
int stat;
|
||||
char *name = NULL;
|
||||
int stat = NC_NOERR;
|
||||
|
||||
assert(ncap != NULL);
|
||||
|
||||
if(ncap->nelems == 0)
|
||||
return NULL;
|
||||
|
||||
attrpp = (NC_attr **) ncap->value;
|
||||
goto done;
|
||||
|
||||
/* normalized version of uname */
|
||||
stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return NULL; /* TODO: need better way to indicate no memory */
|
||||
goto done; /* TODO: need better way to indicate no memory */
|
||||
slen = strlen(name);
|
||||
|
||||
attrpp = (NC_attr **) ncap->value;
|
||||
for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
|
||||
{
|
||||
if(strlen((*attrpp)->name->cp) == slen &&
|
||||
strncmp((*attrpp)->name->cp, name, slen) == 0)
|
||||
{
|
||||
free(name);
|
||||
return(attrpp); /* Normal return */
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
free(name);
|
||||
return(NULL);
|
||||
attrpp = NULL; /* not found */
|
||||
done:
|
||||
if(name) free(name);
|
||||
return (attrpp); /* Normal return */
|
||||
}
|
||||
|
||||
|
||||
@ -501,71 +499,65 @@ NC3_inq_att(int ncid,
|
||||
int
|
||||
NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
|
||||
{
|
||||
int status;
|
||||
NC *nc;
|
||||
NC3_INFO* ncp;
|
||||
NC_attrarray *ncap;
|
||||
NC_attr **tmp;
|
||||
NC_attr *attrp;
|
||||
int status = NC_NOERR;
|
||||
NC *nc = NULL;
|
||||
NC3_INFO* ncp = NULL;
|
||||
NC_attrarray *ncap = NULL;
|
||||
NC_attr **tmp = NULL;
|
||||
NC_attr *attrp = NULL;
|
||||
NC_string *newStr, *old;
|
||||
char *newname; /* normalized version */
|
||||
char *newname = NULL; /* normalized version */
|
||||
|
||||
/* start sortof inline clone of NC_lookupattr() */
|
||||
|
||||
/* sortof inline clone of NC_lookupattr() */
|
||||
status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
ncp = NC3_DATA(nc);
|
||||
|
||||
if(NC_readonly(ncp))
|
||||
return NC_EPERM;
|
||||
{status = NC_EPERM; goto done;}
|
||||
|
||||
ncap = NC_attrarray0(ncp, varid);
|
||||
if(ncap == NULL)
|
||||
return NC_ENOTVAR;
|
||||
{status = NC_ENOTVAR; goto done;}
|
||||
|
||||
status = NC_check_name(unewname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
tmp = NC_findattr(ncap, name);
|
||||
if(tmp == NULL)
|
||||
return NC_ENOTATT;
|
||||
{status = NC_ENOTATT; goto done;}
|
||||
attrp = *tmp;
|
||||
/* end inline clone NC_lookupattr() */
|
||||
/* end inline clone NC_lookupattr() */
|
||||
|
||||
if(NC_findattr(ncap, unewname) != NULL)
|
||||
{
|
||||
/* name in use */
|
||||
return NC_ENAMEINUSE;
|
||||
}
|
||||
{status = NC_ENAMEINUSE; goto done;} /* name in use */
|
||||
|
||||
old = attrp->name;
|
||||
status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char**)&newname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
if(NC_indef(ncp))
|
||||
{
|
||||
newStr = new_NC_string(strlen(newname), newname);
|
||||
free(newname);
|
||||
if( newStr == NULL)
|
||||
return NC_ENOMEM;
|
||||
{status = NC_ENOMEM; goto done;}
|
||||
attrp->name = newStr;
|
||||
free_NC_string(old);
|
||||
return NC_NOERR;
|
||||
goto done;
|
||||
}
|
||||
/* else not in define mode */
|
||||
|
||||
/* If new name is longer than old, then complain,
|
||||
but otherwise, no change (test is same as set_NC_string)*/
|
||||
if(old->nchars < strlen(newname)) {
|
||||
free(newname);
|
||||
return NC_ENOTINDEFINE;
|
||||
}
|
||||
if(old->nchars < strlen(newname))
|
||||
{status = NC_ENOTINDEFINE; goto done;}
|
||||
|
||||
status = set_NC_string(old, newname);
|
||||
free(newname);
|
||||
if( status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
set_NC_hdirty(ncp);
|
||||
|
||||
@ -573,43 +565,43 @@ NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
|
||||
{
|
||||
status = NC_sync(ncp);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
done:
|
||||
if(newname) free(newname);
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
NC3_del_att(int ncid, int varid, const char *uname)
|
||||
{
|
||||
int status;
|
||||
NC *nc;
|
||||
NC3_INFO* ncp;
|
||||
NC_attrarray *ncap;
|
||||
NC_attr **attrpp;
|
||||
int status = NC_NOERR;
|
||||
NC *nc = NULL;
|
||||
NC3_INFO* ncp = NULL;
|
||||
NC_attrarray *ncap = NULL;
|
||||
NC_attr **attrpp = NULL;
|
||||
NC_attr *old = NULL;
|
||||
int attrid;
|
||||
size_t slen;
|
||||
char* name = NULL;
|
||||
|
||||
status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
ncp = NC3_DATA(nc);
|
||||
|
||||
if(!NC_indef(ncp))
|
||||
return NC_ENOTINDEFINE;
|
||||
{status = NC_ENOTINDEFINE; goto done;}
|
||||
|
||||
ncap = NC_attrarray0(ncp, varid);
|
||||
if(ncap == NULL)
|
||||
return NC_ENOTVAR;
|
||||
{status = NC_ENOTVAR; goto done;}
|
||||
|
||||
{
|
||||
char* name;
|
||||
int stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return stat;
|
||||
status = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
|
||||
if(status != NC_NOERR)
|
||||
goto done;
|
||||
|
||||
/* sortof inline NC_findattr() */
|
||||
/* start sortof inline NC_findattr() */
|
||||
slen = strlen(name);
|
||||
|
||||
attrpp = (NC_attr **) ncap->value;
|
||||
@ -622,11 +614,9 @@ NC3_del_att(int ncid, int varid, const char *uname)
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
if( (size_t) attrid == ncap->nelems )
|
||||
return NC_ENOTATT;
|
||||
/* end inline NC_findattr() */
|
||||
{status = NC_ENOTATT; goto done;}
|
||||
/* end inline NC_findattr() */
|
||||
|
||||
/* shuffle down */
|
||||
for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
|
||||
@ -640,7 +630,9 @@ NC3_del_att(int ncid, int varid, const char *uname)
|
||||
|
||||
free_NC_attr(old);
|
||||
|
||||
return NC_NOERR;
|
||||
done:
|
||||
if(name) free(name);
|
||||
return status;
|
||||
}
|
||||
|
||||
dnl
|
||||
|
115
libsrc/dim.c
115
libsrc/dim.c
@ -55,28 +55,29 @@ static NC_dim *
|
||||
new_NC_dim(const char *uname, size_t size)
|
||||
{
|
||||
NC_string *strp;
|
||||
NC_dim *dimp;
|
||||
int stat;
|
||||
char* name;
|
||||
NC_dim *dimp = NULL;
|
||||
int stat = NC_NOERR;
|
||||
char* name = NULL;
|
||||
|
||||
stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return NULL;
|
||||
goto done;
|
||||
strp = new_NC_string(strlen(name), name);
|
||||
free(name);
|
||||
if(strp == NULL)
|
||||
return NULL;
|
||||
{stat = NC_ENOMEM; goto done;}
|
||||
|
||||
dimp = new_x_NC_dim(strp);
|
||||
if(dimp == NULL)
|
||||
{
|
||||
free_NC_string(strp);
|
||||
return NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dimp->size = size;
|
||||
|
||||
return(dimp);
|
||||
done:
|
||||
if(name) free(name);
|
||||
return (dimp);
|
||||
}
|
||||
|
||||
|
||||
@ -119,7 +120,6 @@ find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Step thru NC_DIMENSION array, seeking match on uname.
|
||||
* Return dimid or -1 on not found.
|
||||
@ -130,32 +130,24 @@ find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
|
||||
static int
|
||||
NC_finddim(const NC_dimarray *ncap, const char *uname, NC_dim **dimpp)
|
||||
{
|
||||
|
||||
int dimid;
|
||||
char *name;
|
||||
int dimid = -1;
|
||||
char *name = NULL;
|
||||
uintptr_t data;
|
||||
|
||||
assert(ncap != NULL);
|
||||
|
||||
if(ncap->nelems == 0)
|
||||
return -1;
|
||||
goto done;
|
||||
/* normalized version of uname */
|
||||
if(nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name))
|
||||
goto done;
|
||||
if(NC_hashmapget(ncap->hashmap, name, strlen(name), &data) == 0)
|
||||
goto done;
|
||||
dimid = (int)data;
|
||||
if(dimpp) *dimpp = ncap->value[dimid];
|
||||
|
||||
{
|
||||
int stat;
|
||||
dimid = 0;
|
||||
|
||||
/* normalized version of uname */
|
||||
stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return stat;
|
||||
dimid = (int)NC_hashmapGetDim(ncap, name);
|
||||
free(name);
|
||||
if (dimid >= 0) {
|
||||
if (dimpp != NULL)
|
||||
*dimpp = ncap->value[dimid];
|
||||
}
|
||||
return(dimid); /* Normal return */
|
||||
}
|
||||
return -1;
|
||||
done:
|
||||
if(name) free(name);
|
||||
return dimid;
|
||||
}
|
||||
|
||||
|
||||
@ -202,7 +194,7 @@ free_NC_dimarrayV(NC_dimarray *ncap)
|
||||
if(ncap->nalloc == 0)
|
||||
return;
|
||||
|
||||
NC_hashmapDelete(ncap->hashmap);
|
||||
NC_hashmapfree(ncap->hashmap);
|
||||
ncap->hashmap = NULL;
|
||||
|
||||
assert(ncap->value != NULL);
|
||||
@ -281,7 +273,7 @@ incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
|
||||
return NC_ENOMEM;
|
||||
ncap->value = vp;
|
||||
ncap->nalloc = NC_ARRAY_GROWBY;
|
||||
ncap->hashmap = NC_hashmapCreate(0);
|
||||
ncap->hashmap = NC_hashmapnew(0);
|
||||
}
|
||||
else if(ncap->nelems +1 > ncap->nalloc)
|
||||
{
|
||||
@ -295,9 +287,10 @@ incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
|
||||
|
||||
if(newelemp != NULL)
|
||||
{
|
||||
NC_hashmapAddDim(ncap, (long)ncap->nelems, newelemp->name->cp);
|
||||
ncap->value[ncap->nelems] = newelemp;
|
||||
ncap->nelems++;
|
||||
uintptr_t intdata = ncap->nelems;
|
||||
NC_hashmapadd(ncap->hashmap, intdata, newelemp->name->cp, strlen(newelemp->name->cp));
|
||||
ncap->value[ncap->nelems] = newelemp;
|
||||
ncap->nelems++;
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -440,69 +433,75 @@ NC3_inq_dim(int ncid, int dimid, char *name, size_t *sizep)
|
||||
int
|
||||
NC3_rename_dim( int ncid, int dimid, const char *unewname)
|
||||
{
|
||||
int status;
|
||||
int status = NC_NOERR;
|
||||
NC *nc;
|
||||
NC3_INFO* ncp;
|
||||
int existid;
|
||||
NC_dim *dimp;
|
||||
char *newname; /* normalized */
|
||||
char *newname = NULL; /* normalized */
|
||||
NC_string *old = NULL;
|
||||
uintptr_t intdata;
|
||||
|
||||
|
||||
status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
ncp = NC3_DATA(nc);
|
||||
|
||||
if(NC_readonly(ncp))
|
||||
return NC_EPERM;
|
||||
{status = NC_EPERM; goto done;}
|
||||
|
||||
status = NC_check_name(unewname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
existid = NC_finddim(&ncp->dims, unewname, &dimp);
|
||||
if(existid != -1)
|
||||
return NC_ENAMEINUSE;
|
||||
{status = NC_ENAMEINUSE; goto done;}
|
||||
|
||||
dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
|
||||
if(dimp == NULL)
|
||||
return NC_EBADDIM;
|
||||
{status = NC_EBADDIM; goto done;}
|
||||
|
||||
old = dimp->name;
|
||||
status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char **)&newname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
if(NC_indef(ncp))
|
||||
{
|
||||
NC_string *newStr = new_NC_string(strlen(newname), newname);
|
||||
free(newname);
|
||||
if(newStr == NULL)
|
||||
return NC_ENOMEM;
|
||||
{status = NC_ENOMEM; goto done;}
|
||||
|
||||
/* Remove old name from hashmap; add new... */
|
||||
NC_hashmapRemoveDim(&ncp->dims, old->cp);
|
||||
|
||||
NC_hashmapremove(ncp->dims.hashmap, old->cp, strlen(old->cp), NULL);
|
||||
dimp->name = newStr;
|
||||
|
||||
NC_hashmapAddDim(&ncp->dims, dimid, newStr->cp);
|
||||
intdata = dimid;
|
||||
NC_hashmapadd(ncp->dims.hashmap, intdata, newStr->cp, strlen(newStr->cp));
|
||||
free_NC_string(old);
|
||||
|
||||
return NC_NOERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* else, not in define mode */
|
||||
|
||||
/* If new name is longer than old, then complain,
|
||||
but otherwise, no change (test is same as set_NC_string)*/
|
||||
if(dimp->name->nchars < strlen(newname)) {
|
||||
{status = NC_ENOTINDEFINE; goto done;}
|
||||
}
|
||||
|
||||
/* Remove old name from hashmap; add new... */
|
||||
NC_hashmapRemoveDim(&ncp->dims, old->cp);
|
||||
/* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */
|
||||
NC_hashmapremove(ncp->dims.hashmap, old->cp, strlen(old->cp), NULL);
|
||||
|
||||
/* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */
|
||||
status = set_NC_string(dimp->name, newname);
|
||||
free(newname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
NC_hashmapAddDim(&ncp->dims, dimid, dimp->name->cp);
|
||||
intdata = (uintptr_t)dimid;
|
||||
NC_hashmapadd(ncp->dims.hashmap, intdata, dimp->name->cp, strlen(dimp->name->cp));
|
||||
|
||||
set_NC_hdirty(ncp);
|
||||
|
||||
@ -510,8 +509,10 @@ NC3_rename_dim( int ncid, int dimid, const char *unewname)
|
||||
{
|
||||
status = NC_sync(ncp);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
done:
|
||||
if(newname) free(newname);
|
||||
return status;
|
||||
}
|
||||
|
@ -36,10 +36,6 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
@ -180,7 +176,7 @@ static int memio_new(const char* path, int ioflags, off_t initialsize, void* mem
|
||||
memio->memory = memory;
|
||||
} else {
|
||||
/* malloc memory */
|
||||
memio->memory = (char*)malloc(memio->alloc);
|
||||
memio->memory = (char*)malloc((size_t)memio->alloc);
|
||||
if(memio->memory == NULL) {status = NC_ENOMEM; goto fail;}
|
||||
}
|
||||
|
||||
@ -227,7 +223,7 @@ memio_create(const char* path, int ioflags,
|
||||
if(path == NULL ||* path == 0)
|
||||
return NC_EINVAL;
|
||||
|
||||
status = memio_new(path, ioflags, initialsz, NULL, &nciop, &memio);
|
||||
status = memio_new(path, ioflags, (off_t)initialsz, NULL, &nciop, &memio);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
|
||||
@ -270,7 +266,7 @@ fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->m
|
||||
}
|
||||
|
||||
/* Pick a default sizehint */
|
||||
if(sizehintp) *sizehintp = pagesize;
|
||||
if(sizehintp) *sizehintp = (size_t)pagesize;
|
||||
|
||||
*nciopp = nciop;
|
||||
return NC_NOERR;
|
||||
@ -322,7 +318,7 @@ memio_open(const char* path,
|
||||
sizehint = *sizehintp;
|
||||
|
||||
if(inmemory) {
|
||||
filesize = meminfo->size;
|
||||
filesize = (off_t)meminfo->size;
|
||||
} else {
|
||||
/* Open the file,and make sure we can write it if needed */
|
||||
oflags = (persist ? O_RDWR : O_RDONLY);
|
||||
@ -373,7 +369,7 @@ fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->mem
|
||||
red = memio->size;
|
||||
pos = memio->memory;
|
||||
while(red > 0) {
|
||||
ssize_t count = read(fd, pos, red);
|
||||
ssize_t count = (ssize_t)read(fd, pos, (size_t)red);
|
||||
if(count < 0) {status = errno; goto unwind_open;}
|
||||
if(count == 0) {status = NC_ENOTNC; goto unwind_open;}
|
||||
red -= count;
|
||||
@ -383,7 +379,7 @@ fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->mem
|
||||
}
|
||||
|
||||
/* Use half the filesize as the blocksize ; why? */
|
||||
sizehint = filesize/2;
|
||||
sizehint = (size_t)filesize/2;
|
||||
|
||||
/* sizehint must be multiple of 8 */
|
||||
sizehint = (sizehint / 8) * 8;
|
||||
@ -454,11 +450,11 @@ memio_pad_length(ncio* nciop, off_t length)
|
||||
if((newsize % pagesize) != 0)
|
||||
newsize += (pagesize - (newsize % pagesize));
|
||||
|
||||
newmem = (char*)realloc(memio->memory,newsize);
|
||||
newmem = (char*)realloc(memio->memory,(size_t)newsize);
|
||||
if(newmem == NULL) return NC_ENOMEM;
|
||||
|
||||
/* zero out the extra memory */
|
||||
memset((void*)((char*)newmem+memio->alloc),0,(newsize - memio->alloc));
|
||||
memset((void*)((char*)newmem+memio->alloc),0,(size_t)(newsize - memio->alloc));
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"realloc: %lu/%lu -> %lu/%lu\n",
|
||||
@ -509,7 +505,7 @@ memio_close(ncio* nciop, int doUnlink)
|
||||
off_t written = memio->size;
|
||||
char* pos = memio->memory;
|
||||
while(written > 0) {
|
||||
ssize_t count = write(fd, pos, written);
|
||||
ssize_t count = (ssize_t)write(fd, pos, (size_t)written);
|
||||
if(count < 0)
|
||||
{status = errno; goto done;}
|
||||
if(count == 0)
|
||||
@ -557,7 +553,7 @@ memio_get(ncio* const nciop, off_t offset, size_t extent, int rflags, void** con
|
||||
NCMEMIO* memio;
|
||||
if(nciop == NULL || nciop->pvt == NULL) return NC_EINVAL;
|
||||
memio = (NCMEMIO*)nciop->pvt;
|
||||
status = guarantee(nciop, offset+extent);
|
||||
status = guarantee(nciop, offset+(off_t)extent);
|
||||
memio->locked++;
|
||||
if(status != NC_NOERR) return status;
|
||||
if(vpp) *vpp = memio->memory+offset;
|
||||
@ -577,11 +573,11 @@ memio_move(ncio* const nciop, off_t to, off_t from, size_t nbytes, int ignored)
|
||||
memio = (NCMEMIO*)nciop->pvt;
|
||||
if(from < to) {
|
||||
/* extend if "to" is not currently allocated */
|
||||
status = guarantee(nciop,to+nbytes);
|
||||
status = guarantee(nciop,to+(off_t)nbytes);
|
||||
if(status != NC_NOERR) return status;
|
||||
}
|
||||
/* check for overlap */
|
||||
if((to + nbytes) > from || (from + nbytes) > to) {
|
||||
if((to + (off_t)nbytes) > from || (from + (off_t)nbytes) > to) {
|
||||
/* Ranges overlap */
|
||||
#ifdef HAVE_MEMMOVE
|
||||
memmove((void*)(memio->memory+to),(void*)(memio->memory+from),nbytes);
|
||||
|
@ -49,10 +49,6 @@
|
||||
# endif
|
||||
#endif /*HAVE_MREMAP*/
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
#define ssize_t int
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
|
@ -712,7 +712,7 @@ NC_check_vlens(NC3_INFO *ncp)
|
||||
return NC_NOERR;
|
||||
|
||||
if (fIsSet(ncp->flags,NC_64BIT_DATA)) /* CDF-5 */
|
||||
vlen_max = X_INT64_MAX - 3; /* "- 3" handles rounded-up size */
|
||||
vlen_max = (size_t)X_INT64_MAX - 3; /* "- 3" handles rounded-up size */
|
||||
else if (fIsSet(ncp->flags,NC_64BIT_OFFSET) && sizeof(off_t) > 4)
|
||||
/* CDF2 format and LFS */
|
||||
vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */
|
||||
|
@ -1,398 +0,0 @@
|
||||
#include "nc3internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* this should be prime */
|
||||
#define TABLE_STARTSIZE 1021
|
||||
|
||||
#define ACTIVE 1
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
extern uint32_t hash_fast(const void *key, size_t length);
|
||||
|
||||
static int isPrime(unsigned long val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 9; i--;)
|
||||
{
|
||||
#ifdef HAVE_RANDOM
|
||||
unsigned long a = ((unsigned long)random() % (val-4)) + 2;
|
||||
#else
|
||||
unsigned long a = ((unsigned long)rand() % (val - 4)) + 2;
|
||||
#endif
|
||||
unsigned long p = 1;
|
||||
unsigned long exp = val-1;
|
||||
while (exp)
|
||||
{
|
||||
if (exp & 1)
|
||||
p = (p*a)%val;
|
||||
|
||||
a = (a*a)%val;
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
if (p != 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned long findPrimeGreaterThan(unsigned long val)
|
||||
{
|
||||
if (val & 1)
|
||||
val+=2;
|
||||
else
|
||||
val++;
|
||||
|
||||
while (!isPrime(val))
|
||||
val+=2;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void rehashDim(const NC_dimarray* ncap)
|
||||
{
|
||||
NC_hashmap* hm = ncap->hashmap;
|
||||
unsigned long size = hm->size;
|
||||
unsigned long count = hm->count;
|
||||
|
||||
hEntry* table = hm->table;
|
||||
|
||||
hm->size = findPrimeGreaterThan(size<<1);
|
||||
hm->table = (hEntry*)calloc(sizeof(hEntry), hm->size);
|
||||
hm->count = 0;
|
||||
|
||||
while(size > 0) {
|
||||
--size;
|
||||
if (table[size].flags == ACTIVE) {
|
||||
NC_dim *elem = ncap->value[table[size].data-1];
|
||||
NC_hashmapAddDim(ncap, table[size].data-1, elem->name->cp);
|
||||
assert(NC_hashmapGetDim(ncap, elem->name->cp) == table[size].data-1);
|
||||
}
|
||||
}
|
||||
|
||||
free(table);
|
||||
assert(count == hm->count);
|
||||
}
|
||||
|
||||
static void rehashVar(const NC_vararray* ncap)
|
||||
{
|
||||
NC_hashmap* hm = ncap->hashmap;
|
||||
unsigned long size = hm->size;
|
||||
unsigned long count = hm->count;
|
||||
|
||||
hEntry* table = hm->table;
|
||||
|
||||
hm->size = findPrimeGreaterThan(size<<1);
|
||||
hm->table = (hEntry*)calloc(sizeof(hEntry), (size_t)hm->size);
|
||||
hm->count = 0;
|
||||
|
||||
while(size > 0) {
|
||||
--size;
|
||||
if (table[size].flags == ACTIVE) {
|
||||
NC_var *elem = ncap->value[table[size].data-1];
|
||||
NC_hashmapAddVar(ncap, table[size].data-1, elem->name->cp);
|
||||
assert(NC_hashmapGetVar(ncap, elem->name->cp) == table[size].data-1);
|
||||
}
|
||||
}
|
||||
|
||||
free(table);
|
||||
assert(count == hm->count);
|
||||
}
|
||||
|
||||
NC_hashmap* NC_hashmapCreate(unsigned long startsize)
|
||||
{
|
||||
NC_hashmap* hm = (NC_hashmap*)malloc(sizeof(NC_hashmap));
|
||||
|
||||
if (!startsize)
|
||||
startsize = TABLE_STARTSIZE;
|
||||
else {
|
||||
startsize *= 4;
|
||||
startsize /= 3;
|
||||
startsize = findPrimeGreaterThan(startsize-2);
|
||||
}
|
||||
|
||||
hm->table = (hEntry*)calloc(sizeof(hEntry), (size_t)startsize);
|
||||
hm->size = startsize;
|
||||
hm->count = 0;
|
||||
|
||||
return hm;
|
||||
}
|
||||
|
||||
void NC_hashmapAddDim(const NC_dimarray* ncap, long data, const char *name)
|
||||
{
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
if (hash->size*3/4 <= hash->count) {
|
||||
rehashDim(ncap);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % MAX(1,(hash->size-2))) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
if (hash->table[index].flags & ACTIVE)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
hash->table[index].data = data+1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hash->table[index].flags |= ACTIVE;
|
||||
hash->table[index].data = data+1;
|
||||
hash->table[index].key = key;
|
||||
++hash->count;
|
||||
return;
|
||||
}
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
|
||||
/* it should not be possible that we EVER come this far, but unfortunately
|
||||
not every generated prime number is prime (Carmichael numbers...) */
|
||||
rehashDim(ncap);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
void NC_hashmapAddVar(const NC_vararray* ncap, long data, const char *name)
|
||||
{
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
if (hash->size*3/4 <= hash->count) {
|
||||
rehashVar(ncap);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % MAX(1,(hash->size-2))) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
if (hash->table[index].flags & ACTIVE)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
hash->table[index].data = data+1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hash->table[index].flags |= ACTIVE;
|
||||
hash->table[index].data = data+1;
|
||||
hash->table[index].key = key;
|
||||
++hash->count;
|
||||
return;
|
||||
}
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
|
||||
/* it should not be possible that we EVER come this far, but unfortunately
|
||||
not every generated prime number is prime (Carmichael numbers...) */
|
||||
rehashVar(ncap);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
long NC_hashmapRemoveDim(const NC_dimarray* ncap, const char *name)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % (hash->size-2)) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
if (hash->table[index].data > 0)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
if (hash->table[index].flags & ACTIVE)
|
||||
{
|
||||
hash->table[index].flags &= ~ACTIVE;
|
||||
--hash->count;
|
||||
return hash->table[index].data-1;
|
||||
}
|
||||
else /* in, but not active (i.e. deleted) */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else /* found an empty place (can't be in) */
|
||||
return -1;
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
/* everything searched through, but not in */
|
||||
return -1;
|
||||
}
|
||||
|
||||
long NC_hashmapRemoveVar(const NC_vararray* ncap, const char *name)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % (hash->size-2)) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
if (hash->table[index].data > 0)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
if (hash->table[index].flags & ACTIVE)
|
||||
{
|
||||
hash->table[index].flags &= ~ACTIVE;
|
||||
--hash->count;
|
||||
return hash->table[index].data-1;
|
||||
}
|
||||
else /* in, but not active (i.e. deleted) */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else /* found an empty place (can't be in) */
|
||||
return -1;
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
/* everything searched through, but not in */
|
||||
return -1;
|
||||
}
|
||||
|
||||
long NC_hashmapGetDim(const NC_dimarray* ncap, const char *name)
|
||||
{
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
if (hash->count)
|
||||
{
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
unsigned long i;
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % (hash->size-2)) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
if (entry.flags & ACTIVE)
|
||||
return entry.data-1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (!(entry.flags & ACTIVE))
|
||||
break;
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
long NC_hashmapGetVar(const NC_vararray* ncap, const char *name)
|
||||
{
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
if (hash->count)
|
||||
{
|
||||
unsigned long key = hash_fast(name, strlen(name));
|
||||
NC_hashmap* hash = ncap->hashmap;
|
||||
|
||||
unsigned long i;
|
||||
unsigned long index = key % hash->size;
|
||||
unsigned long step = (key % (hash->size-2)) + 1;
|
||||
|
||||
for (i = 0; i < hash->size; i++)
|
||||
{
|
||||
hEntry entry = hash->table[index];
|
||||
if (entry.key == key &&
|
||||
strncmp(name, ncap->value[entry.data-1]->name->cp,
|
||||
ncap->value[entry.data-1]->name->nchars) == 0)
|
||||
{
|
||||
if (entry.flags & ACTIVE)
|
||||
return entry.data-1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (!(entry.flags & ACTIVE))
|
||||
break;
|
||||
|
||||
index = (index + step) % hash->size;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long NC_hashmapCount(NC_hashmap* hash)
|
||||
{
|
||||
return hash->count;
|
||||
}
|
||||
|
||||
void NC_hashmapDelete(NC_hashmap* hash)
|
||||
{
|
||||
if (hash) {
|
||||
free(hash->table);
|
||||
free(hash);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NC_hashmap_verify(NC_hashmap* hash, NC_dim** dims)
|
||||
{
|
||||
unsigned long i;
|
||||
if(hash->count == 0) {
|
||||
fprintf(stderr,"<empty>\n");
|
||||
goto done;
|
||||
}
|
||||
for(i=0;i<hash->size;i++) {
|
||||
hEntry* e = &hash->table[i];
|
||||
if(e->flags == ACTIVE) {
|
||||
fprintf(stderr,"[%d] key=%lu data=%ld",(int)i,e->key,e->data-1);
|
||||
if(dims != NULL) {
|
||||
fprintf(stderr," name=%s",dims[e->data-1]->name->cp);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
fflush(stderr);
|
||||
}
|
@ -41,10 +41,6 @@
|
||||
#define NC_NOERR 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
|
@ -536,12 +536,12 @@ v1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap)
|
||||
if(type != NC_DIMENSION)
|
||||
return EINVAL;
|
||||
|
||||
ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));
|
||||
ncap->value = (NC_dim **) calloc(1,ncap->nelems * sizeof(NC_dim *));
|
||||
if(ncap->value == NULL)
|
||||
return NC_ENOMEM;
|
||||
ncap->nalloc = ncap->nelems;
|
||||
|
||||
ncap->hashmap = NC_hashmapCreate(ncap->nelems);
|
||||
ncap->hashmap = NC_hashmapnew(ncap->nelems);
|
||||
|
||||
{
|
||||
NC_dim **dpp = ncap->value;
|
||||
@ -557,7 +557,7 @@ v1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap)
|
||||
}
|
||||
{
|
||||
int dimid = (size_t)(dpp - ncap->value);
|
||||
NC_hashmapAddDim(ncap, dimid, (*dpp)->name->cp);
|
||||
NC_hashmapadd(ncap->hashmap, (uintptr_t)dimid, (*dpp)->name->cp,strlen((*dpp)->name->cp));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1176,12 +1176,12 @@ v1h_get_NC_vararray(v1hs *gsp, NC_vararray *ncap)
|
||||
if(type != NC_VARIABLE)
|
||||
return EINVAL;
|
||||
|
||||
ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *));
|
||||
ncap->value = (NC_var **) calloc(1,ncap->nelems * sizeof(NC_var *));
|
||||
if(ncap->value == NULL)
|
||||
return NC_ENOMEM;
|
||||
ncap->nalloc = ncap->nelems;
|
||||
|
||||
ncap->hashmap = NC_hashmapCreate(ncap->nelems);
|
||||
ncap->hashmap = NC_hashmapnew(ncap->nelems);
|
||||
{
|
||||
NC_var **vpp = ncap->value;
|
||||
NC_var *const *const end = &vpp[ncap->nelems];
|
||||
@ -1196,7 +1196,7 @@ v1h_get_NC_vararray(v1hs *gsp, NC_vararray *ncap)
|
||||
}
|
||||
{
|
||||
int varid = (size_t)(vpp - ncap->value);
|
||||
NC_hashmapAddVar(ncap, varid, (*vpp)->name->cp);
|
||||
NC_hashmapadd(ncap->hashmap, (uintptr_t)varid, (*vpp)->name->cp,strlen((*vpp)->name->cp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
102
libsrc/var.c
102
libsrc/var.c
@ -230,7 +230,7 @@ free_NC_vararrayV(NC_vararray *ncap)
|
||||
if(ncap->nalloc == 0)
|
||||
return;
|
||||
|
||||
NC_hashmapDelete(ncap->hashmap);
|
||||
NC_hashmapfree(ncap->hashmap);
|
||||
ncap->hashmap = NULL;
|
||||
|
||||
assert(ncap->value != NULL);
|
||||
@ -310,7 +310,7 @@ incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp)
|
||||
ncap->value = vp;
|
||||
ncap->nalloc = NC_ARRAY_GROWBY;
|
||||
|
||||
ncap->hashmap = NC_hashmapCreate(0);
|
||||
ncap->hashmap = NC_hashmapnew(0);
|
||||
}
|
||||
else if(ncap->nelems +1 > ncap->nalloc)
|
||||
{
|
||||
@ -324,7 +324,7 @@ incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp)
|
||||
|
||||
if(newelemp != NULL)
|
||||
{
|
||||
NC_hashmapAddVar(ncap, (long)ncap->nelems, newelemp->name->cp);
|
||||
NC_hashmapadd(ncap->hashmap, (uintptr_t)ncap->nelems, newelemp->name->cp, strlen(newelemp->name->cp));
|
||||
ncap->value[ncap->nelems] = newelemp;
|
||||
ncap->nelems++;
|
||||
}
|
||||
@ -353,35 +353,33 @@ elem_NC_vararray(const NC_vararray *ncap, size_t elem)
|
||||
* Step thru NC_VARIABLE array, seeking match on name.
|
||||
* Return varid or -1 on not found.
|
||||
* *varpp is set to the appropriate NC_var.
|
||||
* Formerly (sort of)
|
||||
NC_hvarid
|
||||
* Formerly (sort of) NC_hvarid
|
||||
*/
|
||||
int
|
||||
NC_findvar(const NC_vararray *ncap, const char *uname, NC_var **varpp)
|
||||
{
|
||||
int hash_var_id;
|
||||
char *name;
|
||||
int stat;
|
||||
int hash_var_id = -1;
|
||||
uintptr_t data;
|
||||
char *name = NULL;
|
||||
|
||||
assert(ncap != NULL);
|
||||
|
||||
if(ncap->nelems == 0)
|
||||
return -1;
|
||||
|
||||
goto done;
|
||||
|
||||
/* normalized version of uname */
|
||||
stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name);
|
||||
if(stat != NC_NOERR)
|
||||
return stat;
|
||||
if(nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name))
|
||||
goto done;
|
||||
|
||||
hash_var_id = (int)NC_hashmapGetVar(ncap, name);
|
||||
free(name);
|
||||
if (hash_var_id >= 0) {
|
||||
if (varpp != NULL)
|
||||
*varpp = ncap->value[hash_var_id];
|
||||
return(hash_var_id); /* Normal return */
|
||||
}
|
||||
return(-1); /* not found */
|
||||
if(NC_hashmapget(ncap->hashmap, name, strlen(name), &data) == 0)
|
||||
goto done;
|
||||
|
||||
hash_var_id = (int)data;
|
||||
if (varpp != NULL)
|
||||
*varpp = ncap->value[hash_var_id];
|
||||
done:
|
||||
if(name != NULL) free(name);
|
||||
return(hash_var_id); /* Normal return */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -487,7 +485,7 @@ NC_var_shape(NC_var *varp, const NC_dimarray *dims)
|
||||
out :
|
||||
|
||||
/* No variable size can be > X_INT64_MAX - 3 */
|
||||
if (0 == NC_check_vlen(varp, X_INT64_MAX-3)) return NC_EVARSIZE;
|
||||
if (0 == NC_check_vlen(varp, (size_t)X_INT64_MAX-3)) return NC_EVARSIZE;
|
||||
|
||||
/*
|
||||
* For CDF-1 and CDF-2 formats, the total number of array elements
|
||||
@ -734,73 +732,72 @@ NC3_inq_var(int ncid,
|
||||
int
|
||||
NC3_rename_var(int ncid, int varid, const char *unewname)
|
||||
{
|
||||
int status;
|
||||
int status = NC_NOERR;
|
||||
NC *nc;
|
||||
NC3_INFO* ncp;
|
||||
uintptr_t intdata;
|
||||
NC_var *varp;
|
||||
NC_string *old, *newStr;
|
||||
int other;
|
||||
char *newname; /* normalized */
|
||||
char *newname = NULL; /* normalized */
|
||||
|
||||
status = NC_check_id(ncid, &nc);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
ncp = NC3_DATA(nc);
|
||||
|
||||
if(NC_readonly(ncp))
|
||||
{
|
||||
return NC_EPERM;
|
||||
}
|
||||
{status = NC_EPERM; goto done;}
|
||||
|
||||
status = NC_check_name(unewname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
/* check for name in use */
|
||||
other = NC_findvar(&ncp->vars, unewname, &varp);
|
||||
if(other != -1)
|
||||
{
|
||||
return NC_ENAMEINUSE;
|
||||
}
|
||||
{status = NC_ENAMEINUSE; goto done;}
|
||||
|
||||
status = NC_lookupvar(ncp, varid, &varp);
|
||||
if(status != NC_NOERR)
|
||||
{
|
||||
/* invalid varid */
|
||||
return status;
|
||||
}
|
||||
|
||||
goto done; /* invalid varid */
|
||||
|
||||
old = varp->name;
|
||||
status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char **)&newname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
if(NC_indef(ncp))
|
||||
{
|
||||
/* Remove old name from hashmap; add new... */
|
||||
NC_hashmapRemoveVar(&ncp->vars, old->cp);
|
||||
|
||||
/* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */
|
||||
NC_hashmapremove(ncp->vars.hashmap,old->cp,strlen(old->cp),NULL);
|
||||
newStr = new_NC_string(strlen(newname),newname);
|
||||
free(newname);
|
||||
if(newStr == NULL)
|
||||
return(-1);
|
||||
{status = NC_ENOMEM; goto done;}
|
||||
varp->name = newStr;
|
||||
NC_hashmapAddVar(&ncp->vars, varid, newStr->cp);
|
||||
intdata = (uintptr_t)varid;
|
||||
NC_hashmapadd(ncp->vars.hashmap, intdata, varp->name->cp, strlen(varp->name->cp));
|
||||
free_NC_string(old);
|
||||
|
||||
return NC_NOERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* else, not in define mode */
|
||||
/* If new name is longer than old, then complain,
|
||||
but otherwise, no change (test is same as set_NC_string)*/
|
||||
if(varp->name->nchars < strlen(newname))
|
||||
{status = NC_ENOTINDEFINE; goto done;}
|
||||
|
||||
/* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */
|
||||
/* Remove old name from hashmap; add new... */
|
||||
NC_hashmapRemoveVar(&ncp->vars, old->cp);
|
||||
NC_hashmapremove(ncp->vars.hashmap,old->cp,strlen(old->cp),NULL);
|
||||
|
||||
/* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */
|
||||
status = set_NC_string(varp->name, newname);
|
||||
free(newname);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
|
||||
NC_hashmapAddVar(&ncp->vars, varid, varp->name->cp);
|
||||
intdata = (uintptr_t)varid;
|
||||
NC_hashmapadd(ncp->vars.hashmap, intdata, varp->name->cp, strlen(varp->name->cp));
|
||||
|
||||
set_NC_hdirty(ncp);
|
||||
|
||||
@ -808,10 +805,11 @@ NC3_rename_var(int ncid, int varid, const char *unewname)
|
||||
{
|
||||
status = NC_sync(ncp);
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
done:
|
||||
if(newname) free(newname);
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Process these files with m4.
|
||||
|
||||
SET(libsrc4_SOURCES nc4dispatch.c nc4attr.c nc4dim.c nc4file.c nc4grp.c nc4type.c nc4var.c ncfunc.c nc4internal.c nc4hdf.c nc4info.c)
|
||||
SET(libsrc4_SOURCES nc4dispatch.c nc4attr.c nc4dim.c nc4file.c nc4grp.c nc4type.c nc4var.c ncfunc.c nc4internal.c nc4hdf.c nc4info.c ncindex.c)
|
||||
|
||||
IF(LOGGING)
|
||||
SET(libsrc4_SOURCES ${libsrc4_SOURCES} error4.c)
|
||||
|
@ -12,7 +12,7 @@ libnetcdf4_la_CPPFLAGS = ${AM_CPPFLAGS}
|
||||
noinst_LTLIBRARIES = libnetcdf4.la
|
||||
libnetcdf4_la_SOURCES = nc4dispatch.c nc4attr.c nc4dim.c nc4file.c \
|
||||
nc4grp.c nc4hdf.c nc4internal.c nc4type.c nc4var.c ncfunc.c error4.c \
|
||||
nc4info.c nc4printer.c
|
||||
nc4info.c nc4printer.c ncindex.c
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
|
||||
|
@ -15,8 +15,8 @@
|
||||
*
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
#include "nc4internal.h"
|
||||
#include "nc.h"
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
#include "ncdispatch.h"
|
||||
|
||||
@ -32,7 +32,6 @@ int nc4typelen(nc_type type);
|
||||
* @param mem_type Type of attribute data in memory.
|
||||
* @param lenp Pointer that gets length of attribute array.
|
||||
* @param attnump Pointer that gets the attribute number.
|
||||
* @param is_long True if attribute data is of type NC_LONG.
|
||||
* @param data Attribute data.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
@ -43,7 +42,7 @@ int nc4typelen(nc_type type);
|
||||
static int
|
||||
nc4_get_att_special(NC_HDF5_FILE_INFO_T* h5, const char* name,
|
||||
nc_type* filetypep, nc_type mem_type, size_t* lenp,
|
||||
int* attnump, int is_long, void* data)
|
||||
int* attnump, void* data)
|
||||
{
|
||||
/* Fail if asking for att id */
|
||||
if(attnump)
|
||||
@ -139,11 +138,10 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
|
||||
|
||||
/* Check varid */
|
||||
if (varid != NC_GLOBAL) {
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(var == NULL)
|
||||
return NC_ENOTVAR;
|
||||
if (grp->vars.value[varid] == NULL)
|
||||
return NC_ENOTVAR;
|
||||
assert(grp->vars.value[varid]->varid == varid);
|
||||
assert(var->hdr.id == varid);
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
@ -155,13 +153,9 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
|
||||
|
||||
/* If this is one of the reserved atts, use nc_get_att_special. */
|
||||
if (nc->ext_ncid == ncid && varid == NC_GLOBAL) {
|
||||
const char** sp;
|
||||
for (sp = NC_RESERVED_SPECIAL_LIST; *sp; sp++) {
|
||||
if (strcmp(name,*sp)==0) {
|
||||
return nc4_get_att_special(h5, norm_name, xtype, mem_type, lenp,
|
||||
attnum, 0, data);
|
||||
}
|
||||
}
|
||||
const NC_reservedatt* ra = NC_findreserved(norm_name);
|
||||
if(ra != NULL && (ra->flags & NAMEONLYFLAG))
|
||||
return nc4_get_att_special(h5, norm_name, xtype, mem_type, lenp, attnum, data);
|
||||
}
|
||||
|
||||
/* Find the attribute, if it exists. */
|
||||
@ -188,7 +182,7 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
|
||||
if (xtype)
|
||||
*xtype = att->nc_typeid;
|
||||
if (attnum) {
|
||||
*attnum = att->attnum;
|
||||
*attnum = att->hdr.id;
|
||||
}
|
||||
|
||||
/* Zero len attributes are easy to read! */
|
||||
@ -196,7 +190,7 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
|
||||
BAIL(NC_NOERR);
|
||||
|
||||
/* Later on, we will need to know the size of this type. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, mem_type, 0, &type_size)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, mem_type, &type_size)))
|
||||
BAIL(retval);
|
||||
|
||||
/* We may have to convert data. Treat NC_CHAR the same as
|
||||
@ -245,7 +239,7 @@ nc4_get_att(int ncid, int varid, const char *name, nc_type *xtype,
|
||||
BAIL(retval);
|
||||
|
||||
/* Retrieve the size of the base type */
|
||||
if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, 0, &base_typelen)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, &base_typelen)))
|
||||
BAIL(retval);
|
||||
|
||||
for (i = 0; i < att->len; i++)
|
||||
@ -362,11 +356,36 @@ NC4_inq_attname(int ncid, int varid, int attnum, char *name)
|
||||
|
||||
/* Get the name. */
|
||||
if (name)
|
||||
strcpy(name, att->name);
|
||||
strcpy(name, att->hdr.name);
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Get the attribute list for either a varid or NC_GLOBAL
|
||||
*
|
||||
* @param grp Group
|
||||
* @param varid Variable ID | NC_BLOGAL
|
||||
* @param varp Pointer into which to return created NC_VAR_INFO_T instance
|
||||
*
|
||||
* @return Attribute list | NULL
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
static NCindex*
|
||||
getattlist(NC_GRP_INFO_T* grp, int varid, NC_VAR_INFO_T** varp)
|
||||
{
|
||||
if (varid == NC_GLOBAL) {
|
||||
if(varp) *varp = NULL;
|
||||
return grp->att;
|
||||
} else {
|
||||
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if (!var) return NULL;
|
||||
assert(var->hdr.id == varid);
|
||||
if(varp) *varp = var;
|
||||
return var->att;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal I think all atts should be named the exact same thing, to
|
||||
* avoid confusion!
|
||||
@ -387,7 +406,8 @@ NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var = NULL;
|
||||
NC_ATT_INFO_T *att, *list;
|
||||
NC_ATT_INFO_T *att;
|
||||
NCindex *list;
|
||||
char norm_newname[NC_MAX_NAME + 1], norm_name[NC_MAX_NAME + 1];
|
||||
hid_t datasetid = 0;
|
||||
int retval = NC_NOERR;
|
||||
@ -415,36 +435,26 @@ NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
|
||||
if ((retval = nc4_check_name(newname, norm_newname)))
|
||||
return retval;
|
||||
|
||||
/* Is norm_newname in use? */
|
||||
if (varid == NC_GLOBAL)
|
||||
{
|
||||
list = grp->att;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
list = var->att;
|
||||
}
|
||||
for (att = list; att; att = att->l.next)
|
||||
if (!strncmp(att->name, norm_newname, NC_MAX_NAME))
|
||||
/* Is new name in use? */
|
||||
list = getattlist(grp,varid,&var);
|
||||
if(list == NULL)
|
||||
return NC_ENOTVAR;
|
||||
|
||||
att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_newname);
|
||||
if(att != NULL)
|
||||
return NC_ENAMEINUSE;
|
||||
|
||||
/* Normalize name and find the attribute. */
|
||||
if ((retval = nc4_normalize_name(name, norm_name)))
|
||||
return retval;
|
||||
for (att = list; att; att = att->l.next)
|
||||
if (!strncmp(att->name, norm_name, NC_MAX_NAME))
|
||||
break;
|
||||
|
||||
att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_name);
|
||||
if (!att)
|
||||
return NC_ENOTATT;
|
||||
|
||||
/* If we're not in define mode, new name must be of equal or
|
||||
less size, if complying with strict NC3 rules. */
|
||||
if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->name) &&
|
||||
if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->hdr.name) &&
|
||||
(h5->cmode & NC_CLASSIC_MODEL))
|
||||
return NC_ENOTINDEFINE;
|
||||
|
||||
@ -453,26 +463,31 @@ NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
|
||||
{
|
||||
if (varid == NC_GLOBAL)
|
||||
{
|
||||
if (H5Adelete(grp->hdf_grpid, att->name) < 0)
|
||||
if (H5Adelete(grp->hdf_grpid, att->hdr.name) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((retval = nc4_open_var_grp2(grp, varid, &datasetid)))
|
||||
return retval;
|
||||
if (H5Adelete(datasetid, att->name) < 0)
|
||||
if (H5Adelete(datasetid, att->hdr.name) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
att->created = NC_FALSE;
|
||||
}
|
||||
|
||||
/* Copy the new name into our metadata. */
|
||||
free(att->name);
|
||||
if (!(att->name = malloc((strlen(norm_newname) + 1) * sizeof(char))))
|
||||
if(att->hdr.name) free(att->hdr.name);
|
||||
if (!(att->hdr.name = strdup(norm_newname)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(att->name, norm_newname);
|
||||
att->hdr.hashkey = NC_hashmapkey(att->hdr.name,strlen(att->hdr.name)); /* Fix hash key */
|
||||
|
||||
att->dirty = NC_TRUE;
|
||||
|
||||
/* Rehash the attribute list so that the new name is used */
|
||||
if(!ncindexrebuild(list))
|
||||
return NC_EINTERNAL;
|
||||
|
||||
/* Mark attributes on variable dirty, so they get written */
|
||||
if(var)
|
||||
var->attr_dirty = NC_TRUE;
|
||||
@ -498,12 +513,14 @@ NC4_del_att(int ncid, int varid, const char *name)
|
||||
{
|
||||
NC *nc;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_ATT_INFO_T *att, *natt;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_ATT_INFO_T **attlist = NULL;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_ATT_INFO_T *att;
|
||||
NCindex* attlist = NULL;
|
||||
hid_t locid = 0, datasetid = 0;
|
||||
int retval = NC_NOERR;
|
||||
int i;
|
||||
size_t deletedid;
|
||||
|
||||
if (!name)
|
||||
return NC_EINVAL;
|
||||
@ -532,27 +549,16 @@ NC4_del_att(int ncid, int varid, const char *name)
|
||||
|
||||
/* Get either the global or a variable attribute list. Also figure
|
||||
out the HDF5 location it's attached to. */
|
||||
attlist = getattlist(grp,varid,&var);
|
||||
if(attlist == NULL)
|
||||
return NC_ENOTVAR;
|
||||
if (varid == NC_GLOBAL)
|
||||
{
|
||||
attlist = &grp->att;
|
||||
locid = grp->hdf_grpid;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = &var->att;
|
||||
assert(var->varid == varid);
|
||||
if (var->created)
|
||||
locid = var->hdf_datasetid;
|
||||
}
|
||||
else if (var->created)
|
||||
locid = var->hdf_datasetid;
|
||||
|
||||
/* Now find the attribute by name or number. */
|
||||
for (att = *attlist; att; att = att->l.next)
|
||||
if (!strcmp(att->name, name))
|
||||
break;
|
||||
/* Now find the attribute by name */
|
||||
att = (NC_ATT_INFO_T*)ncindexlookup(attlist,name);
|
||||
|
||||
/* If att is NULL, we couldn't find the attribute. */
|
||||
if (!att)
|
||||
@ -563,18 +569,28 @@ NC4_del_att(int ncid, int varid, const char *name)
|
||||
{
|
||||
assert(locid);
|
||||
|
||||
if(H5Adelete(locid, att->name) < 0)
|
||||
if(H5Adelete(locid, att->hdr.name) < 0)
|
||||
BAIL(NC_EATTMETA);
|
||||
}
|
||||
|
||||
/* Renumber all following attributes. */
|
||||
for (natt = att->l.next; natt; natt = natt->l.next)
|
||||
natt->attnum--;
|
||||
|
||||
/* Delete this attribute from this list. */
|
||||
deletedid = att->hdr.id;
|
||||
|
||||
/* Remove this attribute in this list */
|
||||
if ((retval = nc4_att_list_del(attlist, att)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Renumber all attributes with higher indices. */
|
||||
for(i=0;i<ncindexsize(attlist);i++) {
|
||||
NC_ATT_INFO_T* a = (NC_ATT_INFO_T*)ncindexith(attlist,i);
|
||||
if(a == NULL) continue;
|
||||
if(a->hdr.id > deletedid) a->hdr.id--;
|
||||
}
|
||||
|
||||
/* rebuild the index */
|
||||
if(!ncindexrebuild(attlist))
|
||||
BAIL(NC_EINTERNAL);
|
||||
|
||||
exit:
|
||||
if (datasetid > 0) H5Dclose(datasetid);
|
||||
return retval;
|
||||
@ -590,7 +606,7 @@ exit:
|
||||
* @param file_type Type of the attribute data in file.
|
||||
* @param len Number of elements in attribute array.
|
||||
* @param data Attribute data.
|
||||
* @param memtype Type of data in memory.
|
||||
* @param mem_type Type of data in memory.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
* @return ::NC_EINVAL Invalid parameters.
|
||||
@ -608,7 +624,8 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var = NULL;
|
||||
NC_ATT_INFO_T *att, **attlist = NULL;
|
||||
NCindex* attlist = NULL;
|
||||
NC_ATT_INFO_T* att;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
nc_bool_t new_att = NC_FALSE;
|
||||
int retval = NC_NOERR, range_error = 0;
|
||||
@ -623,17 +640,9 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
|
||||
/* Find att, if it exists. (Must check varid first or nc_test will
|
||||
* break.) */
|
||||
if (varid == NC_GLOBAL)
|
||||
attlist = &grp->att;
|
||||
else
|
||||
{
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
attlist = &var->att;
|
||||
assert(var->varid == varid);
|
||||
}
|
||||
attlist = getattlist(grp,varid,&var);
|
||||
if(attlist == NULL)
|
||||
return NC_ENOTVAR;
|
||||
|
||||
/* The length needs to be positive (cast needed for braindead
|
||||
systems with signed size_t). */
|
||||
@ -659,28 +668,20 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
if ((retval = nc4_check_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
/* Check that a reserved NC_GLOBAL att name is not being used. */
|
||||
if (nc->ext_ncid == ncid && varid == NC_GLOBAL) {
|
||||
const char** reserved = NC_RESERVED_ATT_LIST;
|
||||
for ( ; *reserved; reserved++) {
|
||||
if (strcmp(name, *reserved)==0)
|
||||
return NC_ENAMEINUSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that a reserved variable att name is not being used. */
|
||||
if (varid != NC_GLOBAL) {
|
||||
const char** reserved = NC_RESERVED_VARATT_LIST;
|
||||
for ( ; *reserved; reserved++) {
|
||||
if (strcmp(name, *reserved) == 0)
|
||||
return NC_ENAMEINUSE;
|
||||
}
|
||||
/* Check that a reserved att name is not being used improperly */
|
||||
const NC_reservedatt* ra = NC_findreserved(name);
|
||||
if(ra != NULL) {
|
||||
/* case 1: grp=root, varid==NC_GLOBAL, flags & READONLYFLAG */
|
||||
if (nc->ext_ncid == ncid && varid == NC_GLOBAL && grp->parent == NULL
|
||||
&& (ra->flags & READONLYFLAG))
|
||||
return NC_ENAMEINUSE;
|
||||
/* case 2: grp=NA, varid!=NC_GLOBAL, flags & DIMSCALEFLAG */
|
||||
if (varid != NC_GLOBAL && (ra->flags & DIMSCALEFLAG))
|
||||
return NC_ENAMEINUSE;
|
||||
}
|
||||
|
||||
/* See if there is already an attribute with this name. */
|
||||
for (att = *attlist; att; att = att->l.next)
|
||||
if (!strcmp(att->name, norm_name))
|
||||
break;
|
||||
att = (NC_ATT_INFO_T*)ncindexlookup(attlist,norm_name);
|
||||
|
||||
LOG((1, "%s: ncid 0x%x varid %d name %s file_type %d mem_type %d len %d",
|
||||
__func__, ncid, varid, name, file_type, mem_type, len));
|
||||
@ -716,7 +717,7 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Get information about this type. */
|
||||
if ((retval = nc4_get_typelen_mem(h5, file_type, 0, &type_size)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, file_type, &type_size)))
|
||||
return retval;
|
||||
|
||||
/* No character conversions are allowed. */
|
||||
@ -735,9 +736,9 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
if (new_att)
|
||||
{
|
||||
LOG((3, "adding attribute %s to the list...", norm_name));
|
||||
if ((ret = nc4_att_list_add(attlist, &att)))
|
||||
if ((ret = nc4_att_list_add(attlist, norm_name, &att)))
|
||||
BAIL (ret);
|
||||
if (!(att->name = strdup(norm_name)))
|
||||
if (!(att->hdr.name = strdup(norm_name)))
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
@ -763,21 +764,17 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
}
|
||||
|
||||
att->len = len;
|
||||
if (att->l.prev)
|
||||
att->attnum = ((NC_ATT_INFO_T *)att->l.prev)->attnum + 1;
|
||||
else
|
||||
att->attnum = 0;
|
||||
|
||||
/* If this is the _FillValue attribute, then we will also have to
|
||||
* copy the value to the fill_vlue pointer of the NC_VAR_INFO_T
|
||||
* struct for this var. (But ignore a global _FillValue
|
||||
* attribute). */
|
||||
if (!strcmp(att->name, _FillValue) && varid != NC_GLOBAL)
|
||||
if (!strcmp(att->hdr.name, _FillValue) && varid != NC_GLOBAL)
|
||||
{
|
||||
int size;
|
||||
|
||||
/* Fill value must be same type and have exactly one value */
|
||||
if (att->nc_typeid != var->type_info->nc_typeid)
|
||||
if (att->nc_typeid != var->type_info->hdr.id)
|
||||
return NC_EBADTYPE;
|
||||
if (att->len != 1)
|
||||
return NC_EINVAL;
|
||||
@ -787,7 +784,7 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
return NC_ELATEFILL;
|
||||
|
||||
/* Get the length of the veriable data type. */
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->nc_typeid, 0,
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->hdr.id,
|
||||
&type_size)))
|
||||
return retval;
|
||||
|
||||
@ -821,7 +818,7 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Copy the fill_value. */
|
||||
LOG((4, "Copying fill value into metadata for variable %s", var->name));
|
||||
LOG((4, "Copying fill value into metadata for variable %s", var->hdr.name));
|
||||
if (var->type_info->nc_type_class == NC_VLEN)
|
||||
{
|
||||
nc_vlen_t *in_vlen = (nc_vlen_t *)data, *fv_vlen = (nc_vlen_t *)(var->fill_value);
|
||||
@ -873,7 +870,7 @@ NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
|
||||
BAIL(retval);
|
||||
|
||||
/* Retrieve the size of the base type */
|
||||
if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, 0, &base_typelen)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, type->u.v.base_nc_typeid, &base_typelen)))
|
||||
BAIL(retval);
|
||||
|
||||
vldata1 = data;
|
||||
|
125
libsrc4/nc4dim.c
125
libsrc4/nc4dim.c
@ -38,6 +38,7 @@ NC4_inq_unlimdim(int ncid, int *unlimdimidp)
|
||||
NC_DIM_INFO_T *dim;
|
||||
int found = 0;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "%s: called", __func__));
|
||||
|
||||
@ -52,11 +53,13 @@ NC4_inq_unlimdim(int ncid, int *unlimdimidp)
|
||||
*unlimdimidp = -1;
|
||||
for (g = grp; g && !found; g = g->parent)
|
||||
{
|
||||
for (dim = g->dim; dim; dim = dim->l.next)
|
||||
for(i=0;i<ncindexsize(grp->dim);i++)
|
||||
{
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if(dim == NULL) continue;
|
||||
if (dim->unlimited)
|
||||
{
|
||||
*unlimdimidp = dim->dimid;
|
||||
*unlimdimidp = dim->hdr.id;
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
@ -99,7 +102,7 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
NC_DIM_INFO_T *dim;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval = NC_NOERR;
|
||||
uint32_t nn_hash;
|
||||
int i;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x name %s len %d", __func__, ncid, name,
|
||||
(int)len));
|
||||
@ -117,11 +120,14 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
if (h5->cmode & NC_CLASSIC_MODEL)
|
||||
{
|
||||
/* Only one limited dimenson for strict nc3. */
|
||||
if (len == NC_UNLIMITED)
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (len == NC_UNLIMITED) {
|
||||
for(i=0;i<ncindexsize(grp->dim);i++) {
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if(dim == NULL) continue;
|
||||
if (dim->unlimited)
|
||||
return NC_EUNLIMIT;
|
||||
|
||||
}
|
||||
}
|
||||
/* Must be in define mode for stict nc3. */
|
||||
if (!(h5->flags & NC_INDEF))
|
||||
return NC_ENOTINDEFINE;
|
||||
@ -137,12 +143,9 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
if(len > X_UINT_MAX) /* Backward compat */
|
||||
return NC_EDIMSIZE;
|
||||
|
||||
/* Create a hash of the name. */
|
||||
nn_hash = hash_fast(norm_name, strlen(norm_name));
|
||||
|
||||
/* Make sure the name is not already in use. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (nn_hash == dim->hash && !strncmp(dim->name, norm_name, NC_MAX_NAME))
|
||||
dim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,norm_name);
|
||||
if(dim != NULL)
|
||||
return NC_ENAMEINUSE;
|
||||
|
||||
/* If it's not in define mode, enter define mode. Do this only
|
||||
@ -154,22 +157,12 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
|
||||
/* Add a dimension to the list. The ID must come from the file
|
||||
* information, since dimids are visible in more than one group. */
|
||||
if ((retval = nc4_dim_list_add(&grp->dim, &dim)))
|
||||
if ((retval = nc4_dim_list_add(grp, norm_name, len, -1, &dim)))
|
||||
return retval;
|
||||
dim->dimid = grp->nc4_info->next_dimid++;
|
||||
|
||||
/* Initialize the metadata for this dimension. */
|
||||
if (!(dim->name = strdup(norm_name)))
|
||||
return NC_ENOMEM;
|
||||
dim->len = len;
|
||||
if (len == NC_UNLIMITED)
|
||||
dim->unlimited = NC_TRUE;
|
||||
|
||||
dim->hash = nn_hash;
|
||||
|
||||
/* Pass back the dimid. */
|
||||
if (idp)
|
||||
*idp = dim->dimid;
|
||||
*idp = dim->hdr.id;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -195,9 +188,8 @@ NC4_inq_dimid(int ncid, const char *name, int *idp)
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_DIM_INFO_T *dim;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int finished = 0;
|
||||
int retval;
|
||||
uint32_t shash;
|
||||
int found;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));
|
||||
|
||||
@ -214,19 +206,18 @@ NC4_inq_dimid(int ncid, const char *name, int *idp)
|
||||
if ((retval = nc4_normalize_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
shash = hash_fast(norm_name, strlen(norm_name));
|
||||
|
||||
/* Go through each dim and check for a name match. */
|
||||
for (g = grp; g && !finished; g = g->parent)
|
||||
for (dim = g->dim; dim; dim = dim->l.next)
|
||||
if (dim->hash == shash && !strncmp(dim->name, norm_name, NC_MAX_NAME))
|
||||
{
|
||||
if (idp)
|
||||
*idp = dim->dimid;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
return NC_EBADDIM;
|
||||
/* check for a name match in this group and its parents */
|
||||
found = 0;
|
||||
for (g = grp; g ; g = g->parent) {
|
||||
dim = (NC_DIM_INFO_T*)ncindexlookup(g->dim,norm_name);
|
||||
if(dim != NULL) {found = 1; break;}
|
||||
}
|
||||
if(!found)
|
||||
return NC_EBADDIM;
|
||||
assert(dim != NULL);
|
||||
if (idp)
|
||||
*idp = dim->hdr.id;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,8 +258,8 @@ NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
|
||||
assert(dim);
|
||||
|
||||
/* Return the dimension name, if the caller wants it. */
|
||||
if (name && dim->name)
|
||||
strcpy(name, dim->name);
|
||||
if (name && dim->hdr.name)
|
||||
strcpy(name, dim->hdr.name);
|
||||
|
||||
/* Return the dimension length, if the caller wants it. */
|
||||
if (lenp)
|
||||
@ -322,11 +313,12 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
|
||||
{
|
||||
NC *nc;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_DIM_INFO_T *dim, *tmpdim;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_DIM_INFO_T *dim, *tmp_dim;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
|
||||
/* Note: name is new name */
|
||||
if (!name)
|
||||
return NC_EINVAL;
|
||||
|
||||
@ -346,25 +338,23 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
|
||||
if ((retval = nc4_check_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
/* Check if name is in use, and retain a pointer to the correct dim */
|
||||
tmp_dim = NULL;
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
{
|
||||
if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
|
||||
return NC_ENAMEINUSE;
|
||||
if (dim->dimid == dimid)
|
||||
tmp_dim = dim;
|
||||
}
|
||||
if (!tmp_dim)
|
||||
return NC_EBADDIM;
|
||||
dim = tmp_dim;
|
||||
/* Get the original dim */
|
||||
if((retval=nc4_find_dim(grp,dimid,&dim,NULL)) != NC_NOERR)
|
||||
return retval;
|
||||
if(dim == NULL) /* No such dim */
|
||||
return NC_EBADDIM;
|
||||
|
||||
/* Check if new name is in use */
|
||||
tmpdim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,norm_name);
|
||||
if(tmpdim != NULL)
|
||||
return NC_ENAMEINUSE;
|
||||
|
||||
/* Check for renaming dimension w/o variable */
|
||||
if (dim->hdf_dimscaleid)
|
||||
{
|
||||
/* Sanity check */
|
||||
assert(!dim->coord_var);
|
||||
LOG((3, "dim %s is a dim without variable", dim->name));
|
||||
LOG((3, "dim %s is a dim without variable", dim->hdr.name));
|
||||
|
||||
/* Delete the dimscale-only dataset. */
|
||||
if ((retval = delete_existing_dimscale_dataset(grp, dimid, dim)))
|
||||
@ -373,17 +363,19 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
|
||||
|
||||
/* Give the dimension its new name in metadata. UTF8 normalization
|
||||
* has been done. */
|
||||
assert(dim->name);
|
||||
free(dim->name);
|
||||
if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
|
||||
assert(dim->hdr.name);
|
||||
free(dim->hdr.name);
|
||||
if (!(dim->hdr.name = strdup(norm_name)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(dim->name, norm_name);
|
||||
dim->hash = hash_fast(norm_name, strlen(norm_name));
|
||||
LOG((3, "dim is now named %s", dim->name));
|
||||
LOG((3, "dim is now named %s", dim->hdr.name));
|
||||
dim->hdr.hashkey = NC_hashmapkey(dim->hdr.name,strlen(dim->hdr.name)); /* Fix hash key */
|
||||
|
||||
if(!ncindexrebuild(grp->dim))
|
||||
return NC_EINTERNAL;
|
||||
|
||||
/* Check if dimension was a coordinate variable, but names are
|
||||
* different now */
|
||||
if (dim->coord_var && strcmp(dim->name, dim->coord_var->name))
|
||||
if (dim->coord_var && strcmp(dim->hdr.name, dim->coord_var->hdr.name))
|
||||
{
|
||||
/* Break up the coordinate variable */
|
||||
if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim)))
|
||||
@ -397,7 +389,7 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
|
||||
|
||||
/* Attempt to find a variable with the same name as the
|
||||
* dimension in the current group. */
|
||||
if ((retval = nc4_find_var(grp, dim->name, &var)))
|
||||
if ((retval = nc4_find_var(grp, dim->hdr.name, &var)))
|
||||
return retval;
|
||||
|
||||
/* Check if we found a variable and the variable has the
|
||||
@ -405,7 +397,7 @@ NC4_rename_dim(int ncid, int dimid, const char *name)
|
||||
if (var && var->dim[0] == dim)
|
||||
{
|
||||
/* Sanity check */
|
||||
assert(var->dimids[0] == dim->dimid);
|
||||
assert(var->dimids[0] == dim->hdr.id);
|
||||
|
||||
/* Reform the coordinate variable. */
|
||||
if ((retval = nc4_reform_coord_var(grp, var, dim)))
|
||||
@ -440,6 +432,7 @@ NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
int num_unlim = 0;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
@ -451,12 +444,14 @@ NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
|
||||
/* Get our dim info. */
|
||||
assert(h5);
|
||||
{
|
||||
for (dim=grp->dim; dim; dim=dim->l.next)
|
||||
for(i=0;i<ncindexsize(grp->dim);i++)
|
||||
{
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if(dim == NULL) continue;
|
||||
if (dim->unlimited)
|
||||
{
|
||||
if (unlimdimidsp)
|
||||
unlimdimidsp[num_unlim] = dim->dimid;
|
||||
unlimdimidsp[num_unlim] = dim->hdr.id;
|
||||
num_unlim++;
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,14 @@ int
|
||||
NC4_initialize(void)
|
||||
{
|
||||
NC4_dispatch_table = &NC4_dispatcher;
|
||||
#ifdef LOGGING
|
||||
if(getenv(NCLOGLEVELENV) != NULL) {
|
||||
char* slevel = getenv(NCLOGLEVELENV);
|
||||
long level = atol(slevel);
|
||||
if(level >= 0)
|
||||
nc_set_log_level((int)level);
|
||||
}
|
||||
#endif
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <H5Fpublic.h>
|
||||
#include <hdf5_hl.h>
|
||||
|
||||
|
||||
/** @internal When we have open objects at file close, should
|
||||
we log them or print to stdout. Default is to log. */
|
||||
#define LOGOPEN 1
|
||||
@ -56,6 +57,49 @@ typedef struct {
|
||||
NC_VAR_INFO_T *var;
|
||||
} att_iter_info;
|
||||
|
||||
/* Define the table of names and properties of attributes that are reserved. */
|
||||
|
||||
#define NRESERVED 11 /*|NC_reservedatt|*/
|
||||
|
||||
/* Must be in sorted order for binary search */
|
||||
static const NC_reservedatt NC_reserved[NRESERVED] = {
|
||||
{NC_ATT_CLASS, READONLYFLAG|DIMSCALEFLAG}, /*CLASS*/
|
||||
{NC_ATT_DIMENSION_LIST, READONLYFLAG|DIMSCALEFLAG}, /*DIMENSION_LIST*/
|
||||
{NC_ATT_NAME, READONLYFLAG|DIMSCALEFLAG}, /*NAME*/
|
||||
{NC_ATT_REFERENCE_LIST, READONLYFLAG|DIMSCALEFLAG}, /*REFERENCE_LIST*/
|
||||
{NC_ATT_FORMAT, READONLYFLAG}, /*_Format*/
|
||||
{ISNETCDF4ATT, READONLYFLAG|NAMEONLYFLAG}, /*_IsNetcdf4*/
|
||||
{NCPROPS, READONLYFLAG|NAMEONLYFLAG}, /*_NCProperties*/
|
||||
{NC_ATT_COORDINATES, READONLYFLAG|DIMSCALEFLAG}, /*_Netcdf4Coordinates*/
|
||||
{NC_DIMID_ATT_NAME, READONLYFLAG|DIMSCALEFLAG}, /*_Netcdf4Dimid*/
|
||||
{SUPERBLOCKATT, READONLYFLAG|NAMEONLYFLAG},/*_SuperblockVersion*/
|
||||
{NC3_STRICT_ATT_NAME, READONLYFLAG}, /*_nc3_strict*/
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal Define a binary searcher for reserved attributes
|
||||
* @param name for which to search
|
||||
* @return pointer to the matchig NC_reservedatt structure.
|
||||
*/
|
||||
const NC_reservedatt*
|
||||
NC_findreserved(const char* name)
|
||||
{
|
||||
int n = NRESERVED;
|
||||
int L = 0;
|
||||
int R = (n - 1);
|
||||
for(;;) {
|
||||
if(L > R) break;
|
||||
int m = (L + R) / 2;
|
||||
const NC_reservedatt* p = &NC_reserved[m];
|
||||
int cmp = strcmp(p->name,name);
|
||||
if(cmp == 0) return p;
|
||||
if(cmp < 0)
|
||||
L = (m + 1);
|
||||
else /*cmp > 0*/
|
||||
R = (m - 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Given an HDF5 type, set a pointer to netcdf type.
|
||||
@ -173,9 +217,9 @@ get_netcdf_type(NC_HDF5_FILE_INFO_T *h5, hid_t native_typeid,
|
||||
|
||||
/* Maybe we already know about this type. */
|
||||
if (!equal)
|
||||
if((type = nc4_rec_find_hdf_type(h5->root_grp, native_typeid)))
|
||||
if((type = nc4_rec_find_hdf_type(h5, native_typeid)))
|
||||
{
|
||||
*xtype = type->nc_typeid;
|
||||
*xtype = type->hdr.id;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -207,9 +251,9 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
|
||||
int fixed_len_string = 0;
|
||||
size_t fixed_size = 0;
|
||||
|
||||
assert(att->name);
|
||||
LOG((5, "%s: att->attnum %d att->name %s att->nc_typeid %d att->len %d",
|
||||
__func__, att->attnum, att->name, (int)att->nc_typeid, att->len));
|
||||
assert(att->hdr.name);
|
||||
LOG((5, "%s: att->hdr.id %d att->hdr.name %s att->nc_typeid %d att->len %d",
|
||||
__func__, att->hdr.id, att->hdr.name, (int)att->nc_typeid, att->len));
|
||||
|
||||
/* Get type of attribute in file. */
|
||||
if ((file_typeid = H5Aget_type(attid)) < 0)
|
||||
@ -292,8 +336,7 @@ read_hdf5_att(NC_GRP_INFO_T *grp, hid_t attid, NC_ATT_INFO_T *att)
|
||||
attribute. */
|
||||
if (dims[0])
|
||||
{
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, att->nc_typeid, 0,
|
||||
&type_size)))
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, att->nc_typeid, &type_size)))
|
||||
return retval;
|
||||
if (att_class == H5T_VLEN)
|
||||
{
|
||||
@ -402,39 +445,24 @@ att_read_var_callbk(hid_t loc_id, const char *att_name, const H5A_info_t *ainfo,
|
||||
int retval = NC_NOERR;
|
||||
NC_ATT_INFO_T *att;
|
||||
att_iter_info *att_info = (att_iter_info *)att_data;
|
||||
const char** reserved;
|
||||
|
||||
/* Should we ignore this attribute? */
|
||||
for(reserved=NC_RESERVED_VARATT_LIST;*reserved;reserved++) {
|
||||
if (strcmp(att_name, *reserved)==0) break;
|
||||
}
|
||||
const NC_reservedatt* ra = NC_findreserved(att_name);
|
||||
if(ra != NULL) goto exit; /* ignore */
|
||||
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(att_info->var->att, att_name, &att)))
|
||||
BAIL(retval);
|
||||
|
||||
if(*reserved == NULL) {
|
||||
/* Open the att by name. */
|
||||
if ((attid = H5Aopen(loc_id, att_name, H5P_DEFAULT)) < 0)
|
||||
BAIL(NC_EATTMETA);
|
||||
LOG((4, "%s:: att_name %s", __func__, att_name));
|
||||
/* Add to the end of the list of atts for this var. */
|
||||
if ((retval = nc4_att_list_add(&att_info->var->att, &att)))
|
||||
BAIL(retval);
|
||||
/* Fill in the information we know. */
|
||||
att->attnum = att_info->var->natts++;
|
||||
if (!(att->name = strdup(att_name)))
|
||||
BAIL(NC_ENOMEM);
|
||||
|
||||
/* Read the rest of the info about the att,
|
||||
* including its values. */
|
||||
if ((retval = read_hdf5_att(att_info->grp, attid, att)))
|
||||
{
|
||||
if (NC_EBADTYPID == retval)
|
||||
{
|
||||
if ((retval = nc4_att_list_del(&att_info->var->att, att)))
|
||||
BAIL(retval);
|
||||
att = NULL;
|
||||
}
|
||||
else
|
||||
BAIL(retval);
|
||||
}
|
||||
BAIL(retval);
|
||||
|
||||
if (att)
|
||||
att->created = NC_TRUE;
|
||||
@ -442,14 +470,19 @@ att_read_var_callbk(hid_t loc_id, const char *att_name, const H5A_info_t *ainfo,
|
||||
if (attid > 0 && H5Aclose(attid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
|
||||
} /* endif not HDF5 att */
|
||||
|
||||
return NC_NOERR;
|
||||
|
||||
exit:
|
||||
if (attid > 0 && H5Aclose(attid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
|
||||
if(retval) {
|
||||
if (retval == NC_EBADTYPID) {
|
||||
/* NC_EBADTYPID will be normally converted to NC_NOERR so that
|
||||
the parent iterator does not fail. */
|
||||
retval = nc4_att_list_del(att_info->var->att,att);
|
||||
att = NULL;
|
||||
}
|
||||
}
|
||||
if (attid > 0 && H5Aclose(attid) < 0)
|
||||
retval = NC_EHDFERR;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -480,13 +513,14 @@ typedef struct NC4_rec_read_metadata_obj_info
|
||||
*/
|
||||
typedef struct NC4_rec_read_metadata_ud
|
||||
{
|
||||
NC4_rec_read_metadata_obj_info_t *grps_head, *grps_tail; /* Pointers to head & tail of list of groups */
|
||||
NC_GRP_INFO_T *grp; /* Pointer to parent group */
|
||||
NClist* grps; /* NClist<NC4_rec_read_metadata_obj_info_t*> */
|
||||
NC_GRP_INFO_T *grp; /* Pointer to parent group */
|
||||
} NC4_rec_read_metadata_ud_t;
|
||||
|
||||
/* Forward */
|
||||
static int NC4_enddef(int ncid);
|
||||
static int nc4_rec_read_metadata(NC_GRP_INFO_T *grp);
|
||||
static void dumpopenobjects(NC_HDF5_FILE_INFO_T* h5);
|
||||
|
||||
/**
|
||||
* @internal This function will write all changed metadata, and
|
||||
@ -575,9 +609,14 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
|
||||
/* Delete all the list contents for vars, dims, and atts, in each
|
||||
* group. */
|
||||
if ((retval = nc4_rec_grp_del(&h5->root_grp, h5->root_grp)))
|
||||
if ((retval = nc4_rec_grp_del(h5->root_grp)))
|
||||
goto exit;
|
||||
|
||||
/* Misc. Cleanup */
|
||||
nclistfree(h5->alldims);
|
||||
nclistfree(h5->allgroups);
|
||||
nclistfree(h5->alltypes);
|
||||
|
||||
/* Close hdf file. */
|
||||
#ifdef USE_PARALLEL4
|
||||
/* Free the MPI Comm & Info objects, if we opened the file in parallel */
|
||||
@ -594,30 +633,7 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
|
||||
|
||||
if (H5Fclose(h5->hdfid) < 0)
|
||||
{
|
||||
int nobjs;
|
||||
|
||||
nobjs = H5Fget_obj_count(h5->hdfid, H5F_OBJ_ALL);
|
||||
/* Apparently we can get an error even when nobjs == 0 */
|
||||
if(nobjs < 0) {
|
||||
BAIL_QUIET(NC_EHDFERR);
|
||||
} else if(nobjs > 0) {
|
||||
#ifdef LOGGING
|
||||
char msg[1024];
|
||||
int logit = 1;
|
||||
/* If the close doesn't work, probably there are still some HDF5
|
||||
* objects open, which means there's a bug in the library. So
|
||||
* print out some info on to help the poor programmer figure it
|
||||
* out. */
|
||||
snprintf(msg,sizeof(msg),"There are %d HDF5 objects open!", nobjs);
|
||||
#ifdef LOGOPEN
|
||||
LOG((0, msg));
|
||||
#else
|
||||
fprintf(stdout,msg);
|
||||
logit = 0;
|
||||
#endif
|
||||
reportopenobjects(logit,h5->hdfid);
|
||||
#endif
|
||||
}
|
||||
dumpopenobjects(h5);
|
||||
}
|
||||
exit:
|
||||
/* Free the nc4_info struct; above code should have reclaimed
|
||||
@ -627,12 +643,46 @@ exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
dumpopenobjects(NC_HDF5_FILE_INFO_T* h5)
|
||||
{
|
||||
int nobjs;
|
||||
|
||||
nobjs = H5Fget_obj_count(h5->hdfid, H5F_OBJ_ALL);
|
||||
/* Apparently we can get an error even when nobjs == 0 */
|
||||
if(nobjs < 0) {
|
||||
return;
|
||||
} else if(nobjs > 0) {
|
||||
char msg[1024];
|
||||
int logit = 0;
|
||||
/* If the close doesn't work, probably there are still some HDF5
|
||||
* objects open, which means there's a bug in the library. So
|
||||
* print out some info on to help the poor programmer figure it
|
||||
* out. */
|
||||
snprintf(msg,sizeof(msg),"There are %d HDF5 objects open!", nobjs);
|
||||
#ifdef LOGGING
|
||||
#ifdef LOGOPEN
|
||||
LOG((0, msg));
|
||||
logit = 1;
|
||||
#endif
|
||||
#else
|
||||
fprintf(stdout,"%s\n",msg);
|
||||
logit = 0;
|
||||
#endif
|
||||
reportopenobjects(logit,h5->hdfid);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NC4NOTUSED
|
||||
/**
|
||||
* @internal Define the names of attributes to ignore added by the
|
||||
* HDF5 dimension scale; these attached to variables. They cannot be
|
||||
* modified thru the netcdf-4 API.
|
||||
*/
|
||||
const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
static const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
NC_ATT_REFERENCE_LIST,
|
||||
NC_ATT_CLASS,
|
||||
NC_ATT_DIMENSION_LIST,
|
||||
@ -647,7 +697,7 @@ const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
* "hidden" global attributes. They can be read, but not modified thru
|
||||
* the netcdf-4 API.
|
||||
*/
|
||||
const char* NC_RESERVED_ATT_LIST[] = {
|
||||
static const char* NC_RESERVED_ATT_LIST[] = {
|
||||
NC_ATT_FORMAT,
|
||||
NC3_STRICT_ATT_NAME,
|
||||
NCPROPS,
|
||||
@ -660,12 +710,13 @@ const char* NC_RESERVED_ATT_LIST[] = {
|
||||
* @internal Define the subset of the reserved list that is readable
|
||||
* by name only
|
||||
*/
|
||||
const char* NC_RESERVED_SPECIAL_LIST[] = {
|
||||
static const char* NC_RESERVED_SPECIAL_LIST[] = {
|
||||
ISNETCDF4ATT,
|
||||
SUPERBLOCKATT,
|
||||
NCPROPS,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
size_t nc4_chunk_cache_size = CHUNK_CACHE_SIZE; /**< Default chunk cache size. */
|
||||
size_t nc4_chunk_cache_nelems = CHUNK_CACHE_NELEMS; /**< Default chunk cache number of elements. */
|
||||
@ -1126,11 +1177,9 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
int dimscale_created = 0; /* Remember if a dimension was created (for error recovery) */
|
||||
short initial_next_dimid = grp->nc4_info->next_dimid;/* Retain for error recovery */
|
||||
int retval;
|
||||
|
||||
/* Add a dimension for this scale. */
|
||||
if ((retval = nc4_dim_list_add(&grp->dim, &new_dim)))
|
||||
BAIL(retval);
|
||||
dimscale_created++;
|
||||
size_t len = 0;
|
||||
int too_long = NC_FALSE;
|
||||
int assigned_id = -1;
|
||||
|
||||
/* Does this dataset have a hidden attribute that tells us its
|
||||
* dimid? If so, read it. */
|
||||
@ -1141,33 +1190,34 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
if ((attid = H5Aopen_name(datasetid, NC_DIMID_ATT_NAME)) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
|
||||
if (H5Aread(attid, H5T_NATIVE_INT, &new_dim->dimid) < 0)
|
||||
if (H5Aread(attid, H5T_NATIVE_INT, &assigned_id) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
|
||||
/* Check if scale's dimid should impact the group's next dimid */
|
||||
if (new_dim->dimid >= grp->nc4_info->next_dimid)
|
||||
grp->nc4_info->next_dimid = new_dim->dimid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Assign dimid */
|
||||
new_dim->dimid = grp->nc4_info->next_dimid++;
|
||||
if (assigned_id >= grp->nc4_info->next_dimid)
|
||||
grp->nc4_info->next_dimid = assigned_id + 1;
|
||||
}
|
||||
|
||||
if (!(new_dim->name = strdup(obj_name)))
|
||||
BAIL(NC_ENOMEM);
|
||||
if (SIZEOF_SIZE_T < 8 && scale_size > NC_MAX_UINT)
|
||||
{
|
||||
new_dim->len = NC_MAX_UINT;
|
||||
new_dim->too_long = NC_TRUE;
|
||||
len = NC_MAX_UINT;
|
||||
too_long = NC_TRUE;
|
||||
}
|
||||
else
|
||||
new_dim->len = scale_size;
|
||||
len = scale_size;
|
||||
|
||||
/* Create the dimension for this scale. */
|
||||
if ((retval = nc4_dim_list_add(grp, obj_name, len, assigned_id, &new_dim)))
|
||||
BAIL(retval);
|
||||
|
||||
new_dim->too_long = too_long;
|
||||
|
||||
dimscale_created++;
|
||||
|
||||
new_dim->hdf5_objid.fileno[0] = statbuf->fileno[0];
|
||||
new_dim->hdf5_objid.fileno[1] = statbuf->fileno[1];
|
||||
new_dim->hdf5_objid.objno[0] = statbuf->objno[0];
|
||||
new_dim->hdf5_objid.objno[1] = statbuf->objno[1];
|
||||
new_dim->hash = hash_fast(obj_name, strlen(obj_name));
|
||||
|
||||
/* If the dimscale has an unlimited dimension, then this dimension
|
||||
* is unlimited. */
|
||||
@ -1186,7 +1236,7 @@ read_scale(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
{
|
||||
size_t len = 0, *lenp = &len;
|
||||
|
||||
if ((retval = nc4_find_dim_len(grp, new_dim->dimid, &lenp)))
|
||||
if ((retval = nc4_find_dim_len(grp, new_dim->hdr.id, &lenp)))
|
||||
BAIL(retval);
|
||||
new_dim->len = *lenp;
|
||||
}
|
||||
@ -1208,8 +1258,8 @@ exit:
|
||||
/* On error, undo any dimscale creation */
|
||||
if (retval < 0 && dimscale_created)
|
||||
{
|
||||
/* Delete the dimension */
|
||||
if ((retval = nc4_dim_list_del(&grp->dim, new_dim)))
|
||||
/* free the dimension */
|
||||
if ((retval = nc4_dim_list_del(grp, new_dim)))
|
||||
BAIL2(retval);
|
||||
|
||||
/* Reset the group's information */
|
||||
@ -1252,7 +1302,7 @@ read_coord_dimids(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
if (!ret && npoints != var->ndims) ret++;
|
||||
|
||||
if (!ret && H5Aread(coord_attid, coord_att_typeid, var->dimids) < 0) ret++;
|
||||
LOG((4, "dimscale %s is multidimensional and has coords", var->name));
|
||||
LOG((4, "dimscale %s is multidimensional and has coords", var->hdr.name));
|
||||
|
||||
/* Update var->dim field based on the var->dimids */
|
||||
for (d = 0; d < var->ndims; d++) {
|
||||
@ -1415,9 +1465,9 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid,
|
||||
else
|
||||
(*type_info)->nc_type_class = NC_FLOAT;
|
||||
}
|
||||
(*type_info)->nc_typeid = nc_type_constant_g[t];
|
||||
(*type_info)->hdr.id = nc_type_constant_g[t];
|
||||
(*type_info)->size = nc_type_size_g[t];
|
||||
if (!((*type_info)->name = strdup(nc_type_name_g[t])))
|
||||
if (!((*type_info)->hdr.name = strdup(nc_type_name_g[t])))
|
||||
return NC_ENOMEM;
|
||||
(*type_info)->hdf_typeid = hdf_typeid;
|
||||
(*type_info)->native_hdf_typeid = native_typeid;
|
||||
@ -1428,7 +1478,7 @@ get_type_info2(NC_HDF5_FILE_INFO_T *h5, hid_t datasetid,
|
||||
NC_TYPE_INFO_T *type;
|
||||
|
||||
/* This is a user-defined type. */
|
||||
if((type = nc4_rec_find_hdf_type(h5->root_grp, native_typeid)))
|
||||
if((type = nc4_rec_find_hdf_type(h5, native_typeid)))
|
||||
*type_info = type;
|
||||
|
||||
/* The type entry in the array of user-defined types already has
|
||||
@ -1468,10 +1518,11 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
hid_t native_typeid;
|
||||
size_t type_size;
|
||||
int retval = NC_NOERR;
|
||||
int nmembers;
|
||||
|
||||
assert(grp && type_name);
|
||||
|
||||
LOG((4, "%s: type_name %s grp->name %s", __func__, type_name, grp->name));
|
||||
LOG((4, "%s: type_name %s grp->hdr.name %s", __func__, type_name, grp->hdr.name));
|
||||
|
||||
/* What is the native type for this platform? */
|
||||
if ((native_typeid = H5Tget_native_type(hdf_typeid, H5T_DIR_DEFAULT)) < 0)
|
||||
@ -1515,6 +1566,9 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
if ((nmembers = H5Tget_nmembers(hdf_typeid)) < 0)
|
||||
return NC_EHDFERR;
|
||||
LOG((5, "compound type has %d members", nmembers));
|
||||
type->u.c.field = nclistnew();
|
||||
nclistsetalloc(type->u.c.field,nmembers);
|
||||
|
||||
for (m = 0; m < nmembers; m++)
|
||||
{
|
||||
hid_t member_hdf_typeid;
|
||||
@ -1523,7 +1577,6 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
H5T_class_t mem_class;
|
||||
nc_type member_xtype;
|
||||
|
||||
|
||||
/* Get the typeid and native typeid of this member of the
|
||||
* compound type. */
|
||||
if ((member_hdf_typeid = H5Tget_member_type(type->native_hdf_typeid, m)) < 0)
|
||||
@ -1574,7 +1627,7 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
break;
|
||||
|
||||
/* Add this member to our list of fields in this compound type. */
|
||||
if ((retval = nc4_field_list_add(&type->u.c.field, type->u.c.num_fields++, member_name,
|
||||
if ((retval = nc4_field_list_add(type, member_name,
|
||||
member_offset, H5Tget_super(member_hdf_typeid),
|
||||
H5Tget_super(member_native_typeid),
|
||||
member_xtype, ndims, dim_size)))
|
||||
@ -1588,7 +1641,7 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
break;
|
||||
|
||||
/* Add this member to our list of fields in this compound type. */
|
||||
if ((retval = nc4_field_list_add(&type->u.c.field, type->u.c.num_fields++, member_name,
|
||||
if ((retval = nc4_field_list_add(type, member_name,
|
||||
member_offset, member_hdf_typeid, member_native_typeid,
|
||||
member_xtype, 0, NULL)))
|
||||
break;
|
||||
@ -1682,17 +1735,18 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
type->u.e.base_hdf_typeid = base_hdf_typeid;
|
||||
|
||||
/* Find out how many member are in the enum. */
|
||||
if ((type->u.e.num_members = H5Tget_nmembers(hdf_typeid)) < 0)
|
||||
if ((nmembers = H5Tget_nmembers(hdf_typeid)) < 0)
|
||||
return NC_EHDFERR;
|
||||
type->u.e.enum_member = nclistnew();
|
||||
nclistsetalloc(type->u.e.enum_member,nmembers);
|
||||
|
||||
/* Allocate space for one value. */
|
||||
if (!(value = calloc(1, type_size)))
|
||||
return NC_ENOMEM;
|
||||
|
||||
/* Read each name and value defined in the enum. */
|
||||
for (i = 0; i < type->u.e.num_members; i++)
|
||||
for (i = 0; i < nmembers; i++)
|
||||
{
|
||||
|
||||
/* Get the name and value from HDF5. */
|
||||
if (!(member_name = H5Tget_member_name(hdf_typeid, i)))
|
||||
{
|
||||
@ -1716,7 +1770,7 @@ read_type(NC_GRP_INFO_T *grp, hid_t hdf_typeid, char *type_name)
|
||||
}
|
||||
|
||||
/* Insert new field into this type's list of fields. */
|
||||
if ((retval = nc4_enum_member_add(&type->u.e.enum_member, type->size,
|
||||
if ((retval = nc4_enum_member_add(type, type->size,
|
||||
member_name, value)))
|
||||
{
|
||||
break;
|
||||
@ -1777,31 +1831,34 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
int retval = NC_NOERR;
|
||||
double rdcc_w0;
|
||||
int f;
|
||||
char* finalname = NULL;
|
||||
|
||||
assert(obj_name && grp);
|
||||
LOG((4, "%s: obj_name %s", __func__, obj_name));
|
||||
|
||||
/* Check for a weird case: a non-coordinate variable that has the
|
||||
* same name as a dimension. It's legal in netcdf, and requires
|
||||
* that the HDF5 dataset name be changed. */
|
||||
if (strlen(obj_name) > strlen(NON_COORD_PREPEND) &&
|
||||
!strncmp(obj_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)))
|
||||
{
|
||||
/* Allocate space for the name. */
|
||||
if(finalname) {free(finalname); finalname = NULL;}
|
||||
if (!(finalname = malloc(((strlen(obj_name) - strlen(NON_COORD_PREPEND))+ 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(finalname, &obj_name[strlen(NON_COORD_PREPEND)]);
|
||||
} else
|
||||
finalname = strdup(obj_name);
|
||||
|
||||
/* Add a variable to the end of the group's var list. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
if ((retval = nc4_var_list_add(grp,finalname,ndims,&var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Fill in what we already know. */
|
||||
var->hdf_datasetid = datasetid;
|
||||
H5Iinc_ref(var->hdf_datasetid); /* Increment number of objects using ID */
|
||||
incr_id_rc++; /* Indicate that we've incremented the ref. count (for errors) */
|
||||
var->varid = grp->nvars++;
|
||||
var->created = NC_TRUE;
|
||||
var->ndims = ndims;
|
||||
|
||||
/* We need some room to store information about dimensions for this
|
||||
* var. */
|
||||
if (var->ndims)
|
||||
{
|
||||
if (!(var->dim = calloc(var->ndims, sizeof(NC_DIM_INFO_T *))))
|
||||
BAIL(NC_ENOMEM);
|
||||
if (!(var->dimids = calloc(var->ndims, sizeof(int))))
|
||||
BAIL(NC_ENOMEM);
|
||||
}
|
||||
|
||||
/* Get the current chunk cache settings. */
|
||||
if ((access_pid = H5Dget_access_plist(datasetid)) < 0)
|
||||
@ -1813,34 +1870,6 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
BAIL(NC_EHDFERR);
|
||||
var->chunk_cache_preemption = rdcc_w0;
|
||||
|
||||
/* Check for a weird case: a non-coordinate variable that has the
|
||||
* same name as a dimension. It's legal in netcdf, and requires
|
||||
* that the HDF5 dataset name be changed. */
|
||||
if (strlen(obj_name) > strlen(NON_COORD_PREPEND) &&
|
||||
!strncmp(obj_name, NON_COORD_PREPEND, strlen(NON_COORD_PREPEND)))
|
||||
{
|
||||
/* Allocate space for the name. */
|
||||
if (!(var->name = malloc(((strlen(obj_name) - strlen(NON_COORD_PREPEND))+ 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
|
||||
strcpy(var->name, &obj_name[strlen(NON_COORD_PREPEND)]);
|
||||
|
||||
/* Allocate space for the HDF5 name. */
|
||||
if (!(var->hdf5_name = malloc((strlen(obj_name) + 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
|
||||
strcpy(var->hdf5_name, obj_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the name. */
|
||||
if (!(var->name = malloc((strlen(obj_name) + 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
|
||||
strcpy(var->name, obj_name);
|
||||
}
|
||||
|
||||
var->hash = hash_fast(var->name, strlen(var->name));
|
||||
/* Find out what filters are applied to this HDF5 dataset,
|
||||
* fletcher32, deflate, and/or shuffle. All other filters are
|
||||
* just dumped */
|
||||
@ -1963,9 +1992,9 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
else
|
||||
{
|
||||
/* sanity check */
|
||||
assert(0 == strcmp(var->name, dim->name));
|
||||
assert(0 == strcmp(var->hdr.name, dim->hdr.name));
|
||||
|
||||
var->dimids[0] = dim->dimid;
|
||||
var->dimids[0] = dim->hdr.id;
|
||||
var->dim[0] = dim;
|
||||
}
|
||||
dim->coord_var = var;
|
||||
@ -2015,22 +2044,20 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
|
||||
att_read_var_callbk, &att_info)) < 0)
|
||||
BAIL(NC_EATTMETA);
|
||||
|
||||
/* Add a var to the variable array, growing it as needed. */
|
||||
if ((retval = nc4_vararray_add(grp, var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Is this a deflated variable with a chunksize greater than the
|
||||
* current cache size? */
|
||||
if ((retval = nc4_adjust_var_cache(grp, var)))
|
||||
BAIL(retval);
|
||||
|
||||
exit:
|
||||
if(finalname) free(finalname);
|
||||
if (retval)
|
||||
{
|
||||
if (incr_id_rc && H5Idec_ref(datasetid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
if (var && nc4_var_del(var))
|
||||
BAIL2(NC_EHDFERR);
|
||||
if (var != NULL) {
|
||||
nc4_var_list_del(grp,var);
|
||||
}
|
||||
}
|
||||
if (access_pid && H5Pclose(access_pid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
@ -2058,7 +2085,6 @@ read_grp_atts(NC_GRP_INFO_T *grp)
|
||||
NC_ATT_INFO_T *att;
|
||||
NC_TYPE_INFO_T *type;
|
||||
char obj_name[NC_MAX_HDF5_NAME + 1];
|
||||
int max_len;
|
||||
int retval = NC_NOERR;
|
||||
int hidden = 0;
|
||||
|
||||
@ -2072,15 +2098,11 @@ read_grp_atts(NC_GRP_INFO_T *grp)
|
||||
LOG((3, "reading attribute of _netCDF group, named %s", obj_name));
|
||||
|
||||
/* See if this a hidden, global attribute */
|
||||
hidden = 0; /* default */
|
||||
if(grp->nc4_info->root_grp == grp) {
|
||||
const char** reserved = NC_RESERVED_ATT_LIST;
|
||||
hidden = 0;
|
||||
for(;*reserved;reserved++) {
|
||||
if(strcmp(*reserved,obj_name)==0) {
|
||||
hidden = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const NC_reservedatt* ra = NC_findreserved(obj_name);
|
||||
if(ra != NULL && (ra->flags & NAMEONLYFLAG))
|
||||
hidden = 1;
|
||||
}
|
||||
|
||||
/* This may be an attribute telling us that strict netcdf-3
|
||||
@ -2091,19 +2113,11 @@ read_grp_atts(NC_GRP_INFO_T *grp)
|
||||
grp->nc4_info->cmode |= NC_CLASSIC_MODEL;
|
||||
else if(!hidden) {
|
||||
/* Add an att struct at the end of the list, and then go to it. */
|
||||
if ((retval = nc4_att_list_add(&grp->att, &att)))
|
||||
if ((retval = nc4_att_list_add(grp->att, obj_name, &att)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Add the info about this attribute. */
|
||||
max_len = strlen(obj_name) > NC_MAX_NAME ? NC_MAX_NAME : strlen(obj_name);
|
||||
if (!(att->name = malloc((max_len + 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
strncpy(att->name, obj_name, max_len);
|
||||
att->name[max_len] = 0;
|
||||
att->attnum = grp->natts++;
|
||||
retval = read_hdf5_att(grp, attid, att);
|
||||
if(retval == NC_EBADTYPID) {
|
||||
if((retval = nc4_att_list_del(&grp->att, att)))
|
||||
if((retval = nc4_att_list_del(grp->att, att)))
|
||||
BAIL(retval);
|
||||
} else if(retval) {
|
||||
BAIL(retval);
|
||||
@ -2191,8 +2205,7 @@ exit:
|
||||
/**
|
||||
* @internal Add callback function to list.
|
||||
*
|
||||
* @param head
|
||||
* @param tail
|
||||
* @param udata - the callback state
|
||||
* @param oinfo The object info.
|
||||
*
|
||||
* @return ::NC_NOERR No error.
|
||||
@ -2200,8 +2213,7 @@ exit:
|
||||
* @author Ed Hartnett
|
||||
*/
|
||||
static int
|
||||
nc4_rec_read_metadata_cb_list_add(NC4_rec_read_metadata_obj_info_t **head,
|
||||
NC4_rec_read_metadata_obj_info_t **tail,
|
||||
nc4_rec_read_metadata_cb_list_add(NC4_rec_read_metadata_ud_t* udata,
|
||||
const NC4_rec_read_metadata_obj_info_t *oinfo)
|
||||
{
|
||||
NC4_rec_read_metadata_obj_info_t *new_oinfo; /* Pointer to info for object */
|
||||
@ -2213,18 +2225,7 @@ nc4_rec_read_metadata_cb_list_add(NC4_rec_read_metadata_obj_info_t **head,
|
||||
/* Make a copy of the object's info */
|
||||
memcpy(new_oinfo, oinfo, sizeof(*oinfo));
|
||||
|
||||
if (*tail)
|
||||
{
|
||||
assert(*head);
|
||||
(*tail)->next = new_oinfo;
|
||||
*tail = new_oinfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(NULL == *head);
|
||||
*head = *tail = new_oinfo;
|
||||
}
|
||||
|
||||
nclistpush(udata->grps,new_oinfo);
|
||||
return (NC_NOERR);
|
||||
}
|
||||
|
||||
@ -2271,7 +2272,7 @@ nc4_rec_read_metadata_cb(hid_t grpid, const char *name, const H5L_info_t *info,
|
||||
* in the current group can be processed and be ready for use by
|
||||
* vars in the child group(s).
|
||||
*/
|
||||
if (nc4_rec_read_metadata_cb_list_add(&udata->grps_head, &udata->grps_tail, &oinfo))
|
||||
if (nc4_rec_read_metadata_cb_list_add(udata, &oinfo))
|
||||
BAIL(H5_ITER_ERROR);
|
||||
break;
|
||||
|
||||
@ -2350,8 +2351,8 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
H5_index_t iter_index;
|
||||
int i, retval = NC_NOERR; /* everything worked! */
|
||||
|
||||
assert(grp && grp->name);
|
||||
LOG((3, "%s: grp->name %s", __func__, grp->name));
|
||||
assert(grp && grp->hdr.name);
|
||||
LOG((3, "%s: grp->hdr.name %s", __func__, grp->hdr.name));
|
||||
|
||||
/* Portably initialize user data for later */
|
||||
memset(&udata, 0, sizeof(udata));
|
||||
@ -2363,7 +2364,7 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
if (grp->parent)
|
||||
{
|
||||
if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid,
|
||||
grp->name, H5P_DEFAULT)) < 0)
|
||||
grp->hdr.name, H5P_DEFAULT)) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
}
|
||||
else
|
||||
@ -2397,6 +2398,7 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
|
||||
/* Set user data for iteration */
|
||||
udata.grp = grp;
|
||||
udata.grps = nclistnew();
|
||||
|
||||
/* Iterate over links in this group, building lists for the types,
|
||||
* datasets and groups encountered
|
||||
@ -2409,14 +2411,13 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
/* (Deferred until now, so that the types in the current group get
|
||||
* processed and are available for vars in the child group(s).)
|
||||
*/
|
||||
for (oinfo = udata.grps_head; oinfo; oinfo = udata.grps_head)
|
||||
for(i=0;i<nclistlength(udata.grps);i++)
|
||||
{
|
||||
NC_GRP_INFO_T *child_grp;
|
||||
NC_HDF5_FILE_INFO_T *h5 = grp->nc4_info;
|
||||
oinfo = (NC4_rec_read_metadata_obj_info_t*)nclistget(udata.grps,i);
|
||||
|
||||
/* Add group to file's hierarchy */
|
||||
if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid++,
|
||||
grp, grp->nc4_info->controller, oinfo->oname, &child_grp)))
|
||||
if ((retval = nc4_grp_list_add(grp, oinfo->oname, &child_grp)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Recursively read the child group's metadata */
|
||||
@ -2426,10 +2427,6 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
/* Close the object */
|
||||
if (H5Oclose(oinfo->oid) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
|
||||
/* Advance to next node, free current node */
|
||||
udata.grps_head = oinfo->next;
|
||||
free(oinfo);
|
||||
}
|
||||
|
||||
/* Scan the group for global (i.e. group-level) attributes. */
|
||||
@ -2437,24 +2434,27 @@ nc4_rec_read_metadata(NC_GRP_INFO_T *grp)
|
||||
BAIL(retval);
|
||||
|
||||
/* when exiting define mode, mark all variable written */
|
||||
for (i=0; i<grp->vars.nelems; i++)
|
||||
grp->vars.value[i]->written_to = NC_TRUE;
|
||||
for (i=0; i<ncindexsize(grp->vars); i++) {
|
||||
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
|
||||
if(var == NULL) continue;
|
||||
var->written_to = NC_TRUE;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* Clean up local information on error, if anything remains */
|
||||
if (retval)
|
||||
/* Clean up local information, if anything remains */
|
||||
for(i=0;i<nclistlength(udata.grps);i++)
|
||||
{
|
||||
for (oinfo = udata.grps_head; oinfo; oinfo = udata.grps_head)
|
||||
{
|
||||
oinfo = (NC4_rec_read_metadata_obj_info_t*)nclistget(udata.grps,i);
|
||||
if (retval)
|
||||
{
|
||||
/* Close the object */
|
||||
if (H5Oclose(oinfo->oid) < 0)
|
||||
BAIL2(NC_EHDFERR);
|
||||
|
||||
/* Advance to next node, free current node */
|
||||
udata.grps_head = oinfo->next;
|
||||
free(oinfo);
|
||||
}
|
||||
}
|
||||
free(oinfo);
|
||||
}
|
||||
nclistfree(udata.grps);
|
||||
udata.grps = NULL;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -2815,12 +2815,15 @@ static int NC4_enddef(int ncid)
|
||||
assert(nc4_info);
|
||||
|
||||
/* Find info for this file and group */
|
||||
if (!(grp = nc4_rec_find_grp(nc4_info->root_grp, (ncid & GRP_ID_MASK))))
|
||||
if (!(grp = nc4_rec_find_grp(nc4_info, (ncid & GRP_ID_MASK))))
|
||||
return NC_EBADGRPID;
|
||||
|
||||
/* when exiting define mode, mark all variable written */
|
||||
for (i=0; i<grp->vars.nelems; i++)
|
||||
grp->vars.value[i]->written_to = NC_TRUE;
|
||||
for (i=0; i<ncindexsize(grp->vars); i++) {
|
||||
NC_VAR_INFO_T* var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
|
||||
if(var != NULL) continue;
|
||||
var->written_to = NC_TRUE;
|
||||
}
|
||||
|
||||
return nc4_enddef_netcdf4_file(nc4_info);
|
||||
}
|
||||
@ -2967,9 +2970,8 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
||||
NC *nc;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_DIM_INFO_T *dim;
|
||||
NC_ATT_INFO_T *att;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "%s: ncid 0x%x", __func__, ncid));
|
||||
|
||||
@ -2979,28 +2981,18 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
||||
|
||||
assert(h5 && grp && nc);
|
||||
|
||||
/* Count the number of dims, vars, and global atts. */
|
||||
/* Count the number of dims, vars, and global atts; need to iterate because of possible nulls */
|
||||
if (ndimsp)
|
||||
{
|
||||
*ndimsp = 0;
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
(*ndimsp)++;
|
||||
*ndimsp = ncindexcount(grp->dim);
|
||||
}
|
||||
if (nvarsp)
|
||||
{
|
||||
int i;
|
||||
*nvarsp = 0;
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
if (grp->vars.value[i])
|
||||
(*nvarsp)++;
|
||||
}
|
||||
*nvarsp = ncindexcount(grp->vars);
|
||||
}
|
||||
if (nattsp)
|
||||
{
|
||||
*nattsp = 0;
|
||||
for (att = grp->att; att; att = att->l.next)
|
||||
(*nattsp)++;
|
||||
*nattsp = ncindexcount(grp->att);
|
||||
}
|
||||
|
||||
if (unlimdimidp)
|
||||
@ -3012,12 +3004,14 @@ NC4_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp)
|
||||
with netcdf-3, then only the last unlimited one will be reported
|
||||
back in xtendimp. */
|
||||
/* Note that this code is inconsistent with nc_inq_unlimid() */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (dim->unlimited)
|
||||
{
|
||||
*unlimdimidp = dim->dimid;
|
||||
for(i=0;i<ncindexsize(grp->dim);i++) {
|
||||
NC_DIM_INFO_T* d = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if(d == NULL) continue;
|
||||
if(d->unlimited) {
|
||||
*unlimdimidp = d->hdr.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
|
@ -31,7 +31,7 @@
|
||||
int
|
||||
NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_GRP_INFO_T *grp, *g;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
@ -63,12 +63,10 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
|
||||
/* Update internal lists to reflect new group. The actual HDF5
|
||||
* group creation will be done when metadata is written by a
|
||||
* sync. */
|
||||
if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid,
|
||||
grp, grp->nc4_info->controller, norm_name, NULL)))
|
||||
if ((retval = nc4_grp_list_add(grp, norm_name, &g)))
|
||||
return retval;
|
||||
if (new_ncid)
|
||||
*new_ncid = grp->nc4_info->controller->ext_ncid | h5->next_nc_grpid;
|
||||
h5->next_nc_grpid++;
|
||||
*new_ncid = grp->nc4_info->controller->ext_ncid | g->hdr.id;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -91,7 +89,7 @@ NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
|
||||
int
|
||||
NC4_rename_grp(int grpid, const char *name)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_GRP_INFO_T *grp, *parent;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
@ -109,6 +107,7 @@ NC4_rename_grp(int grpid, const char *name)
|
||||
/* Do not allow renaming the root group */
|
||||
if (grp->parent == NULL)
|
||||
return NC_EBADGRPID;
|
||||
parent = grp->parent;
|
||||
|
||||
/* Check and normalize the name. */
|
||||
if ((retval = nc4_check_name(name, norm_name)))
|
||||
@ -116,7 +115,7 @@ NC4_rename_grp(int grpid, const char *name)
|
||||
|
||||
/* Check that this name is not in use as a var, grp, or type in the
|
||||
* parent group (i.e. the group that grp is in). */
|
||||
if ((retval = nc4_check_dup_name(grp->parent, norm_name)))
|
||||
if ((retval = nc4_check_dup_name(parent, norm_name)))
|
||||
return retval;
|
||||
|
||||
/* If it's not in define mode, switch to define mode. */
|
||||
@ -136,21 +135,24 @@ NC4_rename_grp(int grpid, const char *name)
|
||||
if (grp->parent->hdf_grpid)
|
||||
{
|
||||
/* Rename the group */
|
||||
if (H5Gmove(grp->parent->hdf_grpid, grp->name, name) < 0)
|
||||
if (H5Gmove(parent->hdf_grpid, grp->hdr.name, name) < 0)
|
||||
return NC_EHDFERR;
|
||||
|
||||
/* Reopen the group, with the new name */
|
||||
if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, name, H5P_DEFAULT)) < 0)
|
||||
if ((grp->hdf_grpid = H5Gopen2(parent->hdf_grpid, name, H5P_DEFAULT)) < 0)
|
||||
return NC_EHDFERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give the group its new name in metadata. UTF8 normalization
|
||||
* has been done. */
|
||||
free(grp->name);
|
||||
if (!(grp->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
|
||||
free(grp->hdr.name);
|
||||
if (!(grp->hdr.name = strdup(norm_name)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(grp->name, norm_name);
|
||||
grp->hdr.hashkey = NC_hashmapkey(grp->hdr.name,strlen(grp->hdr.name)); /* Fix hash key */
|
||||
|
||||
if(!ncindexrebuild(parent->children))
|
||||
return NC_EINTERNAL;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -185,17 +187,16 @@ NC4_inq_ncid(int ncid, const char *name, int *grp_ncid)
|
||||
assert(h5);
|
||||
|
||||
/* Normalize name. */
|
||||
if ((retval = nc4_normalize_name(name, norm_name)))
|
||||
if ((retval = nc4_check_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
/* Look through groups for one of this name. */
|
||||
for (g = grp->children; g; g = g->l.next)
|
||||
if (!strcmp(norm_name, g->name)) /* found it! */
|
||||
{
|
||||
g = (NC_GRP_INFO_T*)ncindexlookup(grp->children,norm_name);
|
||||
if(g != NULL)
|
||||
{
|
||||
if (grp_ncid)
|
||||
*grp_ncid = grp->nc4_info->controller->ext_ncid | g->nc_grpid;
|
||||
*grp_ncid = grp->nc4_info->controller->ext_ncid | g->hdr.id;
|
||||
return NC_NOERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here, we didn't find the named group. */
|
||||
return NC_ENOGRP;
|
||||
@ -220,6 +221,7 @@ NC4_inq_grps(int ncid, int *numgrps, int *ncids)
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
int num = 0;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "nc_inq_grps: ncid 0x%x", ncid));
|
||||
|
||||
@ -229,14 +231,16 @@ NC4_inq_grps(int ncid, int *numgrps, int *ncids)
|
||||
assert(h5);
|
||||
|
||||
/* Count the number of groups in this group. */
|
||||
for (g = grp->children; g; g = g->l.next)
|
||||
for(i=0;i<ncindexsize(grp->children);i++)
|
||||
{
|
||||
g = (NC_GRP_INFO_T*)ncindexith(grp->children,i);
|
||||
if(g == NULL) continue;
|
||||
if (ncids)
|
||||
{
|
||||
/* Combine the nc_grpid in a bitwise or with the ext_ncid,
|
||||
* which allows the returned ncid to carry both file and
|
||||
* group information. */
|
||||
*ncids = g->nc_grpid | g->nc4_info->controller->ext_ncid;
|
||||
*ncids = g->hdr.id | g->nc4_info->controller->ext_ncid;
|
||||
ncids++;
|
||||
}
|
||||
num++;
|
||||
@ -275,7 +279,7 @@ NC4_inq_grpname(int ncid, char *name)
|
||||
|
||||
/* Copy the name. */
|
||||
if (name)
|
||||
strcpy(name, grp->name);
|
||||
strcpy(name, grp->hdr.name);
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -317,7 +321,7 @@ NC4_inq_grpname_full(int ncid, size_t *lenp, char *full_name)
|
||||
assert(name && gid);
|
||||
|
||||
/* Always start with a "/" for the root group. */
|
||||
strcpy(name, "/");
|
||||
strcpy(name, NC_GROUP_NAME);
|
||||
|
||||
/* Get the ncids for all generations. */
|
||||
gid[0] = ncid;
|
||||
@ -380,7 +384,7 @@ NC4_inq_grp_parent(int ncid, int *parent_ncid)
|
||||
if (grp->parent)
|
||||
{
|
||||
if (parent_ncid)
|
||||
*parent_ncid = grp->nc4_info->controller->ext_ncid | grp->parent->nc_grpid;
|
||||
*parent_ncid = grp->nc4_info->controller->ext_ncid | grp->parent->hdr.id;
|
||||
}
|
||||
else
|
||||
return NC_ENOGRP;
|
||||
@ -421,9 +425,8 @@ NC4_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid)
|
||||
|
||||
/* Copy full_name because strtok messes with the value it works
|
||||
* with, and we don't want to mess up full_name. */
|
||||
if (!(full_name_cpy = malloc(strlen(full_name) + 1)))
|
||||
if (!(full_name_cpy = strdup(full_name)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(full_name_cpy, full_name);
|
||||
|
||||
/* Get the first part of the name. */
|
||||
if (!(cp = strtok(full_name_cpy, "/")))
|
||||
@ -491,12 +494,12 @@ NC4_inq_varids(int ncid, int *nvars, int *varids)
|
||||
|
||||
/* This is a netCDF-4 group. Round up them doggies and count
|
||||
* 'em. The list is in correct (i.e. creation) order. */
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
for (i=0; i < ncindexsize(grp->vars); i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,i);
|
||||
if (!var) continue;
|
||||
if (varids)
|
||||
varids[num_vars] = var->varid;
|
||||
varids[num_vars] = var->hdr.id;
|
||||
num_vars++;
|
||||
}
|
||||
|
||||
@ -559,28 +562,34 @@ NC4_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents)
|
||||
assert(h5);
|
||||
|
||||
/* First count them. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
num++;
|
||||
if (include_parents)
|
||||
num = ncindexcount(grp->dim);
|
||||
if (include_parents) {
|
||||
for (g = grp->parent; g; g = g->parent)
|
||||
for (dim = g->dim; dim; dim = dim->l.next)
|
||||
num++;
|
||||
num += ncindexcount(g->dim);
|
||||
}
|
||||
|
||||
/* If the user wants the dimension ids, get them. */
|
||||
if (dimids)
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
|
||||
/* Get dimension ids from this group. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
dimids[n++] = dim->dimid;
|
||||
for(i=0;i<ncindexsize(grp->dim);i++) {
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
|
||||
if(dim == NULL) continue;
|
||||
dimids[n++] = dim->hdr.id;
|
||||
}
|
||||
|
||||
/* Get dimension ids from parent groups. */
|
||||
if (include_parents)
|
||||
for (g = grp->parent; g; g = g->parent)
|
||||
for (dim = g->dim; dim; dim = dim->l.next)
|
||||
dimids[n++] = dim->dimid;
|
||||
|
||||
for (g = grp->parent; g; g = g->parent) {
|
||||
for(i=0;i<ncindexsize(g->dim);i++) {
|
||||
dim = (NC_DIM_INFO_T*)ncindexith(g->dim,i);
|
||||
if(dim == NULL) continue;
|
||||
dimids[n++] = dim->hdr.id;
|
||||
}
|
||||
}
|
||||
qsort(dimids, num, sizeof(int), int_cmp);
|
||||
}
|
||||
|
||||
|
455
libsrc4/nc4hdf.c
455
libsrc4/nc4hdf.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,10 +16,10 @@
|
||||
#include "nc4internal.h"
|
||||
#include "nc4dispatch.h"
|
||||
|
||||
#define NUM_ATOMIC_TYPES 13 /**< Number of netCDF atomic types. */
|
||||
#define NUM_ATOMIC_TYPES (NC_MAX_ATOMIC_TYPE+1) /**< Number of netCDF atomic types. */
|
||||
|
||||
/** @internal Names of atomic types. */
|
||||
char atomic_name[NUM_ATOMIC_TYPES][NC_MAX_NAME + 1] = {"none", "byte", "char",
|
||||
char* nc4_atomic_name[NUM_ATOMIC_TYPES] = {"none", "byte", "char",
|
||||
"short", "int", "float",
|
||||
"double", "ubyte",
|
||||
"ushort", "uint",
|
||||
@ -93,12 +93,12 @@ NC4_inq_type_equal(int ncid1, nc_type typeid1, int ncid2,
|
||||
/* Not atomic types - so find type1 and type2 information. */
|
||||
if ((retval = nc4_find_nc4_grp(ncid1, &grpone)))
|
||||
return retval;
|
||||
if (!(type1 = nc4_rec_find_nc_type(grpone->nc4_info->root_grp,
|
||||
if (!(type1 = nc4_rec_find_nc_type(grpone->nc4_info,
|
||||
typeid1)))
|
||||
return NC_EBADTYPE;
|
||||
if ((retval = nc4_find_nc4_grp(ncid2, &grptwo)))
|
||||
return retval;
|
||||
if (!(type2 = nc4_rec_find_nc_type(grptwo->nc4_info->root_grp,
|
||||
if (!(type2 = nc4_rec_find_nc_type(grptwo->nc4_info,
|
||||
typeid2)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
@ -139,7 +139,7 @@ NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp)
|
||||
|
||||
/* Handle atomic types. */
|
||||
for (i = 0; i < NUM_ATOMIC_TYPES; i++)
|
||||
if (!strcmp(name, atomic_name[i]))
|
||||
if (!strcmp(name, nc4_atomic_name[i]))
|
||||
{
|
||||
if (typeidp)
|
||||
*typeidp = i;
|
||||
@ -165,21 +165,22 @@ NC4_inq_typeid(int ncid, const char *name, nc_type *typeidp)
|
||||
return retval;
|
||||
}
|
||||
/* Is the type in this group? If not, search parents. */
|
||||
for (grptwo = grp; grptwo; grptwo = grptwo->parent)
|
||||
for (type = grptwo->type; type; type = type->l.next)
|
||||
if (!strcmp(norm_name, type->name))
|
||||
for (grptwo = grp; grptwo; grptwo = grptwo->parent) {
|
||||
type = (NC_TYPE_INFO_T*)ncindexlookup(grptwo->type,norm_name);
|
||||
if(type)
|
||||
{
|
||||
if (typeidp)
|
||||
*typeidp = type->nc_typeid;
|
||||
*typeidp = type->hdr.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Still didn't find type? Search file recursively, starting at the
|
||||
* root group. */
|
||||
if (!type)
|
||||
if ((type = nc4_rec_find_named_type(grp->nc4_info->root_grp, norm_name)))
|
||||
if (typeidp)
|
||||
*typeidp = type->nc_typeid;
|
||||
*typeidp = type->hdr.id;
|
||||
|
||||
free(norm_name);
|
||||
|
||||
@ -220,13 +221,16 @@ NC4_inq_typeids(int ncid, int *ntypes, int *typeids)
|
||||
assert(h5 && grp);
|
||||
|
||||
/* Count types. */
|
||||
if (grp->type)
|
||||
for (type = grp->type; type; type = type->l.next)
|
||||
if (grp->type) {
|
||||
int i;
|
||||
for(i=0;i<ncindexsize(grp->type);i++)
|
||||
{
|
||||
if((type = (NC_TYPE_INFO_T*)ncindexith(grp->type,i)) == NULL) continue;
|
||||
if (typeids)
|
||||
typeids[num] = type->nc_typeid;
|
||||
typeids[num] = type->hdr.id;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give the count to the user. */
|
||||
if (ntypes)
|
||||
@ -284,8 +288,7 @@ add_user_type(int ncid, size_t size, const char *name, nc_type base_typeid,
|
||||
/* No size is provided for vlens or enums, get it from the base type. */
|
||||
if (type_class == NC_VLEN || type_class == NC_ENUM)
|
||||
{
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, base_typeid, 0,
|
||||
&size)))
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, base_typeid, &size)))
|
||||
return retval;
|
||||
}
|
||||
else if (size <= 0)
|
||||
@ -303,12 +306,15 @@ add_user_type(int ncid, size_t size, const char *name, nc_type base_typeid,
|
||||
type->nc_type_class = type_class;
|
||||
if (type_class == NC_VLEN)
|
||||
type->u.v.base_nc_typeid = base_typeid;
|
||||
else if (type_class == NC_ENUM)
|
||||
else if (type_class == NC_ENUM) {
|
||||
type->u.e.base_nc_typeid = base_typeid;
|
||||
type->u.e.enum_member = nclistnew();
|
||||
} else if (type_class == NC_COMPOUND)
|
||||
type->u.c.field = nclistnew();
|
||||
|
||||
/* Return the typeid to the user. */
|
||||
if (typeidp)
|
||||
*typeidp = type->nc_typeid;
|
||||
*typeidp = type->hdr.id;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -332,7 +338,7 @@ NC4_inq_type(int ncid, nc_type typeid1, char *name, size_t *size)
|
||||
{
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_TYPE_INFO_T *type;
|
||||
int atomic_size[NUM_ATOMIC_TYPES] = {0, NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN,
|
||||
static const int atomic_size[NUM_ATOMIC_TYPES] = {0, NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN,
|
||||
NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN,
|
||||
NC_BYTE_LEN, NC_SHORT_LEN, NC_INT_LEN, NC_INT64_LEN,
|
||||
NC_INT64_LEN, NC_STRING_LEN};
|
||||
@ -345,7 +351,7 @@ NC4_inq_type(int ncid, nc_type typeid1, char *name, size_t *size)
|
||||
if (typeid1 < NUM_ATOMIC_TYPES)
|
||||
{
|
||||
if (name)
|
||||
strcpy(name, atomic_name[typeid1]);
|
||||
strcpy(name, nc4_atomic_name[typeid1]);
|
||||
if (size)
|
||||
*size = atomic_size[typeid1];
|
||||
return NC_NOERR;
|
||||
@ -356,11 +362,11 @@ NC4_inq_type(int ncid, nc_type typeid1, char *name, size_t *size)
|
||||
return retval;
|
||||
|
||||
/* Find this type. */
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info->root_grp, typeid1)))
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info, typeid1)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
if (name)
|
||||
strcpy(name, type->name);
|
||||
strcpy(name, type->hdr.name);
|
||||
|
||||
if (size)
|
||||
{
|
||||
@ -471,11 +477,9 @@ NC4_insert_array_compound(int ncid, int typeid1, const char *name,
|
||||
return NC_ETYPDEFINED;
|
||||
|
||||
/* Insert new field into this type's list of fields. */
|
||||
if ((retval = nc4_field_list_add(&type->u.c.field, type->u.c.num_fields,
|
||||
norm_name, offset, 0, 0, field_typeid,
|
||||
if ((retval = nc4_field_list_add(type, norm_name, offset, 0, 0, field_typeid,
|
||||
ndims, dim_sizesp)))
|
||||
return retval;
|
||||
type->u.c.num_fields++;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
@ -511,16 +515,16 @@ NC4_inq_user_type(int ncid, nc_type typeid1, char *name, size_t *size,
|
||||
return retval;
|
||||
|
||||
/* Find this type. */
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info->root_grp, typeid1)))
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info, typeid1)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Count the number of fields. */
|
||||
if (nfieldsp)
|
||||
{
|
||||
if (type->nc_type_class == NC_COMPOUND)
|
||||
*nfieldsp = type->u.c.num_fields;
|
||||
*nfieldsp = nclistlength(type->u.c.field);
|
||||
else if (type->nc_type_class == NC_ENUM)
|
||||
*nfieldsp = type->u.e.num_members;
|
||||
*nfieldsp = nclistlength(type->u.e.enum_member);
|
||||
else
|
||||
*nfieldsp = 0;
|
||||
}
|
||||
@ -536,7 +540,7 @@ NC4_inq_user_type(int ncid, nc_type typeid1, char *name, size_t *size,
|
||||
*size = type->size;
|
||||
}
|
||||
if (name)
|
||||
strcpy(name, type->name);
|
||||
strcpy(name, type->hdr.name);
|
||||
|
||||
/* VLENS and ENUMs have a base type - that is, they type they are
|
||||
* arrays of or enums of. */
|
||||
@ -590,15 +594,15 @@ NC4_inq_compound_field(int ncid, nc_type typeid1, int fieldid, char *name,
|
||||
return retval;
|
||||
|
||||
/* Find this type. */
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info->root_grp, typeid1)))
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info, typeid1)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Find the field. */
|
||||
for (field = type->u.c.field; field; field = field->l.next)
|
||||
if (field->fieldid == fieldid)
|
||||
field = (NC_FIELD_INFO_T*)nclistget(type->u.c.field,fieldid);
|
||||
if(field)
|
||||
{
|
||||
if (name)
|
||||
strcpy(name, field->name);
|
||||
strcpy(name, field->hdr.name);
|
||||
if (offsetp)
|
||||
*offsetp = field->offset;
|
||||
if (field_typeidp)
|
||||
@ -664,6 +668,7 @@ NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fi
|
||||
NC_FIELD_INFO_T *field;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
LOG((2, "nc_inq_compound_fieldindex: ncid 0x%x typeid %d name %s",
|
||||
ncid, typeid1, name));
|
||||
@ -685,15 +690,18 @@ NC4_inq_compound_fieldindex(int ncid, nc_type typeid1, const char *name, int *fi
|
||||
return retval;
|
||||
|
||||
/* Find the field with this name. */
|
||||
for (field = type->u.c.field; field; field = field->l.next)
|
||||
if (!strcmp(field->name, norm_name))
|
||||
for(i=0;i<nclistlength(type->u.c.field);i++) {
|
||||
if((field = (NC_FIELD_INFO_T*)nclistget(type->u.c.field,i)) == NULL) continue;
|
||||
if (!strcmp(field->hdr.name, norm_name))
|
||||
break;
|
||||
field = NULL; /* because this is the indicator of not found */
|
||||
}
|
||||
|
||||
if (!field)
|
||||
return NC_EBADFIELD;
|
||||
|
||||
if (fieldidp)
|
||||
*fieldidp = field->fieldid;
|
||||
*fieldidp = field->hdr.id;
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
@ -789,6 +797,7 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
|
||||
long long ll_val;
|
||||
int i;
|
||||
int retval;
|
||||
int found;
|
||||
|
||||
LOG((3, "nc_inq_enum_ident: xtype %d value %d\n", xtype, value));
|
||||
|
||||
@ -797,7 +806,7 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
|
||||
return retval;
|
||||
|
||||
/* Find this type. */
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info->root_grp, xtype)))
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info, xtype)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Complain if they are confused about the type. */
|
||||
@ -805,9 +814,9 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Move to the desired enum member in the list. */
|
||||
enum_member = type->u.e.enum_member;
|
||||
for (i = 0; i < type->u.e.num_members; i++)
|
||||
for (found = 0, i = 0; i < nclistlength(type->u.e.enum_member); i++)
|
||||
{
|
||||
if((enum_member = (NC_ENUM_MEMBER_INFO_T*)nclistget(type->u.e.enum_member,i)) == NULL) continue;
|
||||
switch (type->u.e.base_nc_typeid)
|
||||
{
|
||||
case NC_BYTE:
|
||||
@ -840,14 +849,13 @@ NC4_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier)
|
||||
{
|
||||
if (identifier)
|
||||
strcpy(identifier, enum_member->name);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
enum_member = enum_member->l.next;
|
||||
}
|
||||
|
||||
/* If we didn't find it, life sucks for us. :-( */
|
||||
if (i == type->u.e.num_members)
|
||||
if (!found)
|
||||
return NC_EINVAL;
|
||||
|
||||
return NC_NOERR;
|
||||
@ -876,7 +884,6 @@ NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_TYPE_INFO_T *type;
|
||||
NC_ENUM_MEMBER_INFO_T *enum_member;
|
||||
int i;
|
||||
int retval;
|
||||
|
||||
LOG((2, "nc_inq_enum_member: ncid 0x%x typeid %d", ncid, typeid1));
|
||||
@ -886,21 +893,18 @@ NC4_inq_enum_member(int ncid, nc_type typeid1, int idx, char *identifier,
|
||||
return retval;
|
||||
|
||||
/* Find this type. */
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info->root_grp, typeid1)))
|
||||
if (!(type = nc4_rec_find_nc_type(grp->nc4_info, typeid1)))
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Complain if they are confused about the type. */
|
||||
if (type->nc_type_class != NC_ENUM)
|
||||
return NC_EBADTYPE;
|
||||
|
||||
/* Check index. */
|
||||
if (idx >= type->u.e.num_members)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Move to the desired enum member in the list. */
|
||||
enum_member = type->u.e.enum_member;
|
||||
for (i = 0; i < idx; i++)
|
||||
enum_member = enum_member->l.next;
|
||||
/* Check index. */
|
||||
enum_member = (NC_ENUM_MEMBER_INFO_T*)nclistget(type->u.e.enum_member,idx);
|
||||
if(enum_member == NULL)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Give the people what they want. */
|
||||
if (identifier)
|
||||
@ -961,10 +965,9 @@ NC4_insert_enum(int ncid, nc_type typeid1, const char *identifier,
|
||||
return NC_ETYPDEFINED;
|
||||
|
||||
/* Insert new field into this type's list of fields. */
|
||||
if ((retval = nc4_enum_member_add(&type->u.e.enum_member, type->size,
|
||||
if ((retval = nc4_enum_member_add(type, type->size,
|
||||
norm_name, value)))
|
||||
return retval;
|
||||
type->u.e.num_members++;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
222
libsrc4/nc4var.c
222
libsrc4/nc4var.c
@ -53,7 +53,7 @@ nc4_reopen_dataset(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
return NC_EHDFERR;
|
||||
if (H5Dclose(var->hdf_datasetid) < 0)
|
||||
return NC_EHDFERR;
|
||||
if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->name,
|
||||
if ((var->hdf_datasetid = H5Dopen2(grp->hdf_grpid, var->hdr.name,
|
||||
access_pid)) < 0)
|
||||
return NC_EHDFERR;
|
||||
if (H5Pclose(access_pid) < 0)
|
||||
@ -101,10 +101,10 @@ NC4_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
assert(var && var->varid == varid);
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(!var)
|
||||
return NC_ENOTVAR;
|
||||
assert(var && var->hdr.id == varid);
|
||||
|
||||
/* Set the values. */
|
||||
var->chunk_cache_size = size;
|
||||
@ -183,10 +183,10 @@ NC4_get_var_chunk_cache(int ncid, int varid, size_t *sizep,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
assert(var && var->varid == varid);
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(!var)
|
||||
return NC_ENOTVAR;
|
||||
assert(var && var->hdr.id == varid);
|
||||
|
||||
/* Give the user what they want. */
|
||||
if (sizep)
|
||||
@ -258,7 +258,7 @@ check_chunksizes(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var, const size_t *chunksize
|
||||
int d;
|
||||
int retval;
|
||||
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->nc_typeid, 0, &type_len)))
|
||||
if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->hdr.id, &type_len)))
|
||||
return retval;
|
||||
if (var->type_info->nc_type_class == NC_VLEN)
|
||||
dprod = (double)sizeof(hvl_t);
|
||||
@ -331,7 +331,7 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
suggested_size = DEFAULT_CHUNK_SIZE / type_size;
|
||||
var->chunksizes[0] = suggested_size / type_size;
|
||||
LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
|
||||
"chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[0]));
|
||||
"chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[0]));
|
||||
}
|
||||
if (var->ndims > 1 && var->ndims == num_unlim) { /* all dims unlimited */
|
||||
suggested_size = pow((double)DEFAULT_CHUNK_SIZE/type_size, 1.0/(double)(var->ndims));
|
||||
@ -339,7 +339,7 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
{
|
||||
var->chunksizes[d] = suggested_size ? suggested_size : 1;
|
||||
LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
|
||||
"chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
|
||||
"chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
suggested_size = var->dim[d]->len;
|
||||
var->chunksizes[d] = suggested_size ? suggested_size : 1;
|
||||
LOG((4, "%s: name %s dim %d DEFAULT_CHUNK_SIZE %d num_values %f type_size %d "
|
||||
"chunksize %ld", __func__, var->name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
|
||||
"chunksize %ld", __func__, var->hdr.name, d, DEFAULT_CHUNK_SIZE, num_values, type_size, var->chunksizes[d]));
|
||||
}
|
||||
|
||||
#ifdef LOGGING
|
||||
@ -396,45 +396,6 @@ nc4_find_default_chunksizes2(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Grow the variable array.
|
||||
*
|
||||
* @param grp Pointer to the group info.
|
||||
* @param var Pointer to the var info.
|
||||
*
|
||||
* @returns ::NC_NOERR No error.
|
||||
* @returns ::NC_ENOMEM Out of memory.
|
||||
* @author Dennis Heimbigner
|
||||
*/
|
||||
int
|
||||
nc4_vararray_add(NC_GRP_INFO_T *grp, NC_VAR_INFO_T *var)
|
||||
{
|
||||
NC_VAR_INFO_T **vp = NULL;
|
||||
|
||||
if (grp->vars.nalloc == 0) {
|
||||
assert(grp->vars.nelems == 0);
|
||||
vp = (NC_VAR_INFO_T **) malloc(NC_ARRAY_GROWBY * sizeof(NC_VAR_INFO_T *));
|
||||
if(vp == NULL)
|
||||
return NC_ENOMEM;
|
||||
grp->vars.value = vp;
|
||||
grp->vars.nalloc = NC_ARRAY_GROWBY;
|
||||
}
|
||||
else if(grp->vars.nelems +1 > grp->vars.nalloc) {
|
||||
vp = (NC_VAR_INFO_T **) realloc(grp->vars.value,
|
||||
(grp->vars.nalloc + NC_ARRAY_GROWBY) * sizeof(NC_VAR_INFO_T *));
|
||||
if(vp == NULL)
|
||||
return NC_ENOMEM;
|
||||
grp->vars.value = vp;
|
||||
grp->vars.nalloc += NC_ARRAY_GROWBY;
|
||||
}
|
||||
|
||||
assert(var->varid == grp->vars.nelems);
|
||||
grp->vars.value[grp->vars.nelems] = var;
|
||||
grp->vars.nelems++;
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal This is called when a new netCDF-4 variable is defined
|
||||
* with nc_def_var().
|
||||
@ -544,9 +505,13 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
* struct. */
|
||||
if (xtype <= NC_STRING)
|
||||
{
|
||||
if (!(type_info = calloc(1, sizeof(NC_TYPE_INFO_T))))
|
||||
BAIL(NC_ENOMEM);
|
||||
type_info->nc_typeid = xtype;
|
||||
size_t len;
|
||||
char name[NC_MAX_NAME+1];
|
||||
nc4_get_typelen_mem(h5,xtype,&len);
|
||||
memcpy(name,nc4_atomic_name[xtype],NC_MAX_NAME);
|
||||
name[NC_MAX_NAME] = '\0';
|
||||
if((retval = nc4_type_new(grp,len,name,xtype,&type_info)))
|
||||
BAIL(retval);
|
||||
type_info->endianness = NC_ENDIAN_NATIVE;
|
||||
if ((retval = nc4_get_hdf_typeid(h5, xtype, &type_info->hdf_typeid,
|
||||
type_info->endianness)))
|
||||
@ -554,8 +519,7 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
if ((type_info->native_hdf_typeid = H5Tget_native_type(type_info->hdf_typeid,
|
||||
H5T_DIR_DEFAULT)) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
if ((retval = nc4_get_typelen_mem(h5, type_info->nc_typeid, 0,
|
||||
&type_info->size)))
|
||||
if ((retval = nc4_get_typelen_mem(h5, type_info->hdr.id, &type_info->size)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Set the "class" of the type */
|
||||
@ -594,36 +558,15 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
}
|
||||
|
||||
/* Create a new var and fill in some HDF5 cache setting values. */
|
||||
if ((retval = nc4_var_add(&var)))
|
||||
if ((retval = nc4_var_list_add(grp, norm_name, ndims, &var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Now fill in the values in the var info structure. */
|
||||
if (!(var->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
|
||||
BAIL(NC_ENOMEM);
|
||||
strcpy(var->name, norm_name);
|
||||
var->hash = hash_fast(norm_name, strlen(norm_name));
|
||||
var->varid = grp->nvars++;
|
||||
var->ndims = ndims;
|
||||
var->is_new_var = NC_TRUE;
|
||||
|
||||
/* Add a var to the variable array, growing it as needed. */
|
||||
if ((retval = nc4_vararray_add(grp, var)))
|
||||
BAIL(retval);
|
||||
|
||||
/* Point to the type, and increment its ref. count */
|
||||
var->type_info = type_info;
|
||||
var->type_info->rc++;
|
||||
type_info = NULL;
|
||||
|
||||
/* Allocate space for dimension information. */
|
||||
if (ndims)
|
||||
{
|
||||
if (!(var->dim = calloc(ndims, sizeof(NC_DIM_INFO_T *))))
|
||||
BAIL(NC_ENOMEM);
|
||||
if (!(var->dimids = calloc(ndims, sizeof(int))))
|
||||
BAIL(NC_ENOMEM);
|
||||
}
|
||||
|
||||
/* Set variables no_fill to match the database default
|
||||
* unless the variable type is variable length (NC_STRING or NC_VLEN)
|
||||
* or is user-defined type.
|
||||
@ -647,7 +590,7 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
BAIL(retval);
|
||||
|
||||
/* Check for dim index 0 having the same name, in the same group */
|
||||
if (d == 0 && dim_grp == grp && dim->hash == var->hash && strcmp(dim->name, norm_name) == 0)
|
||||
if (d == 0 && dim_grp == grp && strcmp(dim->hdr.name, norm_name) == 0)
|
||||
{
|
||||
var->dimscale = NC_TRUE;
|
||||
dim->coord_var = var;
|
||||
@ -668,7 +611,7 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
|
||||
/* Now delete the DIM_WITHOUT_VARIABLE dataset (it will be
|
||||
* recreated later, if necessary). */
|
||||
if (H5Gunlink(grp->hdf_grpid, dim->name) < 0)
|
||||
if (H5Gunlink(grp->hdf_grpid, dim->hdr.name) < 0)
|
||||
BAIL(NC_EDIMMETA);
|
||||
}
|
||||
}
|
||||
@ -685,7 +628,7 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
/* Determine default chunksizes for this variable. (Even for
|
||||
* variables which may be contiguous.) */
|
||||
LOG((4, "allocating array of %d size_t to hold chunksizes for var %s",
|
||||
var->ndims, var->name));
|
||||
var->ndims, var->hdr.name));
|
||||
if (var->ndims)
|
||||
if (!(var->chunksizes = calloc(var->ndims, sizeof(size_t))))
|
||||
BAIL(NC_ENOMEM);
|
||||
@ -703,9 +646,8 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
* is not a coordinate variable. I need to change its HDF5 name,
|
||||
* because the dimension will cause a HDF5 dataset to be created,
|
||||
* and this var has the same name. */
|
||||
for (dim = grp->dim; dim; dim = dim->l.next)
|
||||
if (dim->hash == var->hash && !strcmp(dim->name, norm_name) &&
|
||||
(!var->ndims || dimidsp[0] != dim->dimid))
|
||||
dim = (NC_DIM_INFO_T*)ncindexlookup(grp->dim,norm_name);
|
||||
if (dim && (!var->ndims || dimidsp[0] != dim->hdr.id))
|
||||
{
|
||||
/* Set a different hdf5 name for this variable to avoid name
|
||||
* clash. */
|
||||
@ -728,8 +670,8 @@ NC4_def_var(int ncid, const char *name, nc_type xtype,
|
||||
|
||||
/* Return the varid. */
|
||||
if (varidp)
|
||||
*varidp = var->varid;
|
||||
LOG((4, "new varid %d", var->varid));
|
||||
*varidp = var->hdr.id;
|
||||
LOG((4, "new varid %d", var->hdr.id));
|
||||
|
||||
exit:
|
||||
if (type_info)
|
||||
@ -789,8 +731,6 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var;
|
||||
NC_ATT_INFO_T *att;
|
||||
int natts=0;
|
||||
int d;
|
||||
int retval;
|
||||
|
||||
@ -810,24 +750,22 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
{
|
||||
if (nattsp)
|
||||
{
|
||||
for (att = grp->att; att; att = att->l.next)
|
||||
natts++;
|
||||
*nattsp = natts;
|
||||
*nattsp = ncindexcount(grp->att);
|
||||
}
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/* Find the var. */
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(!var)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
assert(var && var->varid == varid);
|
||||
assert(var && var->hdr.id == varid);
|
||||
|
||||
/* Copy the data to the user's data buffers. */
|
||||
if (name)
|
||||
strcpy(name, var->name);
|
||||
strcpy(name, var->hdr.name);
|
||||
if (xtypep)
|
||||
*xtypep = var->type_info->nc_typeid;
|
||||
*xtypep = var->type_info->hdr.id;
|
||||
if (ndimsp)
|
||||
*ndimsp = var->ndims;
|
||||
if (dimidsp)
|
||||
@ -835,9 +773,7 @@ NC4_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep,
|
||||
dimidsp[d] = var->dimids[d];
|
||||
if (nattsp)
|
||||
{
|
||||
for (att = var->att; att; att = att->l.next)
|
||||
natts++;
|
||||
*nattsp = natts;
|
||||
*nattsp = ncindexcount(var->att);
|
||||
}
|
||||
|
||||
/* Chunking stuff. */
|
||||
@ -983,10 +919,10 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
|
||||
return NC_EPERM;
|
||||
|
||||
/* Find the var. */
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(!var)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
assert(var && var->varid == varid);
|
||||
assert(var && var->hdr.id == varid);
|
||||
|
||||
/* Can't turn on parallel and deflate/fletcher32/szip/shuffle. */
|
||||
if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
|
||||
@ -1099,7 +1035,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
|
||||
/* NC_STRING types may not turn off fill mode. It's disallowed
|
||||
* by HDF5 and will cause a HDF5 error later. */
|
||||
if (*no_fill)
|
||||
if (var->type_info->nc_typeid == NC_STRING)
|
||||
if (var->type_info->hdr.id == NC_STRING)
|
||||
return NC_EINVAL;
|
||||
|
||||
/* Set the no-fill mode. */
|
||||
@ -1114,7 +1050,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
|
||||
{
|
||||
/* Copy the fill_value. */
|
||||
LOG((4, "Copying fill value into metadata for variable %s",
|
||||
var->name));
|
||||
var->hdr.name));
|
||||
|
||||
/* If there's a _FillValue attribute, delete it. */
|
||||
retval = NC4_del_att(ncid, varid, _FillValue);
|
||||
@ -1122,7 +1058,7 @@ nc_def_var_extra(int ncid, int varid, int *shuffle, int *deflate,
|
||||
return retval;
|
||||
|
||||
/* Create a _FillValue attribute. */
|
||||
if ((retval = nc_put_att(ncid, varid, _FillValue, var->type_info->nc_typeid, 1, fill_value)))
|
||||
if ((retval = nc_put_att(ncid, varid, _FillValue, var->type_info->hdr.id, 1, fill_value)))
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1428,11 +1364,10 @@ NC4_def_var_filter(int ncid, int varid, unsigned int id, size_t nparams,
|
||||
assert(nc && grp && h5);
|
||||
|
||||
/* Find the var. */
|
||||
if (varid < 0 || varid >= grp->vars.nelems)
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if(!var)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
assert(var->hdr.id == varid);
|
||||
|
||||
/* Can't turn on parallel and filters */
|
||||
if (nc->mode & (NC_MPIIO | NC_MPIPOSIX)) {
|
||||
@ -1497,8 +1432,6 @@ NC4_inq_varid(int ncid, const char *name, int *varidp)
|
||||
NC_VAR_INFO_T *var;
|
||||
char norm_name[NC_MAX_NAME + 1];
|
||||
int retval;
|
||||
uint32_t nn_hash;
|
||||
int i;
|
||||
|
||||
if (!name)
|
||||
return NC_EINVAL;
|
||||
@ -1515,19 +1448,13 @@ NC4_inq_varid(int ncid, const char *name, int *varidp)
|
||||
if ((retval = nc4_normalize_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
nn_hash = hash_fast(norm_name, strlen(norm_name));
|
||||
|
||||
/* Find var of this name. */
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (nn_hash == var->hash && !(strcmp(var->name, norm_name)))
|
||||
var = (NC_VAR_INFO_T*)ncindexlookup(grp->vars,norm_name);
|
||||
if(var)
|
||||
{
|
||||
*varidp = var->varid;
|
||||
*varidp = var->hdr.id;
|
||||
return NC_NOERR;
|
||||
}
|
||||
}
|
||||
return NC_ENOTVAR;
|
||||
}
|
||||
|
||||
@ -1554,10 +1481,8 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
NC *nc;
|
||||
NC_GRP_INFO_T *grp;
|
||||
NC_HDF5_FILE_INFO_T *h5;
|
||||
NC_VAR_INFO_T *var, *tmp_var;
|
||||
uint32_t nn_hash;
|
||||
NC_VAR_INFO_T *var, *tmpvar;
|
||||
int retval = NC_NOERR;
|
||||
int i;
|
||||
|
||||
if (!name)
|
||||
return NC_EINVAL;
|
||||
@ -1583,25 +1508,20 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
if ((retval = NC_check_name(name)))
|
||||
return retval;
|
||||
|
||||
/* Check if name is in use, and retain a pointer to the correct variable */
|
||||
nn_hash = hash_fast(name, strlen(name));
|
||||
tmp_var = NULL;
|
||||
for (i=0; i < grp->vars.nelems; i++)
|
||||
{
|
||||
var = grp->vars.value[i];
|
||||
if (!var) continue;
|
||||
if (nn_hash == var->hash && !strncmp(var->name, name, NC_MAX_NAME))
|
||||
return NC_ENAMEINUSE;
|
||||
if (var->varid == varid)
|
||||
tmp_var = var;
|
||||
}
|
||||
if (!tmp_var)
|
||||
/* Get the variable wrt varid */
|
||||
var = (NC_VAR_INFO_T*)ncindexith(grp->vars,varid);
|
||||
if (!var)
|
||||
return NC_ENOTVAR;
|
||||
var = tmp_var;
|
||||
|
||||
/* Check if new name is in use; note that renaming to same name is still an error
|
||||
according to the nc_test/test_write.c code. Why?*/
|
||||
tmpvar = (NC_VAR_INFO_T*)ncindexlookup(grp->vars,name);
|
||||
if(tmpvar != NULL)
|
||||
return NC_ENAMEINUSE;
|
||||
|
||||
/* If we're not in define mode, new name must be of equal or
|
||||
less size, if strict nc3 rules are in effect for this . */
|
||||
if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(var->name) &&
|
||||
if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(var->hdr.name) &&
|
||||
(h5->cmode & NC_CLASSIC_MODEL))
|
||||
return NC_ENOTINDEFINE;
|
||||
|
||||
@ -1614,25 +1534,27 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
* so, it must be deleted. */
|
||||
if (var->ndims && var->dim[0]->hdf_dimscaleid)
|
||||
{
|
||||
if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->dimid, var->dim[0])))
|
||||
if ((retval = delete_existing_dimscale_dataset(grp, var->dim[0]->hdr.id, var->dim[0])))
|
||||
return retval;
|
||||
}
|
||||
|
||||
LOG((3, "Moving dataset %s to %s", var->name, name));
|
||||
if (H5Gmove(grp->hdf_grpid, var->name, name) < 0)
|
||||
LOG((3, "Moving dataset %s to %s", var->hdr.name, name));
|
||||
if (H5Gmove(grp->hdf_grpid, var->hdr.name, name) < 0)
|
||||
BAIL(NC_EHDFERR);
|
||||
}
|
||||
|
||||
/* Now change the name in our metadata. */
|
||||
free(var->name);
|
||||
if (!(var->name = malloc((strlen(name) + 1) * sizeof(char))))
|
||||
free(var->hdr.name);
|
||||
if (!(var->hdr.name = strdup(name)))
|
||||
return NC_ENOMEM;
|
||||
strcpy(var->name, name);
|
||||
var->hash = nn_hash;
|
||||
LOG((3, "var is now %s", var->name));
|
||||
LOG((3, "var is now %s", var->hdr.name));
|
||||
var->hdr.hashkey = NC_hashmapkey(var->hdr.name,strlen(var->hdr.name)); /* Fix hash key */
|
||||
|
||||
if(!ncindexrebuild(grp->vars))
|
||||
return NC_EINTERNAL;
|
||||
|
||||
/* Check if this was a coordinate variable previously, but names are different now */
|
||||
if (var->dimscale && strcmp(var->name, var->dim[0]->name))
|
||||
if (var->dimscale && strcmp(var->hdr.name, var->dim[0]->hdr.name))
|
||||
{
|
||||
/* Break up the coordinate variable */
|
||||
if ((retval = nc4_break_coord_var(grp, var, var->dim[0])))
|
||||
@ -1654,7 +1576,7 @@ NC4_rename_var(int ncid, int varid, const char *name)
|
||||
*/
|
||||
if ((retval = nc4_find_dim(grp, var->dimids[0], &dim, &dim_grp)))
|
||||
return retval;
|
||||
if (!strcmp(dim->name, name) && dim_grp == grp)
|
||||
if (!strcmp(dim->hdr.name, name) && dim_grp == grp)
|
||||
{
|
||||
/* Reform the coordinate variable */
|
||||
if ((retval = nc4_reform_coord_var(grp, var, dim)))
|
||||
@ -1717,7 +1639,7 @@ NC4_var_par_access(int ncid, int varid, int par_access)
|
||||
return NC_ENOTVAR;
|
||||
var = grp->vars.value[varid];
|
||||
if (!var) return NC_ENOTVAR;
|
||||
assert(var->varid == varid);
|
||||
assert(var->hdr.id == varid);
|
||||
|
||||
if (par_access)
|
||||
var->parallel_access = NC_COLLECTIVE;
|
||||
|
409
libsrc4/ncindex.c
Normal file
409
libsrc4/ncindex.c
Normal file
@ -0,0 +1,409 @@
|
||||
/*
|
||||
Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
|
||||
See LICENSE.txt for license information.
|
||||
*/
|
||||
|
||||
/** \file \internal
|
||||
Internal netcdf-4 functions.
|
||||
|
||||
This file contains functions for manipulating ncindex objects.
|
||||
|
||||
Warning: This code depends critically on the assumption that
|
||||
|void*| == |uintptr_t|
|
||||
|
||||
*/
|
||||
|
||||
/* Define this for debug so that table sizes are small */
|
||||
#undef SMALLTABLE
|
||||
#undef NCNOHASH
|
||||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#include "nc4internal.h"
|
||||
#include "ncindex.h"
|
||||
|
||||
#ifdef SMALLTABLE
|
||||
/* Keep the table sizes small initially */
|
||||
#define DFALTTABLESIZE 7
|
||||
#else
|
||||
#define DFALTTABLESIZE 37
|
||||
#endif
|
||||
|
||||
/* Hack to access internal state of a hashmap. Use with care */
|
||||
/* Convert an entry from ACTIVE to DELETED;
|
||||
Return 0 if not found.
|
||||
*/
|
||||
extern int NC_hashmapdeactivate(NC_hashmap*, uintptr_t data);
|
||||
|
||||
#ifndef NCNOHASH
|
||||
extern void printhashmap(NC_hashmap*);
|
||||
#endif
|
||||
|
||||
/* Locate object by name in an NCindex */
|
||||
NC_OBJ*
|
||||
ncindexlookup(NCindex* ncindex, const char* name)
|
||||
{
|
||||
NC_OBJ* obj = NULL;
|
||||
if(ncindex == NULL || name == NULL)
|
||||
return NULL;
|
||||
{
|
||||
#ifndef NCNOHASH
|
||||
uintptr_t index;
|
||||
assert(ncindex->map != NULL);
|
||||
if(!NC_hashmapget(ncindex->map,(void*)name,strlen(name),&index))
|
||||
return NULL; /* not present */
|
||||
obj = (NC_OBJ*)nclistget(ncindex->list,(size_t)index);
|
||||
#else
|
||||
int i;
|
||||
for(i=0;i<nclistlength(ncindex->list);i++) {
|
||||
NC_OBJ* o = (NC_OBJ*)ncindex->list->content[i];
|
||||
if(strcmp(o->name,name)==0) return o;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* Get ith object in the vector */
|
||||
NC_OBJ*
|
||||
ncindexith(NCindex* index, size_t i)
|
||||
{
|
||||
if(index == NULL) return NULL;
|
||||
assert(index->list != NULL);
|
||||
return nclistget(index->list,i);
|
||||
}
|
||||
|
||||
/* See if x is contained in the index */
|
||||
/* Return vector position if in index, otherwise return -1. */
|
||||
int
|
||||
ncindexfind(NCindex* index, NC_OBJ* nco)
|
||||
{
|
||||
int i;
|
||||
NClist* list;
|
||||
if(index == NULL || nco == NULL) return -1;
|
||||
list = index->list;
|
||||
for(i=0;i<nclistlength(list);i++) {
|
||||
NC_OBJ* o = (NC_OBJ*)list->content[i];
|
||||
if(nco == o) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add object to the end of the vector, also insert into the hashmaps */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
int
|
||||
ncindexadd(NCindex* ncindex, NC_OBJ* obj)
|
||||
{
|
||||
if(ncindex == NULL) return 0;
|
||||
#ifndef NCNOHASH
|
||||
{
|
||||
uintptr_t index; /*Note not the global id */
|
||||
index = (uintptr_t)nclistlength(ncindex->list);
|
||||
NC_hashmapadd(ncindex->map,index,(void*)obj->name,strlen(obj->name));
|
||||
}
|
||||
#endif
|
||||
if(!nclistpush(ncindex->list,obj))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Insert object at ith position of the vector, also insert into the hashmaps; */
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
int
|
||||
ncindexset(NCindex* ncindex, size_t i, NC_OBJ* obj)
|
||||
{
|
||||
if(ncindex == NULL) return 0;
|
||||
if(!nclistset(ncindex->list,i,obj)) return 0;
|
||||
#ifndef NCNOHASH
|
||||
{
|
||||
uintptr_t index = (uintptr_t)i;
|
||||
NC_hashmapadd(ncindex->map,index,(void*)obj->name,strlen(obj->name));
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove ith object from the index;
|
||||
* Return 1 if ok, 0 otherwise.*/
|
||||
int
|
||||
ncindexidel(NCindex* index, size_t i)
|
||||
{
|
||||
if(index == NULL) return 0;
|
||||
nclistremove(index->list,i);
|
||||
#ifndef NCNOHASH
|
||||
/* Remove from the hash map by deactivating its entry */
|
||||
if(!NC_hashmapdeactivate(index->map,(uintptr_t)i))
|
||||
return 0; /* not present */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*Return a duplicate of the index's vector */
|
||||
/* Return list if ok, NULL otherwise.*/
|
||||
NC_OBJ**
|
||||
ncindexdup(NCindex* index)
|
||||
{
|
||||
if(index == NULL || nclistlength(index->list) == 0)
|
||||
return NULL;
|
||||
return (NC_OBJ**)nclistdup(index->list);
|
||||
}
|
||||
|
||||
/* Count the non-null entries in an NCindex */
|
||||
int
|
||||
ncindexcount(NCindex* index)
|
||||
{
|
||||
int count = 0;
|
||||
int i;
|
||||
for(i=0;i<ncindexsize(index);i++) {
|
||||
if(ncindexith(index,i) != NULL) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
Rebuild the list map by rehashing all entries
|
||||
using their current, possibly changed id and name;
|
||||
also recompute their hashkey.
|
||||
*/
|
||||
/* Return 1 if ok, 0 otherwise.*/
|
||||
int
|
||||
ncindexrebuild(NCindex* index)
|
||||
{
|
||||
#ifndef NCNOHASH
|
||||
size_t i;
|
||||
size_t size = nclistlength(index->list);
|
||||
NC_OBJ** contents = (NC_OBJ**)nclistextract(index->list);
|
||||
/* Reset the index map and list*/
|
||||
nclistfree(index->list);
|
||||
index->list = nclistnew();
|
||||
nclistsetalloc(index->list,size);
|
||||
NC_hashmapfree(index->map);
|
||||
index->map = NC_hashmapnew(size);
|
||||
/* Now, reinsert all the attributes except NULLs */
|
||||
for(i=0;i<size;i++) {
|
||||
NC_OBJ* tmp = contents[i];
|
||||
if(tmp == NULL) continue; /* ignore */
|
||||
if(!ncindexadd(index,tmp))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Free a list map */
|
||||
int
|
||||
ncindexfree(NCindex* index)
|
||||
{
|
||||
if(index == NULL) return 1;
|
||||
nclistfree(index->list);
|
||||
NC_hashmapfree(index->map);
|
||||
free(index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a new index */
|
||||
NCindex*
|
||||
ncindexnew(size_t size0)
|
||||
{
|
||||
NCindex* index = NULL;
|
||||
size_t size = (size0 == 0 ? DFALTTABLESIZE : size0);
|
||||
index = calloc(1,sizeof(NCindex));
|
||||
if(index == NULL) return NULL;
|
||||
index->list = nclistnew();
|
||||
if(index->list == NULL) {ncindexfree(index); return NULL;}
|
||||
nclistsetalloc(index->list,size);
|
||||
#ifndef NCNOHASH
|
||||
index->map = NC_hashmapnew(size);
|
||||
if(index->map == NULL) {ncindexfree(index); return NULL;}
|
||||
#endif
|
||||
return index;
|
||||
}
|
||||
|
||||
#ifndef NCNOHASH
|
||||
/* Debug: handle the data key part */
|
||||
static const char*
|
||||
keystr(NC_hentry* e)
|
||||
{
|
||||
if(e->keysize < sizeof(uintptr_t))
|
||||
return (const char*)(&e->key);
|
||||
else
|
||||
return (const char*)(e->key);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ncindexverify(NCindex* lm, int dump)
|
||||
{
|
||||
size_t i;
|
||||
NClist* l = lm->list;
|
||||
int nerrs = 0;
|
||||
#ifndef NCNOHASH
|
||||
size_t m;
|
||||
#endif
|
||||
|
||||
if(lm == NULL) {
|
||||
fprintf(stderr,"index: <empty>\n");
|
||||
return 1;
|
||||
}
|
||||
if(dump) {
|
||||
fprintf(stderr,"-------------------------\n");
|
||||
#ifndef NCNOHASH
|
||||
if(lm->map->active == 0) {
|
||||
fprintf(stderr,"hash: <empty>\n");
|
||||
goto next1;
|
||||
}
|
||||
for(i=0;i < lm->map->alloc; i++) {
|
||||
NC_hentry* e = &lm->map->table[i];
|
||||
if(e->flags != 1) continue;
|
||||
fprintf(stderr,"hash: %ld: data=%lu key=%s\n",(unsigned long)i,(unsigned long)e->data,keystr(e));
|
||||
fflush(stderr);
|
||||
}
|
||||
next1:
|
||||
#endif
|
||||
if(nclistlength(l) == 0) {
|
||||
fprintf(stderr,"list: <empty>\n");
|
||||
goto next2;
|
||||
}
|
||||
for(i=0;i < nclistlength(l); i++) {
|
||||
const char** a = (const char**)nclistget(l,i);
|
||||
fprintf(stderr,"list: %ld: name=%s\n",(unsigned long)i,*a);
|
||||
fflush(stderr);
|
||||
}
|
||||
fprintf(stderr,"-------------------------\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
next2:
|
||||
#ifndef NCNOHASH
|
||||
/* Need to verify that every entry in map is also in vector and vice-versa */
|
||||
|
||||
/* Verify that map entry points to same-named entry in vector */
|
||||
for(m=0;m < lm->map->alloc; m++) {
|
||||
NC_hentry* e = &lm->map->table[m];
|
||||
char** object = NULL;
|
||||
char* oname = NULL;
|
||||
uintptr_t udata = (uintptr_t)e->data;
|
||||
if((e->flags & 1) == 0) continue;
|
||||
object = nclistget(l,(size_t)udata);
|
||||
if(object == NULL) {
|
||||
fprintf(stderr,"bad data: %d: %lu\n",(int)m,(unsigned long)udata);
|
||||
nerrs++;
|
||||
} else {
|
||||
oname = *object;
|
||||
if(strcmp(oname,keystr(e)) != 0) {
|
||||
fprintf(stderr,"name mismatch: %d: %lu: hash=%s list=%s\n",
|
||||
(int)m,(unsigned long)udata,keystr(e),oname);
|
||||
nerrs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Walk vector and mark corresponding hash entry*/
|
||||
if(nclistlength(l) == 0 || lm->map->active == 0)
|
||||
goto done; /* cannot verify */
|
||||
for(i=0;i < nclistlength(l); i++) {
|
||||
int match;
|
||||
const char** xp = (const char**)nclistget(l,i);
|
||||
/* Walk map looking for *xp */
|
||||
for(match=0,m=0;m < lm->map->active; m++) {
|
||||
NC_hentry* e = &lm->map->table[m];
|
||||
if((e->flags & 1) == 0) continue;
|
||||
if(strcmp(keystr(e),*xp)==0) {
|
||||
if((e->flags & 128) == 128) {
|
||||
fprintf(stderr,"%ld: %s already in map at %ld\n",(unsigned long)i,keystr(e),(unsigned long)m);
|
||||
nerrs++;
|
||||
}
|
||||
match = 1;
|
||||
e->flags += 128;
|
||||
}
|
||||
}
|
||||
if(!match) {
|
||||
fprintf(stderr,"mismatch: %d: %s in vector, not in map\n",(int)i,*xp);
|
||||
nerrs++;
|
||||
}
|
||||
}
|
||||
/* Verify that every element in map in in vector */
|
||||
for(m=0;m < lm->map->active; m++) {
|
||||
NC_hentry* e = &lm->map->table[m];
|
||||
if((e->flags & 1) == 0) continue;
|
||||
if((e->flags & 128) == 128) continue;
|
||||
/* We have a hash entry not in the vector */
|
||||
fprintf(stderr,"mismatch: %d: %s->%lu in hash, not in vector\n",(int)m,keystr(e),(unsigned long)e->data);
|
||||
nerrs++;
|
||||
}
|
||||
/* clear the 'touched' flag */
|
||||
for(m=0;m < lm->map->active; m++) {
|
||||
NC_hentry* e = &lm->map->table[m];
|
||||
e->flags &= ~128;
|
||||
}
|
||||
|
||||
done:
|
||||
#endif /*NCNOHASH*/
|
||||
fflush(stderr);
|
||||
return (nerrs > 0 ? 0: 1);
|
||||
}
|
||||
|
||||
static const char*
|
||||
sortname(NC_SORT sort)
|
||||
{
|
||||
switch(sort) {
|
||||
case NCNAT: return "NCNAT";
|
||||
case NCVAR: return "NCVAR";
|
||||
case NCDIM: return "NCDIM";
|
||||
case NCATT: return "NCATT";
|
||||
case NCTYP: return "NCTYP";
|
||||
case NCGRP: return "NCGRP";
|
||||
default: break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void
|
||||
printindexlist(NClist* lm)
|
||||
{
|
||||
int i;
|
||||
if(lm == NULL) {
|
||||
fprintf(stderr,"<empty>\n");
|
||||
return;
|
||||
}
|
||||
for(i=0;i<nclistlength(lm);i++) {
|
||||
NC_OBJ* o = (NC_OBJ*)nclistget(lm,i);
|
||||
if(o == NULL)
|
||||
fprintf(stderr,"[%ld] <null>\n",(unsigned long)i);
|
||||
else
|
||||
fprintf(stderr,"[%ld] sort=%s name=|%s| id=%lu hashkey=%lu\n",
|
||||
(unsigned long)i,sortname(o->sort),o->name,(unsigned long)o->id,(unsigned long)o->hashkey);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NCNOHASH
|
||||
void
|
||||
printindexmap(NCindex* lm)
|
||||
{
|
||||
if(lm == NULL) {
|
||||
fprintf(stderr,"<empty>\n");
|
||||
return;
|
||||
}
|
||||
printhashmap(lm->map);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
printindex(NCindex* lm)
|
||||
{
|
||||
if(lm == NULL) {
|
||||
fprintf(stderr,"<empty>\n");
|
||||
return;
|
||||
}
|
||||
printindexlist(lm->list);
|
||||
#ifndef NCNOHASH
|
||||
printindexmap(lm);
|
||||
#endif
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
# Test c output
|
||||
T=tst_addvar
|
||||
T=tst_diskless2
|
||||
|
||||
ARGS=test_pnetcdf.nc
|
||||
#SRC=error.c test_get.c test_put.c test_read.c test_write.c util.c
|
||||
|
||||
#ARGS=netcdf4
|
||||
|
||||
#CMD=valgrind --leak-check=full
|
||||
#CMD=export NETCDF_LOG_LEVEL=5 ;gdb --args
|
||||
CMD=gdb --args
|
||||
|
||||
PAR=1
|
||||
#PAR=1
|
||||
|
||||
CFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -g -O -I.. -I../include
|
||||
CFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
|
||||
|
||||
ifdef PAR
|
||||
CC=mpicc
|
||||
|
@ -18,10 +18,6 @@
|
||||
#endif
|
||||
#include "error.h"
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#if defined(_CRAY) && !defined(_CRAYIEEE) && !defined(__crayx1)
|
||||
#define CRAYFLOAT 1 /* CRAY Floating point */
|
||||
#elif defined(_SX) && defined(_FLOAT2) /* NEC SUPER-UX in CRAY mode */
|
||||
|
@ -14,6 +14,16 @@ redistribution conditions.
|
||||
#include <stdlib.h>
|
||||
#include <netcdf.h>
|
||||
|
||||
/*
|
||||
netcdf tst_diskless {
|
||||
variables:
|
||||
int resistor_value;
|
||||
float capacitor_value;
|
||||
short number_of_555_timer_chips;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#define FLAGS4 (NC_DISKLESS|NC_NETCDF4|NC_CLASSIC_MODEL)
|
||||
#define FLAGS3 (NC_DISKLESS)
|
||||
|
||||
|
@ -9,8 +9,7 @@ SET(NC4_TESTS tst_dims tst_dims2 tst_dims3 tst_files tst_files4
|
||||
cdm_sea_soundings tst_vl tst_atts1 tst_atts2 tst_vars2 tst_files5
|
||||
tst_files6 tst_sync tst_h_strbug tst_h_refs tst_h_scalar tst_rename
|
||||
tst_rename2 tst_h5_endians tst_atts_string_rewrite tst_put_vars_two_unlim_dim
|
||||
tst_hdf5_file_compat tst_fill_attr_vanish tst_rehash tst_types tst_bug324)
|
||||
|
||||
tst_hdf5_file_compat tst_fill_attr_vanish tst_rehash tst_types tst_bug324 tst_filterparser)
|
||||
|
||||
# Note, renamegroup needs to be compiled before run_grp_rename
|
||||
|
||||
@ -19,11 +18,10 @@ IF(BUILD_UTILITIES)
|
||||
build_bin_test(renamegroup)
|
||||
add_sh_test(nc_test4 run_grp_rename)
|
||||
ADD_SH_TEST(nc_test4 tst_misc)
|
||||
IF(ENABLE_FILTER_TESTING)
|
||||
build_bin_test(test_filter)
|
||||
build_bin_test(test_filter_misc)
|
||||
IF(ENABLE_FILTER_TESTING)
|
||||
ADD_SH_TEST(nc_test4 tst_filter)
|
||||
SET(NC4_TESTS ${NC4_TESTS} tst_filterparser)
|
||||
ENDIF(ENABLE_FILTER_TESTING)
|
||||
|
||||
ENDIF(BUILD_UTILITIES)
|
||||
|
@ -1,5 +1,6 @@
|
||||
# Test c output
|
||||
T=test_filter_misc
|
||||
T=tst_dims
|
||||
|
||||
#SRC=hdf5plugins/H5Zmisc.c
|
||||
|
||||
#CMD=valgrind --leak-check=full
|
||||
@ -13,7 +14,7 @@ CMD=gdb --args
|
||||
|
||||
CFLAGS = -Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
|
||||
|
||||
LDFLAGS = ../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lm
|
||||
LDFLAGS = ../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lm -lmfhdf -ldf
|
||||
|
||||
ifdef PAR
|
||||
CC=mpicc
|
||||
|
@ -11,14 +11,16 @@ PLUGINHDRS=h5bzip2.h
|
||||
EXTRA_DIST=${PLUGINSRC} ${BZIP2SRC} ${PLUGINHDRS} ${BZIP2HDRS} \
|
||||
H5Ztemplate.c H5Zmisc.c CMakeLists.txt
|
||||
|
||||
if ENABLE_FILTER_TESTING
|
||||
# WARNING: This list must be kept consistent with the corresponding
|
||||
# AC_CONFIG_LINK commands near the end of configure.ac.
|
||||
HDF5PLUGINSRC=${PLUGINSRC} ${BZIP2SRC} ${PLUGINHDRS} ${BZIP2HDRS}
|
||||
|
||||
DLLSRC=${PLUGINSRC} ${BZIP2SRC} ${PLUGINHDRS} ${BZIP2HDRS}
|
||||
if ENABLE_FILTER_TESTING
|
||||
|
||||
lib_LTLIBRARIES = libbzip2.la libmisc.la
|
||||
|
||||
libbzip2_la_SOURCES = ${DLLSRC}
|
||||
libbzip2_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined -rpath ${abs_builddir}
|
||||
libbzip2_la_SOURCES = ${HDF5PLUGINSRC}
|
||||
libbzip2_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined
|
||||
|
||||
libmisc_la_SOURCES = H5Zmisc.c h5misc.h
|
||||
libmisc_la_LDFLAGS = -module -avoid-version -shared -export-dynamic -no-undefined -rpath ${abs_builddir}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <hdf5.h>
|
||||
#include "netcdf.h"
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
/* The C standard apparently defines all floating point constants as double;
|
||||
we rely on that in this code.
|
||||
*/
|
||||
@ -443,8 +445,10 @@ init(int argc, char** argv)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
H5Eprint(stderr);
|
||||
nc_set_log_level(1);
|
||||
#endif
|
||||
init(argc,argv);
|
||||
if(!test_test1()) ERRR;
|
||||
exit(nerrs > 0?1:0);
|
||||
|
@ -26,13 +26,16 @@
|
||||
#define CONTENTS_3 "Lots 0f pe0ple!" /* same len as CONTENTS */
|
||||
#define VAR_NAME "Earth"
|
||||
|
||||
#ifdef _MSC_VER /* otherwise defined in nc4internal/nc4file */
|
||||
/**
|
||||
WARNING: following should match lists in libsrc4/nc4file.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @internal Define the names of attributes to ignore added by the
|
||||
* HDF5 dimension scale; these attached to variables. They cannot be
|
||||
* modified thru the netcdf-4 API.
|
||||
*/
|
||||
const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
static const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
NC_ATT_REFERENCE_LIST,
|
||||
NC_ATT_CLASS,
|
||||
NC_ATT_DIMENSION_LIST,
|
||||
@ -47,7 +50,7 @@ const char* NC_RESERVED_VARATT_LIST[] = {
|
||||
* "hidden" global attributes. They can be read, but not modified thru
|
||||
* the netcdf-4 API.
|
||||
*/
|
||||
const char* NC_RESERVED_ATT_LIST[] = {
|
||||
static const char* NC_RESERVED_ATT_LIST[] = {
|
||||
NC_ATT_FORMAT,
|
||||
NC3_STRICT_ATT_NAME,
|
||||
NCPROPS,
|
||||
@ -60,20 +63,17 @@ const char* NC_RESERVED_ATT_LIST[] = {
|
||||
* @internal Define the subset of the reserved list that is readable
|
||||
* by name only
|
||||
*/
|
||||
const char* NC_RESERVED_SPECIAL_LIST[] = {
|
||||
static const char* NC_RESERVED_SPECIAL_LIST[] = {
|
||||
ISNETCDF4ATT,
|
||||
SUPERBLOCKATT,
|
||||
NCPROPS,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /*_MSC_VER*/
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
printf("\n*** Testing netCDF-4 attributes.\n");
|
||||
nc_set_log_level(3);
|
||||
printf("*** testing attribute renaming for read-only file...");
|
||||
{
|
||||
int ncid;
|
||||
@ -253,7 +253,7 @@ main(int argc, char **argv)
|
||||
const char** reserved = NC_RESERVED_VARATT_LIST;
|
||||
for ( ; *reserved; reserved++)
|
||||
{
|
||||
if (nc_put_att_text(ncid, 0, *reserved, strlen(CONTENTS),
|
||||
if (nc_put_att_text(ncid, 0, *reserved, strlen(CONTENTS),
|
||||
CONTENTS) != NC_ENAMEINUSE) ERR;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
nc_set_log_level(0);
|
||||
printf("\n*** Testing netcdf-4 dimensions even more.\n");
|
||||
printf("*** testing netcdf-4 dimension inheritance...");
|
||||
{
|
||||
|
@ -63,8 +63,8 @@ mismatch(size_t i, unsigned int *params, const char* tag)
|
||||
static void
|
||||
mismatch2(size_t i, unsigned int *params, const char* tag)
|
||||
{
|
||||
fprintf(stderr,"mismatch2: %s [%d-%ld] baseline=%ud,%ud params=%u,%u\n",
|
||||
tag,(int)i,i+1,baseline[i],baseline[i+1],params[i],params[i+1]);
|
||||
fprintf(stderr,"mismatch2: %s [%ld-%ld] baseline=%ud,%ud params=%u,%u\n",
|
||||
tag,(long)i,(long)(i+1),baseline[i],baseline[i+1],params[i],params[i+1]);
|
||||
fflush(stderr);
|
||||
nerrs++;
|
||||
}
|
||||
|
@ -215,6 +215,7 @@ main(int argc, char **argv)
|
||||
if (nc_inq_ncid(ncid, HENRY_VII, &grpid_in)) ERR;
|
||||
|
||||
/* Ensure that dimensions in parent are visible and correct. */
|
||||
memset(dimids_in,0,sizeof(dimids_in));
|
||||
if (nc_inq_dimids(grpid_in, &ndims_in, dimids_in, 1)) ERR;
|
||||
if (ndims_in != NDIMS_IN_FILE || dimids_in[0] != dimid1 || dimids_in[1] != dimid2) ERR;
|
||||
if (nc_inq_dim(grpid_in, dimids_in[0], name_in, &len_in)) ERR;
|
||||
|
@ -32,7 +32,6 @@ main()
|
||||
/* Create new file, using default properties. */
|
||||
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
|
||||
/* Create dataset with reference datatype */
|
||||
if ((dsetid = H5Dcreate2(fileid, REF_VAR_NAME, H5T_STD_REF_OBJ, scalar_spaceid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
|
||||
|
||||
|
@ -149,7 +149,7 @@ main()
|
||||
#ifdef VERBOSE
|
||||
for (idim=0; idim<ndim; idim++)
|
||||
printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
|
||||
idim,start[idim],idim,count[idim],idim,stride[idim]);
|
||||
idim,(unsigned long)start[idim],idim,(unsigned long)count[idim],idim,(unsigned long)stride[idim]);
|
||||
#endif
|
||||
|
||||
ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);
|
||||
@ -199,7 +199,7 @@ main()
|
||||
#ifdef VERBOSE
|
||||
for (idim=0; idim<ndim; idim++)
|
||||
printf("start[%d]=%3lu count[%d]=%3lu stride[%d]=%3lu\n",
|
||||
idim, start[idim], idim, count[idim], idim, stride[idim]);
|
||||
idim, (unsigned long)start[idim], idim, (unsigned long)count[idim], idim, (unsigned long)stride[idim]);
|
||||
#endif
|
||||
|
||||
ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);
|
||||
@ -256,7 +256,7 @@ main()
|
||||
#ifdef VERBOSE
|
||||
for (idim=0; idim<ndim; idim++)
|
||||
printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
|
||||
idim,start[idim],idim,count[idim],idim,stride[idim]);
|
||||
idim,(unsigned long)start[idim],idim,(unsigned long)count[idim],idim,(unsigned long)stride[idim]);
|
||||
#endif
|
||||
|
||||
memset((void*)sdat,0,sizeof(sdat));
|
||||
|
@ -1,8 +1,8 @@
|
||||
# Test c output
|
||||
T=t
|
||||
T=tst_unicode
|
||||
#ARGS=./x.nc
|
||||
|
||||
TF=test_atomic_array.cdl
|
||||
#TF=test_atomic_array.cdl
|
||||
|
||||
#CMD=valgrind --leak-check=full
|
||||
CMD=gdb --args
|
||||
@ -33,7 +33,7 @@ endif
|
||||
|
||||
LLP=/usr/local/lib:${LD_LIBRARY_PATH}
|
||||
|
||||
all:: comp ./x.nc
|
||||
all:: comp
|
||||
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
|
||||
${CMD} ./t ${ARGS}
|
||||
|
||||
|
@ -52,10 +52,6 @@ int optind;
|
||||
#include "nc4internal.h" /* to get name of the special properties file */
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SSIZE_T) && !defined(H5_SIZEOF_SSIZE_T)
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#define XML_VERSION "1.0"
|
||||
|
||||
#define int64_t long long
|
||||
@ -1723,17 +1719,27 @@ do_ncdump_rec(int ncid, const char *path)
|
||||
* ambiguous. */
|
||||
{
|
||||
int dimid_test; /* to see if dimname is ambiguous */
|
||||
int target_dimid; /* from variable dim list */
|
||||
int locid; /* group id where dimension is defined */
|
||||
/*Locate the innermost definition of a dimension with given name*/
|
||||
NC_CHECK( nc_inq_dimid(ncid, dim_name, &dimid_test) );
|
||||
|
||||
/* Now, starting with current group, walk the parent chain
|
||||
upward looking for the target dim_id */
|
||||
target_dimid = var.dims[id];
|
||||
locid = ncid;
|
||||
while(var.dims[id] != dimid_test) { /* not in locid, try ancestors */
|
||||
while(target_dimid != dimid_test) {/*not in locid, try ancestors*/
|
||||
int parent_id;
|
||||
NC_CHECK( nc_inq_grp_parent(locid, &parent_id) );
|
||||
locid = parent_id;
|
||||
/* Is dim of this name defined in this group or higher? */
|
||||
NC_CHECK( nc_inq_dimid(locid, dim_name, &dimid_test) );
|
||||
}
|
||||
/* dimid is in group locid, prefix dimname with group name if needed */
|
||||
if(locid != ncid) {
|
||||
/* innermost dimid with given name is in group locid.
|
||||
If this is not current group, then use fully qualified
|
||||
name (fqn) for the dimension name by prefixing dimname
|
||||
with group name */
|
||||
if(locid != ncid) { /* We need to use fqn */
|
||||
size_t len;
|
||||
char *locname; /* the group name */
|
||||
NC_CHECK( nc_inq_grpname_full(locid, &len, NULL) );
|
||||
|
@ -9,7 +9,6 @@ set -e
|
||||
echo ""
|
||||
echo "*** Testing ncgen and ncdump using some test CDL files."
|
||||
echo "*** creating tst_small.nc from ref_tst_small.cdl..."
|
||||
cat $srcdir/ref_tst_small.cdl
|
||||
${NCGEN} -b -o tst_small.nc $srcdir/ref_tst_small.cdl
|
||||
echo "*** creating tst_small.cdl from tst_small.nc..."
|
||||
${NCDUMP} tst_small.nc > tst_small.cdl
|
||||
|
@ -25,6 +25,25 @@ Test _NCProperties and other special attributes
|
||||
#define GROUPNAME "subgroup"
|
||||
#define DIMNAME "time"
|
||||
|
||||
/*
|
||||
Effective cdl:
|
||||
|
||||
netcdf nc4_fileinfo {
|
||||
dimensions:
|
||||
time = 4;
|
||||
variables:
|
||||
int :int_attr;
|
||||
int int_var;
|
||||
int int_var:int_attr;
|
||||
char int_var:_NCProperties;
|
||||
int time(time);
|
||||
group subgroup: {
|
||||
int :int_attr;
|
||||
char :_NCProperties;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ export verbose
|
||||
|
||||
echo "*** Performing diff/cycle tests for classic format: k=1"
|
||||
KFLAG=1 ; export KFLAG
|
||||
bash -x ${srcdir}/tst_ncgen4_diff.sh
|
||||
bash -x ${srcdir}/tst_ncgen4_cycle.sh
|
||||
bash ${srcdir}/tst_ncgen4_diff.sh
|
||||
bash ${srcdir}/tst_ncgen4_cycle.sh
|
||||
echo "SUCCESS!!"
|
||||
exit 0
|
||||
|
||||
|
@ -11,12 +11,12 @@
|
||||
The output file name is chosen by using the following in priority order:
|
||||
1. -o flag name
|
||||
2. command line input file with .cdl changed to .nc
|
||||
3. dataset name as specified in netcdf <name> {...}
|
||||
3. dataset name as specified in netcdf <name> {...}
|
||||
*/
|
||||
void
|
||||
define_netcdf(void)
|
||||
{
|
||||
char filename[2048+1];
|
||||
char filename[2049];
|
||||
|
||||
/* Rule for specifying the dataset name:
|
||||
1. use -o name
|
||||
@ -37,8 +37,8 @@ define_netcdf(void)
|
||||
p = strrchr(filename,'.');
|
||||
if(p != NULL) {*p= '\0';}
|
||||
p = strrchr(filename,'/');
|
||||
if(p != NULL) {memmove(filename,(p+1),2048);}
|
||||
|
||||
if(p != NULL) {memmove(filename,(p+1),(2048-strlen(cdlname)));}
|
||||
|
||||
} else {/* construct name from dataset name */
|
||||
strncpy(filename,datasetname,2048); /* Reserve space for extension, terminating '\0' */
|
||||
}
|
||||
@ -100,7 +100,7 @@ topfqn(Symbol* sym)
|
||||
char* parentfqn;
|
||||
Symbol* parent;
|
||||
#endif
|
||||
|
||||
|
||||
if(sym->fqn != NULL)
|
||||
return; /* already defined */
|
||||
|
||||
@ -116,9 +116,9 @@ topfqn(Symbol* sym)
|
||||
topfqn(parent);
|
||||
}
|
||||
parentfqn = parent->fqn;
|
||||
|
||||
|
||||
fqnname = fqnescape(sym->name);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parentfqn) + 1 + 1);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parentfqn) + 1 + 1);
|
||||
strcpy(fqn,parentfqn);
|
||||
strcat(fqn,"/");
|
||||
strcat(fqn,fqnname);
|
||||
@ -142,7 +142,7 @@ nestedfqn(Symbol* sym)
|
||||
char* fqn;
|
||||
char* fqnname;
|
||||
Symbol* parent;
|
||||
|
||||
|
||||
if(sym->fqn != NULL)
|
||||
return; /* already defined */
|
||||
|
||||
@ -153,7 +153,7 @@ nestedfqn(Symbol* sym)
|
||||
assert(parent->fqn != NULL);
|
||||
|
||||
fqnname = fqnescape(sym->name);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parent->fqn) + 1 + 1);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parent->fqn) + 1 + 1);
|
||||
strcpy(fqn,parent->fqn);
|
||||
strcat(fqn,".");
|
||||
strcat(fqn,fqnname);
|
||||
@ -172,7 +172,7 @@ attfqn(Symbol* sym)
|
||||
char* fqnname;
|
||||
char* parentfqn;
|
||||
Symbol* parent;
|
||||
|
||||
|
||||
if(sym->fqn != NULL)
|
||||
return; /* already defined */
|
||||
|
||||
@ -185,7 +185,7 @@ attfqn(Symbol* sym)
|
||||
parentfqn = parent->fqn;
|
||||
|
||||
fqnname = fqnescape(sym->name);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parentfqn) + 1 + 1);
|
||||
fqn = (char*)malloc(strlen(fqnname) + strlen(parentfqn) + 1 + 1);
|
||||
strcpy(fqn,parentfqn);
|
||||
strcat(fqn,"_");
|
||||
strcat(fqn,fqnname);
|
||||
@ -221,7 +221,7 @@ cprefixed(List* prefix, char* suffix, char* separator)
|
||||
Symbol* sym = (Symbol*)listget(prefix,i);
|
||||
strcat(result,sym->name); /* append "<prefix[i]/>"*/
|
||||
strcat(result,separator);
|
||||
}
|
||||
}
|
||||
strcat(result,suffix); /* append "<suffix>"*/
|
||||
return result;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*********************************************************************
|
||||
* Copyright 1993, UCAR/Unidata
|
||||
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
||||
* $Header: /upc/share/CVS/netcdf-3/nctest/atttests.c,v 1.18 2006/10/31 16:21:45 ed Exp $
|
||||
* $Header: /upc/share/CVS/netcdf-3/nctst/atttests.c,v 1.18 2006/10/31 16:21:45 ed Exp $
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef _MPW
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#define MAX_NUM_FORMATS 5
|
||||
|
||||
int current_format = 0;
|
||||
|
||||
/* Determine how many formats are available, and what they are. */
|
||||
void
|
||||
determine_test_formats(int *num_formats, int *format)
|
||||
@ -68,6 +70,8 @@ main(int argc, char **argv)
|
||||
|
||||
for (i = 0; i < num_formats; i++)
|
||||
{
|
||||
current_format = format[i];
|
||||
|
||||
/* Skip netCDF-4 - only netCDF-4 classic will work. */
|
||||
if (format[i] == NC_FORMAT_NETCDF4)
|
||||
continue;
|
||||
|
@ -10,6 +10,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int current_format;
|
||||
|
||||
extern int test_nccreate(const char*);
|
||||
extern int test_ncopen(const char*);
|
||||
extern int test_ncredef(const char*);
|
||||
|
7
oc2/oc.c
7
oc2/oc.c
@ -1929,14 +1929,15 @@ oc_data_ddtree(OCobject link, OCobject ddsroot)
|
||||
return OCTHROW(OC_NOERR);
|
||||
}
|
||||
|
||||
OCDT
|
||||
oc_data_mode(OCobject link, OCobject datanode)
|
||||
OCerror
|
||||
oc_data_mode(OCobject link, OCobject datanode, OCDT* modep)
|
||||
{
|
||||
OCdata* data;
|
||||
OCVERIFY(OC_Data,datanode);
|
||||
OCDEREF(OCdata*,data,datanode);
|
||||
|
||||
return data->datamode;
|
||||
if(modep) *modep = data->datamode;
|
||||
return OC_NOERR;
|
||||
}
|
||||
|
||||
/* Free up a datanode that is no longer being used;
|
||||
|
@ -22,7 +22,7 @@ typedef unsigned int OCDT;
|
||||
#define OCDT_ATOMIC ((OCDT)(32)) /* is atomic leaf */
|
||||
|
||||
/* Return mode for this data */
|
||||
extern OCDT oc_data_mode(OClink, OCdatanode);
|
||||
extern OCerror oc_data_mode(OClink, OCdatanode, OCDT* modep);
|
||||
|
||||
extern OCerror oc_dds_dd(OClink, OCddsnode, int);
|
||||
extern OCerror oc_dds_ddnode(OClink, OCddsnode);
|
||||
|
Loading…
x
Reference in New Issue
Block a user