summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>1997-07-30 21:17:56 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>1997-07-30 21:17:56 (GMT)
commit03997b1f368f935ab4b3a9a878fd3587cbc74862 (patch)
tree193909bb46d7310f8ea8d31308cddc8850530220
parentad9255a57faca8454d0a5f2f955001eed32833ea (diff)
downloadhdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.zip
hdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.tar.gz
hdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.tar.bz2
[svn-r2] Oops...
-rw-r--r--Makefile117
-rw-r--r--src/H5.c275
-rw-r--r--src/H5A.c789
-rw-r--r--src/H5AC.c315
-rw-r--r--src/H5ACprivate.h71
-rw-r--r--src/H5ACproto.h29
-rw-r--r--src/H5Aprivate.h90
-rw-r--r--src/H5Aproto.h204
-rw-r--r--src/H5B.c1177
-rw-r--r--src/H5Bprivate.h85
-rw-r--r--src/H5Bproto.h29
-rw-r--r--src/H5C.c506
-rw-r--r--src/H5Cprivate.h25
-rw-r--r--src/H5Cproto.h41
-rw-r--r--src/H5E.c394
-rw-r--r--src/H5Eprivate.h131
-rw-r--r--src/H5Eproto.h126
-rw-r--r--src/H5F.c852
-rw-r--r--src/H5Fprivate.h101
-rw-r--r--src/H5Fproto.h43
-rw-r--r--src/H5G.c196
-rw-r--r--src/H5Gnode.c661
-rw-r--r--src/H5Gprivate.h125
-rw-r--r--src/H5Gproto.h29
-rw-r--r--src/H5H.c653
-rw-r--r--src/H5Hprivate.h36
-rw-r--r--src/H5Hproto.h29
-rw-r--r--src/H5M.c257
-rw-r--r--src/H5MF.c88
-rw-r--r--src/H5MFprivate.h28
-rw-r--r--src/H5MFproto.h29
-rw-r--r--src/H5MM.c175
-rw-r--r--src/H5MMprivate.h32
-rw-r--r--src/H5MMproto.h29
-rw-r--r--src/H5Mprivate.h86
-rw-r--r--src/H5Mproto.h37
-rw-r--r--src/H5P.c216
-rw-r--r--src/H5Pprivate.h30
-rw-r--r--src/H5Pproto.h39
-rw-r--r--src/H5T.c662
-rw-r--r--src/H5Tprivate.h50
-rw-r--r--src/H5Tproto.h57
-rw-r--r--src/H5private.h30
-rw-r--r--src/H5proto.h35
-rw-r--r--src/Makefile92
-rw-r--r--src/h5oplat.h555
-rw-r--r--src/hdf5.h60
-rw-r--r--src/hdf5fort.h75
-rw-r--r--src/hdf5gen.h49
-rw-r--r--src/hdf5glob.h58
-rw-r--r--src/hdf5lims.h60
-rw-r--r--src/hdf5meta.h145
-rw-r--r--src/hdf5pabl.h32
-rw-r--r--src/hdf5plat.h750
-rw-r--r--src/hdf5port.h202
-rw-r--r--src/hdf5type.h70
-rw-r--r--test/Makefile50
-rw-r--r--test/testhdf5.c302
-rw-r--r--test/testhdf5.h115
-rw-r--r--test/tfile.c288
-rw-r--r--test/theap.c87
-rw-r--r--test/tmeta.c120
62 files changed, 12119 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c081fc9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,117 @@
+# ##################################################################
+#
+#
+# This is the top level Makefile to build HDF5 on Unix based
+# platforms
+#
+
+# Define your sh shell
+#SHELL=/bin/sh
+
+# Define your machine type
+#MACHINE=UNIX386
+
+# Define your C compiler and flags
+CC= gcc
+#CFLAGS= -ansi -Wall -pedantic -O -c
+CFLAGS= -ansi -Wall -pedantic -g -c
+
+# Define your FORTRAN compiler
+FC= f77
+FFLAGS=
+
+# Location where the HDF include files are to be installed
+HDFINC= `pwd`/src
+
+# Location where the HDF library is to be installed
+HDFLIB= `pwd`/src
+
+# Location to put HDF utility executables
+HDFBIN= `pwd`/bin
+
+# Name of library archiver and flags to send
+AR= ar
+ARFLAGS= ru
+
+# Name of achive randomizer (use 'touch' if non-existant)
+RANLIB= ranlib
+
+# Name of remove utility
+RM= /bin/rm
+RMFLAGS= -f
+
+# ##################################################################
+#
+# This is the top level Makefile to build HDF5 on Unix based
+# platforms
+#
+
+#
+#
+# Flags to recursively send
+#
+
+HDF_FLAGS = \
+ CC="$(CC)" \
+ CFLAGS="$(CFLAGS)" \
+ FC="$(FC)" \
+ FFLAGS="$(FFLAGS)" \
+ RANLIB="$(RANLIB)" \
+ AR="$(AR)" \
+ ARFLAGS="$(ARFLAGS)" \
+ RM="$(RM)" \
+ RMFLAGS="$(RMFLAGS)" \
+ MACHINE="$(MACHINE)" \
+ HDFLIB="$(HDFLIB)" \
+ HDFINC="$(HDFINC)" \
+ HDFBIN="$(HDFBIN)"
+
+#
+#
+# General rules
+#
+all:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \
+ SUBDIRS="src test" subd message
+
+rebuild:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \
+ SUBDIRS="src test" subd message
+
+libhdf5:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=all \
+ SUBDIRS="src" subd
+
+tests:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=test \
+ SUBDIRS="src test" subd
+
+debug:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=debug \
+ SUBDIRS="src test" subd message
+
+clean:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \
+ SUBDIRS="src test" subd
+ $(RM) $(RMFLAGS) core *.log
+
+distclean:
+ @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \
+ SUBDIRS="src test" subd
+ $(RM) $(RMFLAGS) core *.log
+ $(RM) -rf bin lib include
+
+subd:
+ @for dir in $(SUBDIRS); do \
+ (cd $$dir; echo Making \`$(TARG)\' in `pwd`; \
+ $(MAKE) $(MFLAGS) $(HDF_FLAGS) $(TARG)); \
+ done
+
+message:
+ @echo ""
+ @echo "***********************************************************"
+ @echo " HDF5 library successfully created."
+ @echo ""
+ @echo "***********************************************************"
+ @echo ""
+
diff --git a/src/H5.c b/src/H5.c
new file mode 100644
index 0000000..cf77b61
--- /dev/null
+++ b/src/H5.c
@@ -0,0 +1,275 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ hdf5.c
+ HDF library support routines
+
+ EXPORTED ROUTINES
+ H5dont_atexit -- Indicate that an 'atexit' routine is _not_ to be installed
+ H5version -- Check the version of the library
+
+ LIBRARY-SCOPED ROUTINES
+ H5_init_library -- initialize the HDF5 library
+ H5_term_library -- shut-down the HDF5 library
+ H5_init_thread -- initialize thread-specific information
+
+ LOCAL ROUTINES
+ H5_init_interface -- initialize the H5 interface
+ + */
+
+#define HDF5_MASTER
+#include "hdf5.h"
+#undef HDF5_MASTER
+
+/* private headers */
+#include "H5ACprivate.h" /*cache */
+#include "H5Bprivate.h" /*B-link trees */
+#include "H5private.h" /* Generic info */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*------------------_-- Local function prototypes ----------------------------*/
+static herr_t H5_init_interface(void);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5_init_library -- Initialize library-global information
+USAGE
+ herr_t H5_init_library()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any library-global data or routines.
+
+--------------------------------------------------------------------------*/
+herr_t H5_init_library(void)
+{
+ CONSTR(FUNC, "H5_init_library"); /* For HERROR */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5_mask, ID_H5_init_library);
+
+ /* Don't call this routine again... */
+ library_initialize = TRUE;
+
+ /* Install atexit() library cleanup routine */
+ if(install_atexit==TRUE)
+ if (HDatexit(&H5_term_library) != 0)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ FUNC_LEAVE(H5_mask, ID_H5_init_library,ret_value);
+} /* H5_init_library */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5_term_library
+ PURPOSE
+ Terminate various static buffers and shutdown the library.
+ USAGE
+ void HPend()
+ RETURNS
+ none
+ DESCRIPTION
+ Walk through the shutdown routines for the various interfaces and
+ terminate them all.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Should only ever be called by the "atexit" function, or real power-users.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+void H5_term_library(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5_term_library"); /* for HERROR */
+#endif /* LATER */
+
+} /* end H5_term_library() */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5_init_thread -- Initialize thread-specific information
+USAGE
+ void H5_init_thread()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any thread-specific data or routines.
+
+--------------------------------------------------------------------------*/
+herr_t H5_init_thread(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5_init_thread"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5_mask, ID_H5_init_thread);
+
+ /* Don't call this routine again... */
+ thread_initialize = TRUE;
+
+
+ /* Create/initialize this thread's error stack */
+ if((thrderrid=H5Enew_err_stack(16))==FAIL)
+ ret_value=FAIL;
+
+ FUNC_LEAVE(H5_mask, ID_H5_init_thread, ret_value);
+} /* H5_init_thread */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5_mask, ID_H5_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ FUNC_LEAVE(H5_mask, ID_H5_init_interface, ret_value);
+} /* H5_init_interface */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5dont_atexit
+ PURPOSE
+ Indicates to the library that an 'atexit()' routine is _not_ to be installed
+ USAGE
+ herr_t H5dont_atexit(void)
+ RETURNS
+ Returns SUCCEED/FAIL
+ DESCRIPTION
+ This routine indicates to the library that an 'atexit()' cleanip routine
+ should not be installed. The major (only?) purpose for this is in
+ situations where the library is dynamically linked into an application and
+ is un-linked from the application before 'exit()' gets callled. In those
+ situations, a routine installed with 'atexit()' would jump to a routine
+ which was no longer in memory, causing errors.
+ In order to be effective, this routine _must_ be called before any other
+ HDF function calls, and must be called each time the library is loaded/
+ linked into the application. (the first time and after it's been un-loaded)
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ If this routine is used, certain memory buffers will not be de-allocated,
+ although in theory a user could call HPend on their own...
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t H5dont_atexit(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5dont_atexit"); /* for HERROR */
+#endif /* LATER */
+ intn ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, we are trying to avoid certain initialization code */
+ PABLO_TRACE_ON(H5_mask, ID_H5dont_atexit);
+
+ if(install_atexit == TRUE)
+ install_atexit=FALSE;
+
+#ifdef LATER
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+#endif /* LATER */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5_mask, ID_H5dont_atexit,ret_value);
+} /* end H5dont_atexit() */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5version -- Checks the version of the library
+USAGE
+ herr_t H5version(majnum, minnum, relnum, patnum)
+ uintn *majnum; OUT: The major revision number of the HDF5 library
+ uintn *minnum; OUT: The minor revision number of the HDF5 library
+ uintn *relnum; OUT: The release revision number of the HDF5 library
+ uintn *patnum; OUT: The patch revision number of the HDF5 library
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Checks the version numbers of the library.
+
+--------------------------------------------------------------------------*/
+herr_t H5version(uintn *majnum, uintn *minnum, uintn *relnum, uintn *patnum)
+{
+ CONSTR(FUNC, "H5version"); /* For HERROR */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5_mask, ID_H5version, H5_init_interface,FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if (majnum==NULL || minnum==NULL || relnum==NULL || patnum==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* Set the version information */
+ *majnum=HDF5_MAJOR_VERSION;
+ *minnum=HDF5_MINOR_VERSION;
+ *relnum=HDF5_RELEASE_VERSION;
+ *patnum=HDF5_PATCH_VERSION;
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5_mask, ID_H5version, ret_value);
+} /* H5version */
+
diff --git a/src/H5A.c b/src/H5A.c
new file mode 100644
index 0000000..3733bf8
--- /dev/null
+++ b/src/H5A.c
@@ -0,0 +1,789 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*
+FILE
+ atom.c - Internal storage routines for handling "atoms"
+
+REMARKS
+ Atoms are just ID's which allow objects (void *'s currently) to be
+ bundled into "groups" for more general storage.
+
+DESIGN
+ The groups are stored in an array of pointers to store each group in an
+ element. Each "atomic group" node contains a link to a hash table to
+ manage the atoms in each group. The allowed "atomic groups" are stored
+ in an enum (called group_t) in atom.h.
+
+BUGS/LIMITATIONS
+ Can't interate over the atoms in a group.
+
+LOCAL ROUTINES
+ H5A_find_atom - Returns a pointer to an atom_info_t from a atom ID
+ H5A_get_atom_node - Gets an atom node (uses the atom free list)
+ H5A_release_atom_node - Releases an atom node (uses the atom free list)
+EXPORTED ROUTINES
+ Atom Functions:
+ H5Aregister_atom - Register an object in a group and get an atom for it
+ H5Aatom_object - Get the object for an atom
+ H5Aatom_group - Get the group for an atom
+ H5Aremove_atom - Remove an atom from a group
+ H5Asearch_atom - Search a group for a particular object
+ H5Ais_reserved - Check whether an atom is a reserved atom in a group
+ Atom Group Functions:
+ H5Ainit_group - Initialize a group to store atoms in
+ H5Adestroy_group - Destroy an atomic group
+ Atom Group Cleanup:
+ H5Ashutdown - Terminate various static buffers.
+
+AUTHOR
+ Quincey Koziol
+
+MODIFICATION HISTORY
+ 1/3/96 - Starting writing specs & coding prototype
+ 1/7/96 - Finished coding prototype
+ 6/10/97 - Moved into HDF5 library
+*/
+
+#define HDF5_ATOM_MASTER
+#include "hdf5.h"
+#include "H5Aprivate.h"
+
+
+/* Private function prototypes */
+static atom_info_t *H5A_find_atom(hatom_t atm);
+
+static atom_info_t *H5A_get_atom_node(void);
+
+static void H5A_release_atom_node(atom_info_t *atm);
+
+/******************************************************************************
+ NAME
+ H5Ainit_group - Initialize an atomic group
+
+ DESCRIPTION
+ Creates a global atomic group to store atoms in. If the group has already
+ been initialized, this routine just increments the count of # of
+ initializations and returns without trying to change the size of the hash
+ table. A specific number of group entries may be reserved to enable
+ "constant" values to be handed out which are valid atoms in the group, but
+ which do not map to any data structures and are not allocated dynamicly
+ later.
+
+ RETURNS
+ Returns SUCCEED if successful and FAIL otherwise
+
+*******************************************************************************/
+intn H5Ainit_group(group_t grp, /* IN: Group to initialize */
+ intn hash_size, /* IN: Minimum hash table size to use for group */
+ uintn reserved /* IN: Number of hash table entries to reserve */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Ainit_group"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ intn ret_value=SUCCEED;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Ainit_group);
+
+ if((grp<=BADGROUP || grp>=MAXGROUP) && hash_size>0)
+ HGOTO_DONE(FAIL);
+
+#ifdef HASH_SIZE_POWER_2
+ /* If anyone knows a faster test for a power of two, please change this silly code -QAK */
+ if(!(hash_size==2 || hash_size==4 || hash_size==8 || hash_size==16
+ || hash_size==32 || hash_size==64 || hash_size==128 || hash_size==256
+ || hash_size==512 || hash_size==1024 || hash_size==2048
+ || hash_size==4096 || hash_size==8192 || hash_size==16374
+ || hash_size==32768 || hash_size==65536 || hash_size==131072
+ || hash_size==262144 || hash_size==524288 || hash_size==1048576
+ || hash_size==2097152 || hash_size==4194304 || hash_size==8388608
+ || hash_size==16777216 || hash_size==33554432 || hash_size==67108864
+ || hash_size==134217728 || hash_size==268435456))
+ HGOTO_DONE(FAIL);
+#endif /* HASH_SIZE_POWER_2 */
+
+ if(atom_group_list[grp]==NULL)
+ { /* Allocate the group information */
+ grp_ptr=(atom_group_t *)HDcalloc(1,sizeof(atom_group_t));
+ if(grp_ptr==NULL)
+ HGOTO_DONE(FAIL);
+ atom_group_list[grp]=grp_ptr;
+ } /* end if */
+ else /* Get the pointer to the existing group */
+ grp_ptr=atom_group_list[grp];
+
+ if(grp_ptr->count==0)
+ { /* Initialize the atom group structure */
+ grp_ptr->hash_size=hash_size;
+ grp_ptr->reserved=reserved;
+ grp_ptr->wrapped=0;
+ grp_ptr->atoms=0;
+ grp_ptr->nextid=0;
+ if((grp_ptr->atom_list=(atom_info_t **)HDcalloc(hash_size,sizeof(atom_info_t *)))==NULL)
+ HGOTO_DONE(FAIL);
+ } /* end if */
+
+ /* Increment the count of the times this group has been initialized */
+ grp_ptr->count++;
+
+#ifdef QAK
+printf("%s: group ID=%d, count=%d, current # of active atoms=%d\n",FUNC,grp,grp_ptr->count,grp_ptr->atoms);
+#endif /* QAK */
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+ if(grp_ptr!=NULL)
+ {
+ if(grp_ptr->atom_list!=NULL)
+ HDfree(grp_ptr->atom_list);
+ HDfree(grp_ptr);
+ } /* end if */
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Ainit_group, ret_value);
+} /* end H5Ainit_group() */
+
+/******************************************************************************
+ NAME
+ H5Adestroy_group - Destroy an atomic group
+
+ DESCRIPTION
+ Destroys an atomic group which atoms are stored in. If the group still
+ has atoms which are registered, this routine fails. If there have been
+ multiple initializations of the group, this routine just decrements the
+ count of initializations and does not check the atoms out-standing.
+
+ RETURNS
+ Returns SUCCEED if successful and FAIL otherwise
+
+*******************************************************************************/
+intn H5Adestroy_group(group_t grp /* IN: Group to destroy */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Adestroy_group"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ intn ret_value=SUCCEED;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Adestroy_group);
+
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(FAIL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL || grp_ptr->count<=0)
+ HGOTO_DONE(FAIL);
+
+#ifdef QAK
+printf("%s: group ID=%d, count=%d, current # of active atoms=%d\n",FUNC,grp,grp_ptr->count,grp_ptr->atoms);
+#endif /* QAK */
+ /* Decrement the number of users of the atomic group */
+ if((--(grp_ptr->count))==0)
+ {
+#ifdef ATOMS_ARE_CACHED
+ {
+ uintn i;
+
+ for(i=0; i<ATOM_CACHE_SIZE; i++)
+ if(ATOM_TO_GROUP(atom_id_cache[i])==grp)
+ {
+ atom_id_cache[i]=(-1);
+ atom_obj_cache[i]=NULL;
+ } /* end if */
+ } /* end block */
+#endif /* ATOMS_ARE_CACHED */
+ HDfree(grp_ptr->atom_list);
+ } /* end if */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Adestroy_group, ret_value);
+} /* end H5Adestroy_group() */
+
+/******************************************************************************
+ NAME
+ H5Aregister_atom - Register an object in a group and get an atom for it.
+
+ DESCRIPTION
+ Registers an object in a group and returns an atom for it. This routine
+ does _not_ check for unique-ness of the objects, if you register an object
+ twice, you will get two different atoms for it. This routine does make
+ certain that each atom in a group is unique. Atoms are created by getting
+ a unique number for the group the atom is in and incorporating the group
+ into the atom which is returned to the user.
+
+ RETURNS
+ Returns atom if successful and FAIL otherwise
+
+*******************************************************************************/
+hatom_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */
+ const VOIDP object /* IN: Object to attach to atom */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Aregister_atom"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ atom_info_t *atm_ptr=NULL; /* ptr to the new atom */
+ hatom_t atm_id; /* new atom ID */
+ uintn hash_loc; /* new item's hash table location */
+ hatom_t ret_value=SUCCEED;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Aregister_atom);
+
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(FAIL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL || grp_ptr->count<=0)
+ HGOTO_DONE(FAIL);
+
+ if((atm_ptr=H5A_get_atom_node())==NULL)
+ HGOTO_DONE(FAIL);
+
+ /* Create the atom & it's ID */
+ atm_id=MAKE_ATOM(grp,grp_ptr->nextid);
+ atm_ptr->id=atm_id;
+ atm_ptr->obj_ptr=object;
+ atm_ptr->next=NULL;
+
+ /* hash bucket already full, prepend to front of chain */
+ hash_loc=grp_ptr->nextid%(uintn)grp_ptr->hash_size;
+ if(grp_ptr->atom_list[hash_loc]!=NULL)
+ atm_ptr->next=grp_ptr->atom_list[hash_loc];
+
+ /* Insert into the group */
+ grp_ptr->atom_list[hash_loc]=atm_ptr;
+ grp_ptr->atoms++;
+ grp_ptr->nextid++;
+
+ /*
+ * This next section of code checks for the 'nextid' getting too large and
+ * wrapping around, thus necessitating checking for duplicate atoms being
+ * handed out.
+ */
+ if(grp_ptr->nextid>(uintn)ATOM_MASK || grp_ptr->wrapped!=0)
+ {
+ if(grp_ptr->wrapped==0)
+ {
+ grp_ptr->wrapped=1; /* set the "wrapped around" flag if it isn't already */
+ grp_ptr->nextid=grp_ptr->reserved; /* re-start the ID counter */
+ } /* end if */
+ do {
+ hatom_t next_atom=MAKE_ATOM(grp,grp_ptr->nextid); /* new atom to check for */
+ atom_info_t *curr_atm; /* ptr to the current atom */
+
+ curr_atm=grp_ptr->atom_list[(uintn)ATOM_TO_LOC(grp_ptr->nextid,grp_ptr->hash_size)];
+ if(curr_atm==NULL) /* Ha! this is not likely... */
+ break;
+
+ while(curr_atm!=NULL)
+ {
+ if(curr_atm->id==next_atom)
+ break;
+ curr_atm=curr_atm->next;
+ } /* end while */
+ if(curr_atm==NULL) /* must not have found a match */
+ break;
+ grp_ptr->nextid++;
+ } while(grp_ptr->nextid<=(uintn)ATOM_MASK);
+ if(grp_ptr->nextid>(uintn)ATOM_MASK) /* All the atoms are gone! */
+ HGOTO_DONE(FAIL);
+ } /* end if */
+
+ ret_value=atm_id;
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Aregister_atom, ret_value);
+} /* end H5Aregister_atom() */
+
+/******************************************************************************
+ NAME
+ H5Aatom_object - Returns to the object ptr for the atom
+
+ DESCRIPTION
+ Retrieves the object ptr which is associated with the atom.
+
+ RETURNS
+ Returns object ptr if successful and NULL otherwise
+
+*******************************************************************************/
+VOIDP H5Aatom_object(hatom_t atm /* IN: Atom to retrieve object for */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Aatom_object"); /* for HERROR */
+#endif /* LATER */
+#ifdef ATOMS_ARE_CACHED
+ uintn i; /* local counter */
+#endif /* ATOMS_ARE_CACHED */
+ atom_info_t *atm_ptr=NULL; /* ptr to the new atom */
+ VOIDP ret_value=NULL;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Aatom_object);
+
+#ifdef ATOMS_ARE_CACHED
+ /* Look for the atom in the cache first */
+ for(i=0; i<ATOM_CACHE_SIZE; i++)
+ if(atom_id_cache[i]==atm)
+ {
+ ret_value=atom_obj_cache[i];
+ if(i>0)
+ { /* Implement a simple "move forward" caching scheme */
+ hatom_t t_atom=atom_id_cache[i-1];
+ VOIDP t_obj=atom_obj_cache[i-1];
+
+ atom_id_cache[i-1]=atom_id_cache[i];
+ atom_obj_cache[i-1]=atom_obj_cache[i];
+ atom_id_cache[i]=t_atom;
+ atom_obj_cache[i]=t_obj;
+ } /* end if */
+ HGOTO_DONE(ret_value);
+ } /* end if */
+#endif /* ATOMS_ARE_CACHED */
+
+ /* General lookup of the atom */
+ if((atm_ptr=H5A_find_atom(atm))==NULL)
+ HGOTO_DONE(NULL);
+
+ /* Check if we've found the correct atom */
+ if(atm_ptr!=NULL)
+ ret_value=atm_ptr->obj_ptr;
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Aatom_object, ret_value);
+} /* end H5Aatom_object() */
+
+/******************************************************************************
+ NAME
+ H5Aatom_group - Returns to the group for the atom
+
+ DESCRIPTION
+ Retrieves the group which is associated with the atom.
+
+ RETURNS
+ Returns group if successful and BADGROUP otherwise
+
+*******************************************************************************/
+group_t H5Aatom_group(hatom_t atm /* IN: Atom to retrieve group for */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Aatom_group"); /* for HERROR */
+#endif /* LATER */
+ group_t ret_value=BADGROUP;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Aatom_group);
+
+ ret_value=ATOM_TO_GROUP(atm);
+ if(ret_value<=BADGROUP || ret_value>=MAXGROUP)
+ HGOTO_DONE(BADGROUP);
+
+done:
+ if(ret_value == BADGROUP)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Aatom_group, ret_value);
+} /* end H5Aatom_group() */
+
+/******************************************************************************
+ NAME
+ H5Aremove_atom - Removes an atom from a group
+
+ DESCRIPTION
+ Removes an atom from a group.
+
+ RETURNS
+ Returns atom's object if successful and NULL otherwise
+
+*******************************************************************************/
+VOIDP H5Aremove_atom(hatom_t atm /* IN: Atom to remove */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Aremove_atom"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ atom_info_t *curr_atm, /* ptr to the current atom */
+ *last_atm; /* ptr to the last atom */
+ group_t grp; /* atom's atomic group */
+ uintn hash_loc; /* atom's hash table location */
+#ifdef ATOMS_ARE_CACHED
+ uintn i; /* local counting variable */
+#endif /* ATOMS_ARE_CACHED */
+ VOIDP ret_value=NULL;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Aremove_atom);
+
+ grp=ATOM_TO_GROUP(atm);
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(NULL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL || grp_ptr->count<=0)
+ HGOTO_DONE(NULL);
+
+ /* Get the location in which the atom is located */
+ hash_loc=(uintn)ATOM_TO_LOC(atm,grp_ptr->hash_size);
+ curr_atm=grp_ptr->atom_list[hash_loc];
+ if(curr_atm==NULL)
+ HGOTO_DONE(NULL);
+
+ last_atm=NULL;
+ while(curr_atm!=NULL)
+ {
+ if(curr_atm->id==atm)
+ break;
+ last_atm=curr_atm;
+ curr_atm=curr_atm->next;
+ } /* end while */
+
+ if(curr_atm!=NULL)
+ {
+ if(last_atm==NULL) /* atom is the first the chain */
+ grp_ptr->atom_list[hash_loc]=curr_atm->next;
+ else
+ last_atm->next=curr_atm->next;
+ ret_value=curr_atm->obj_ptr;
+ H5A_release_atom_node(curr_atm);
+ } /* end if */
+ else /* couldn't find the atom in the proper place */
+ HGOTO_DONE(NULL);
+
+#ifdef ATOMS_ARE_CACHED
+ /* Delete object from cache */
+ for(i=0; i<ATOM_CACHE_SIZE; i++)
+ if(atom_id_cache[i]==atm)
+ {
+ atom_id_cache[i]=(-1);
+ atom_obj_cache[i]=NULL;
+ break; /* we assume there is only one instance in the cache */
+ } /* end if */
+#endif /* ATOMS_ARE_CACHED */
+
+ /* Decrement the number of atoms in the group */
+ (grp_ptr->atoms)--;
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Aremove_atom, ret_value);
+} /* end H5Aremove_atom() */
+
+/******************************************************************************
+ NAME
+ H5Asearch_atom - Search for an object in a group and get it's pointer.
+
+ DESCRIPTION
+ Searchs for an object in a group and returns the pointer to it.
+ This routine calls the function pointer passed in for each object in the
+ group until it finds a match. Currently there is no way to resume a
+ search.
+
+ RETURNS
+ Returns pointer an atom's object if successful and NULL otherwise
+
+*******************************************************************************/
+VOIDP H5Asearch_atom(group_t grp, /* IN: Group to search for the object in */
+ H5Asearch_func_t func, /* IN: Ptr to the comparison function */
+ const VOIDP key /* IN: pointer to key to compare against */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Asearch_atom"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ atom_info_t *atm_ptr=NULL; /* ptr to the new atom */
+ intn i; /* local counting variable */
+ VOIDP ret_value=NULL;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Asearch_atom);
+
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(NULL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL || grp_ptr->count<=0)
+ HGOTO_DONE(NULL);
+
+ /* Start at the beginning of the array */
+ for(i=0; i<grp_ptr->hash_size; i++)
+ {
+ atm_ptr=grp_ptr->atom_list[i];
+ while(atm_ptr!=NULL)
+ {
+ if((*func)(atm_ptr->obj_ptr,key))
+ HGOTO_DONE(atm_ptr->obj_ptr); /* found the item we are looking for */
+ atm_ptr=atm_ptr->next;
+ } /* end while */
+ } /* end for */
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Asearch_atom, ret_value);
+} /* end H5Asearch_atom() */
+
+/******************************************************************************
+ NAME
+ H5Ais_reserved - Check whether an atom is a reserved atom in a group
+
+ DESCRIPTION
+ Determines the group an atom belongs to and checks if the atom is a
+ reserved atom in the group.
+
+ RETURNS
+ Returns BTRUE/BFALSE/BFAIL
+
+*******************************************************************************/
+intn H5Ais_reserved(hatom_t atm /* IN: Group to search for the object in */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5Ais_reserved"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ group_t grp; /* atom's atomic group */
+ hbool_t ret_value=BFAIL;
+
+ PABLO_TRACE_ON(H5A_mask, ID_H5Ais_reserved);
+
+ grp=ATOM_TO_GROUP(atm);
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(BFAIL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL)
+ HGOTO_DONE(BFAIL);
+
+ /* Get the location in which the atom is located */
+ if((atm&ATOM_MASK)<grp_ptr->reserved)
+ ret_value=BTRUE;
+ else
+ ret_value=BFALSE;
+
+done:
+ if(ret_value == BFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5A_mask, ID_H5Ais_reserved, ret_value);
+} /* end H5Ais_reserved() */
+
+/******************************************************************************
+ NAME
+ H5A_find_atom - Finds a atom in a group
+
+ DESCRIPTION
+ Retrieves the atom ptr which is associated with the atom.
+
+ RETURNS
+ Returns atom ptr if successful and NULL otherwise
+
+*******************************************************************************/
+static atom_info_t *H5A_find_atom(hatom_t atm /* IN: Atom to retrieve atom for */
+)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5A_find_atom"); /* for HERROR */
+#endif /* LATER */
+ atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */
+ atom_info_t *atm_ptr=NULL; /* ptr to the new atom */
+ group_t grp; /* atom's atomic group */
+ uintn hash_loc; /* atom's hash table location */
+ atom_info_t *ret_value=NULL;
+
+
+ grp=ATOM_TO_GROUP(atm);
+ if(grp<=BADGROUP || grp>=MAXGROUP)
+ HGOTO_DONE(NULL);
+
+ grp_ptr=atom_group_list[grp];
+ if(grp_ptr==NULL || grp_ptr->count<=0)
+ HGOTO_DONE(NULL);
+
+ /* Get the location in which the atom is located */
+ hash_loc=(uintn)ATOM_TO_LOC(atm,grp_ptr->hash_size);
+ atm_ptr=grp_ptr->atom_list[hash_loc];
+ if(atm_ptr==NULL)
+ HGOTO_DONE(NULL);
+
+ while(atm_ptr!=NULL)
+ {
+ if(atm_ptr->id==atm)
+ break;
+ atm_ptr=atm_ptr->next;
+ } /* end while */
+ ret_value=atm_ptr;
+
+#ifdef ATOMS_ARE_CACHED
+ atom_id_cache[ATOM_CACHE_SIZE-1]=atm;
+ atom_obj_cache[ATOM_CACHE_SIZE-1]=atm_ptr->obj_ptr;
+#endif /* ATOMS_ARE_CACHED */
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ return ret_value;
+} /* end H5A_find_atom() */
+
+/******************************************************************************
+ NAME
+ H5A_get_atom_node - Gets an atom node
+
+ DESCRIPTION
+ Either gets an atom node from the free list (if there is one available)
+ or allocate a node.
+
+ RETURNS
+ Returns atom ptr if successful and NULL otherwise
+
+*******************************************************************************/
+static atom_info_t *H5A_get_atom_node(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5A_get_atom_node"); /* for HERROR */
+#endif /* LATER */
+ atom_info_t *ret_value=NULL;
+
+ if(atom_free_list!=NULL)
+ {
+ ret_value=atom_free_list;
+ atom_free_list=atom_free_list->next;
+ } /* end if */
+ else
+ {
+ if((ret_value=(atom_info_t *)HDmalloc(sizeof(atom_info_t)))==NULL)
+ HGOTO_DONE(NULL);
+ } /* end else */
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ return ret_value;
+} /* end H5A_get_atom_node() */
+
+/******************************************************************************
+ NAME
+ H5A_release_atom_node - Releases an atom node
+
+ DESCRIPTION
+ Puts an atom node into the free list
+
+ RETURNS
+ No return value
+
+*******************************************************************************/
+static void H5A_release_atom_node(atom_info_t *atm)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5A_release_atom_node"); /* for HERROR */
+#endif /* LATER */
+
+ /* Insert the atom at the beginning of the free list */
+ atm->next=atom_free_list;
+ atom_free_list=atm;
+} /* end H5A_release_atom_node() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ashutdown
+ PURPOSE
+ Terminate various static buffers.
+ USAGE
+ intn H5Ashutdown()
+ RETURNS
+ Returns SUCCEED/FAIL
+ DESCRIPTION
+ Free various buffers allocated in the H5A routines.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Should only ever be called by the "atexit" function HDFend
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+intn
+H5Ashutdown(void)
+{
+ atom_info_t *curr;
+ intn i;
+
+ /* Release the free-list if it exists */
+ if(atom_free_list!=NULL)
+ {
+ while(atom_free_list!=NULL)
+ {
+ curr=atom_free_list;
+ atom_free_list=atom_free_list->next;
+ HDfree(curr);
+ } /* end while */
+ } /* end if */
+
+ for(i=0; i<(intn)MAXGROUP; i++)
+ if(atom_group_list[i]!=NULL)
+ {
+ HDfree(atom_group_list[i]);
+ atom_group_list[i]=NULL;
+ } /* end if */
+ return (SUCCEED);
+} /* end H5Ashutdown() */
+
diff --git a/src/H5AC.c b/src/H5AC.c
new file mode 100644
index 0000000..a0123b1
--- /dev/null
+++ b/src/H5AC.c
@@ -0,0 +1,315 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: hdf5cache.c
+ * Jul 9 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Functions in this file implement a cache for
+ * things which exist on disk. All "things" associated
+ * with a particular HDF file share the same cache; each
+ * HDF file has it's own cache.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include "hdf5.h"
+
+#include "H5ACprivate.h"
+
+#define HASH(addr) ((unsigned)(addr) % H5AC_NSLOTS)
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_new
+ *
+ * Purpose: Initialize the cache just after a file is opened.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_new (hdf5_file_t *f)
+{
+ f->cache = HDcalloc (H5AC_NSLOTS, sizeof (H5AC_cache_t));
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_dest
+ *
+ * Purpose: Flushes all data to disk and destroys the cache.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_dest (hdf5_file_t *f)
+{
+ if (H5AC_flush (f, NULL, 0, TRUE)<0) return -1;
+ HDfree (f->cache);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_find
+ *
+ * Purpose: Given an object type and the address at which that object
+ * is located in the file, return a pointer to the object.
+ * The optional UDATA structure is passed down to the function
+ * that is responsible for loading the object into memory.
+ *
+ * Return: Success: Pointer to the object. The pointer is
+ * valid until some other cache function
+ * is called.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ const void *udata)
+{
+ unsigned idx = HASH(addr);
+ herr_t status;
+ void *thing = NULL;
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ assert (type);
+ assert (type->load);
+ assert (type->flush);
+
+ /*
+ * Return right away if the item is in the cache.
+ */
+ if (f->cache[idx].type==type && f->cache[idx].addr==addr) {
+ return f->cache[idx].thing;
+ }
+
+ /*
+ * Load a new thing. If it can't be loaded, then return an error
+ * without preempting anything.
+ */
+ if (NULL==(thing=(type->load)(f, addr, udata))) {
+ return NULL;
+ }
+
+ /*
+ * Free the previous cache entry if there is one.
+ */
+ if (f->cache[idx].type) {
+ flush = f->cache[idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing);
+ if (status<0) {
+ /*
+ * The old thing could not be removed from the stack.
+ * Release the new thing and fail.
+ */
+ status = (type->flush)(f, TRUE, addr, thing);
+ assert (status>=0);
+ return NULL;
+ }
+ }
+
+ /*
+ * Make the cache point to the new thing.
+ */
+ f->cache[idx].type = type;
+ f->cache[idx].addr = addr;
+ f->cache[idx].thing = thing;
+
+ return thing;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_flush
+ *
+ * Purpose: Flushes (and destroys if DESTROY is non-zero) the specified
+ * entry from the cache. If the entry type is CACHE_FREE then
+ * all types of entries are flushed. If the ADDR is zero then
+ * all entries of the specified type are flushed.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ hbool_t destroy)
+{
+ uintn i = HASH(addr);
+ herr_t status;
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ if (!type || 0==addr) {
+ /*
+ * Look at all cache entries.
+ */
+ for (i=0; i<H5AC_NSLOTS; i++) {
+ if (NULL==f->cache[i].type) continue;
+ if ((!type || type==f->cache[i].type) &&
+ (0==addr || addr==f->cache[i].addr)) {
+ flush = f->cache[i].type->flush;
+ status = (flush)(f, destroy, f->cache[i].addr,
+ f->cache[i].thing);
+ if (status<0) return -1;
+ if (destroy) f->cache[i].type = NULL;
+ }
+ }
+
+ } else if (f->cache[i].type==type && f->cache[i].addr==addr) {
+ /*
+ * Flush just this entry.
+ */
+ flush = f->cache[i].type->flush;
+ status = (flush) (f, destroy, f->cache[i].addr, f->cache[i].thing);
+ if (status<0) return -1;
+ if (destroy) f->cache[i].type = NULL;
+
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_set
+ *
+ * Purpose: Adds the specified thing to the cache. The thing need not
+ * exist on disk yet, but it must have an address and disk
+ * space reserved.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, void *thing)
+{
+ herr_t status;
+ uintn idx = HASH (addr);
+ herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL;
+
+ assert (type);
+ assert (type->flush);
+
+ if (f->cache[idx].type) {
+ flush = f->cache[idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing);
+ if (status<0) return -1;
+ }
+
+ f->cache[idx].type = type;
+ f->cache[idx].addr = addr;
+ f->cache[idx].thing = thing;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5AC_rename
+ *
+ * Purpose: Use this function to notify the cache that an object's
+ * file address changed.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
+ off_t old_addr, off_t new_addr)
+{
+ uintn old_idx = HASH (old_addr);
+ uintn new_idx = HASH (new_addr);
+ herr_t (*flush)(hdf5_file_t*, hbool_t, off_t, void*);
+ herr_t status;
+
+ assert (type);
+
+ if (f->cache[old_idx].type!=type || f->cache[old_idx].addr!=old_addr) {
+ return 0; /*item not in cache*/
+ }
+
+ if (old_idx==new_idx) {
+ f->cache[old_idx].addr = new_addr;
+ return 0;
+ }
+
+ /*
+ * Free the item from the destination cache line.
+ */
+ if (f->cache[new_idx].type) {
+ flush = f->cache[new_idx].type->flush;
+ status = (flush)(f, TRUE, f->cache[new_idx].addr,
+ f->cache[new_idx].thing);
+ if (status<0) return -1;
+ }
+
+ /*
+ * Move the source to the destination (it might not be cached)
+ */
+ f->cache[new_idx].type = f->cache[old_idx].type;
+ f->cache[new_idx].addr = new_addr;
+ f->cache[new_idx].thing = f->cache[old_idx].thing;
+ f->cache[old_idx].type = NULL;
+
+ return 0;
+}
+
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
new file mode 100644
index 0000000..5dce2cd
--- /dev/null
+++ b/src/H5ACprivate.h
@@ -0,0 +1,71 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5ACprivate.h
+ * Jul 9 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Constants and typedefs available to the rest of the
+ * library.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5ACprivate_H
+#define _H5ACprivate_H
+
+#include "H5ACproto.h" /*public prototypes */
+#include "H5Fprivate.h" /*for private hdf5_file_t definition */
+
+/*
+ * Class methods pertaining to caching. Each type of cached object will
+ * have a constant variable with permanent life-span that describes how
+ * to cache the object. That variable will be of type H5AC_class_t and
+ * have the following required fields...
+ *
+ * LOAD: Loads an object from disk to memory. The function
+ * should allocate some data structure and return it.
+ *
+ * FLUSH: Writes some data structure back to disk. It would be
+ * wise for the data structure to include dirty flags to
+ * indicate whether it really needs to be written. This
+ * function is also responsible for freeing memory allocated
+ * by the LOAD method if the DEST argument is non-zero.
+ */
+typedef struct H5AC_class_t {
+ void *(*load)(hdf5_file_t*, off_t addr, const void *udata);
+ herr_t (*flush)(hdf5_file_t*, hbool_t dest, off_t addr, void *thing);
+} H5AC_class_t;
+
+/*
+ * A cache has a certain number of entries. Objects are mapped into a
+ * cache entry by hashing the object's file address. Each file has its
+ * own cache, an array of slots.
+ */
+#define H5AC_NSLOTS 1033 /*prime number tend to work best */
+
+typedef struct H5AC_cache_t {
+ const H5AC_class_t *type; /*type of object stored here */
+ off_t addr; /*file address for object */
+ void *thing; /*the thing which is cached */
+} H5AC_cache_t;
+
+/*
+ * Library prototypes.
+ */
+herr_t H5AC_dest (hdf5_file_t *f);
+void *H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ const void *udata);
+herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ hbool_t destroy);
+herr_t H5AC_new (hdf5_file_t *f);
+herr_t H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type,
+ off_t old, off_t new);
+herr_t H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, off_t addr,
+ void *thing);
+
+#endif /* !_H5ACprivate_H */
diff --git a/src/H5ACproto.h b/src/H5ACproto.h
new file mode 100644
index 0000000..25218a9
--- /dev/null
+++ b/src/H5ACproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5ACproto.h
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Function prototypes for the H5AC package.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5ACproto_H
+#define _H5ACproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
new file mode 100644
index 0000000..1a2db6f
--- /dev/null
+++ b/src/H5Aprivate.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*-----------------------------------------------------------------------------
+ * File: atom.h
+ * Purpose: header file for atom API
+ *---------------------------------------------------------------------------*/
+
+/* avoid re-inclusion */
+#ifndef __ATOM_H
+#define __ATOM_H
+
+#include "H5Aproto.h" /* Include Public Definitions */
+
+/* Atom Features control */
+/* Define the following macro for fast hash calculations (but limited hash sizes) */
+#define HASH_SIZE_POWER_2
+
+/* Define the following macro for atom caching over all the atoms */
+#define ATOMS_ARE_CACHED
+
+#if defined HDF5_ATOM_MASTER | defined HDF5_ATOM_TESTER
+#ifdef ATOMS_ARE_CACHED
+/* # of previous atoms cached */
+#define ATOM_CACHE_SIZE 4
+#endif /* ATOMS_ARE_CACHED */
+
+/* Map an atom to a Group number */
+#define ATOM_TO_GROUP(a) ((group_t)((((hatom_t)(a))>>((sizeof(hatom_t)*8)-GROUP_BITS))&GROUP_MASK))
+
+#ifdef HASH_SIZE_POWER_2
+/* Map an atom to a hash location (assumes s is a power of 2 and smaller than the ATOM_MASK constant) */
+#define ATOM_TO_LOC(a,s) ((hatom_t)(a)&((s)-1))
+#else /* HASH_SIZE_POWER_2 */
+/* Map an atom to a hash location */
+#define ATOM_TO_LOC(a,s) (((hatom_t)(a)&ATOM_MASK)%(s))
+#endif /* HASH_SIZE_POWER_2 */
+
+/* Atom information structure used */
+typedef struct atom_info_struct_tag {
+ hatom_t id; /* atom ID for this info */
+ VOIDP *obj_ptr; /* pointer associated with the atom */
+ struct atom_info_struct_tag *next; /* link to next atom (in case of hash-clash) */
+ }atom_info_t;
+
+/* Atom group structure used */
+typedef struct atom_group_struct_tag {
+ uintn count; /* # of times this group has been initialized */
+ uintn reserved; /* # of atoms to reserve for constant atoms */
+ uintn wrapped; /* whether the id count has wrapped around */
+ intn hash_size; /* size of the hash table to store the atoms in */
+ uintn atoms; /* current number of atoms held */
+ uintn nextid; /* atom ID to use for the next atom */
+ atom_info_t **atom_list;/* pointer to an array of ptrs to atoms */
+ }atom_group_t;
+
+/* Define this in only one place */
+#ifdef HDF5_ATOM_MASTER
+
+/* Array of pointers to atomic groups */
+static atom_group_t *atom_group_list[MAXGROUP]={NULL};
+
+/* Pointer to the atom node free list */
+static atom_info_t *atom_free_list=NULL;
+
+#ifdef ATOMS_ARE_CACHED
+/* Array of pointers to atomic groups */
+static hatom_t atom_id_cache[ATOM_CACHE_SIZE]={-1,-1,-1,-1};
+static VOIDP atom_obj_cache[ATOM_CACHE_SIZE]={NULL};
+#endif /* ATOMS_ARE_CACHED */
+
+#endif /* HDF5_ATOM_MASTER */
+
+/* Useful routines for generally private use */
+
+#endif /* HDF5_ATOM_MASTER | HDF5_ATOM_TESTER */
+
+#endif /* __ATOM_H */
+
diff --git a/src/H5Aproto.h b/src/H5Aproto.h
new file mode 100644
index 0000000..2bf2ba5
--- /dev/null
+++ b/src/H5Aproto.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5A module
+ */
+
+#ifndef H5APROTO_H
+#define H5APROTO_H
+
+/* Group values allowed */
+typedef enum {BADGROUP=(-1), /* Invalid Group */
+H5_ERR=0, /* Group ID for Error stack objects */
+H5_FILE, /* Group ID for File objects */
+H5_TEMPLATE, /* Group ID for Template objects */
+H5_DATATYPE, /* Group ID for Datatype objects */
+H5_DATASPACE, /* Group ID for Dataspace objects */
+MAXGROUP /* Highest group in group_t (Invalid as true group) */
+} group_t;
+
+/* Type of atoms to return to users */
+typedef int32 hatom_t;
+
+/* Type of the function to compare objects & keys */
+typedef intn (*H5Asearch_func_t)(const VOIDP obj, const VOIDP key);
+
+/* # of bits to use for Group ID in each atom (change if MAXGROUP>16) */
+#define GROUP_BITS 4
+#define GROUP_MASK 0x0F
+
+/* # of bits to use for the Atom index in each atom (assumes 8-bit bytes) */
+#define ATOM_BITS ((sizeof(hatom_t)*8)-GROUP_BITS)
+#define ATOM_MASK 0x0FFFFFFF
+
+/* Combine a Group number and an atom index into an atom */
+#define MAKE_ATOM(g,i) ((((hatom_t)(g)&GROUP_MASK)<<((sizeof(hatom_t)*8)-GROUP_BITS))|((hatom_t)(i)&ATOM_MASK))
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5A.c */
+/******************************************************************************
+ NAME
+ H5Ainit_group - Initialize an atomic group
+
+ DESCRIPTION
+ Creates an atomic group to store atoms in. If the group has already been
+ initialized, this routine just increments the count of # of initializations
+ and returns without trying to change the size of the hash table.
+
+ RETURNS
+ Returns SUCCEED if successful and FAIL otherwise
+
+*******************************************************************************/
+intn H5Ainit_group(group_t grp, /* IN: Group to initialize */
+ intn hash_size, /* IN: Minimum hash table size to use for group */
+ uintn reserved /* IN: Number of hash table entries to reserve */
+);
+
+/******************************************************************************
+ NAME
+ H5Adestroy_group - Destroy an atomic group
+
+ DESCRIPTION
+ Destroys an atomic group which atoms are stored in. If the group still
+ has atoms which are registered, this routine fails. If there have been
+ multiple initializations of the group, this routine just decrements the
+ count of initializations and does not check the atoms out-standing.
+
+ RETURNS
+ Returns SUCCEED if successful and FAIL otherwise
+
+*******************************************************************************/
+intn H5Adestroy_group(group_t grp /* IN: Group to destroy */
+);
+
+/******************************************************************************
+ NAME
+ H5Aregister_atom - Register an object in a group and get an atom for it.
+
+ DESCRIPTION
+ Registers an object in a group and returns an atom for it. This routine
+ does _not_ check for unique-ness of the objects, if you register an object
+ twice, you will get two different atoms for it. This routine does make
+ certain that each atom in a group is unique. Atoms are created by getting
+ a unique number for the group the atom is in and incorporating the group
+ into the atom which is returned to the user.
+
+ RETURNS
+ Returns atom if successful and FAIL otherwise
+
+*******************************************************************************/
+hatom_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */
+ const VOIDP object /* IN: Object to attach to atom */
+);
+
+/******************************************************************************
+ NAME
+ H5Aatom_object - Returns to the object ptr for the atom
+
+ DESCRIPTION
+ Retrieves the object ptr which is associated with the atom.
+
+ RETURNS
+ Returns object ptr if successful and NULL otherwise
+
+*******************************************************************************/
+VOIDP H5Aatom_object(hatom_t atm /* IN: Atom to retrieve object for */
+);
+
+/******************************************************************************
+ NAME
+ H5Aatom_group - Returns to the group for the atom
+
+ DESCRIPTION
+ Retrieves the group which is associated with the atom.
+
+ RETURNS
+ Returns group if successful and FAIL otherwise
+
+*******************************************************************************/
+group_t H5Aatom_group(hatom_t atm /* IN: Atom to retrieve group for */
+);
+
+/******************************************************************************
+ NAME
+ H5Aremove_atom - Removes an atom from a group
+
+ DESCRIPTION
+ Removes an atom from a group.
+
+ RETURNS
+ Returns atom's object if successful and FAIL otherwise
+
+*******************************************************************************/
+VOIDP H5Aremove_atom(hatom_t atm /* IN: Atom to remove */
+);
+
+/******************************************************************************
+ NAME
+ H5Asearch_atom - Search for an object in a group and get it's pointer.
+
+ DESCRIPTION
+ Searchs for an object in a group and returns the pointer to it.
+ This routine calls the function pointer passed in for each object in the
+ group until it finds a match. Currently there is no way to resume a
+ search.
+
+ RETURNS
+ Returns pointer an atom's object if successful and NULL otherwise
+
+*******************************************************************************/
+VOIDP H5Asearch_atom(group_t grp, /* IN: Group to search for the object in */
+ H5Asearch_func_t func, /* IN: Ptr to the comparison function */
+ const VOIDP key /* IN: pointer to key to compare against */
+);
+
+/******************************************************************************
+ NAME
+ H5Ais_reserved - Check whether an atom is a reserved atom in a group
+
+ DESCRIPTION
+ Determines the group an atom belongs to and checks if the atom is a
+ reserved atom in the group.
+
+ RETURNS
+ Returns BTRUE/BFALSE/BFAIL
+
+*******************************************************************************/
+intn H5Ais_reserved(hatom_t atm /* IN: Group to search for the object in */
+);
+
+/******************************************************************************
+ NAME
+ H5Ashutdown - Terminate various static buffers.
+
+ DESCRIPTION
+ Free various buffers allocated in the H5A routines.
+
+ RETURNS
+ Returns SUCCEED/FAIL
+
+*******************************************************************************/
+intn H5Ashutdown(void);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5APROTO_H */
+
diff --git a/src/H5B.c b/src/H5B.c
new file mode 100644
index 0000000..f3a7052
--- /dev/null
+++ b/src/H5B.c
@@ -0,0 +1,1177 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: hdf5btree.c
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Implements balanced, sibling-linked, N-ary trees
+ * capable of storing any type of data with unique key
+ * values.
+ *
+ * A B-link-tree is a balanced tree where each node has
+ * a pointer to its left and right siblings. A
+ * B-link-tree is a rooted tree having the following
+ * properties:
+ *
+ * 1. Every node, x, has the following fields:
+ *
+ * a. level[x], the level in the tree at which node
+ * x appears. Leaf nodes are at level zero.
+ *
+ * b. n[x], the number of children pointed to by the
+ * node. Internal nodes point to subtrees while
+ * leaf nodes point to arbitrary data.
+ *
+ * c. The child pointers themselves, child[x,i] such
+ * that 0 <= i < n[x].
+ *
+ * d. n[x]+1 key values stored in increasing
+ * order:
+ *
+ * key[x,0] < key[x,1] < ... < key[x,n[x]].
+ *
+ * e. left[x] is a pointer to the node's left sibling
+ * or the null pointer if this is the left-most
+ * node at this level in the tree.
+ *
+ * f. right[x] is a pointer to the node's right
+ * sibling or the null pointer if this is the
+ * right-most node at this level in the tree.
+ *
+ * 3. The keys key[x,i] partition the key spaces of the
+ * children of x:
+ *
+ * key[x,i] <= key[child[x,i],j] <= key[x,i+1]
+ *
+ * for any valid combination of i and j.
+ *
+ * 4. There are lower and upper bounds on the number of
+ * child pointers a node can contain. These bounds
+ * can be expressed in terms of a fixed integer k>=2
+ * called the `minimum degree' of the B-tree.
+ *
+ * a. Every node other than the root must have at least
+ * k child pointers and k+1 keys. If the tree is
+ * nonempty, the root must have at least one child
+ * pointer and two keys.
+ *
+ * b. Every node can contain at most 2k child pointers
+ * and 2k+1 keys. A node is `full' if it contains
+ * exactly 2k child pointers and 2k+1 keys.
+ *
+ * 5. When searching for a particular value, V, and
+ * key[V] = key[x,i] for some node x and entry i,
+ * then:
+ *
+ * a. If i=0 the child[0] is followed.
+ *
+ * b. If i=n[x] the child[n[x]-1] is followed.
+ *
+ * c. Otherwise, the child that is followed
+ * (either child[x,i-1] or child[x,i]) is
+ * determined by the type of object to which the
+ * leaf nodes of the tree point and is controlled
+ * by the key comparison function registered for
+ * that type of B-tree.
+ *
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Define this if the root address of a B-link tree should never change.
+ *
+ * If this isn't defined and the root node of a tree splits, then the
+ * new root (which points to the old root plus the new node from the
+ * split) will be at a new file address.
+ *
+ * But if this is defined, then the old root will be copied to a new
+ * location and the new root will occupy the file memory vacated by the
+ * old root.
+ */
+#define H5B_ANCHOR_ROOT
+
+/* system headers */
+#include <assert.h>
+#include "hdf5.h"
+
+/* private headers */
+#include "H5ACprivate.h" /*cache */
+#include "H5Bprivate.h" /*B-link trees */
+#include "H5MFprivate.h" /*File memory management */
+#include "H5MMprivate.h" /*Core memory management */
+
+#define BOUND(MIN,X,MAX) ((MIN)<(X)?(MIN):((MAX)>(X)?(MAX):(X)))
+#define false 0
+#define true 1
+
+/* PRIVATE PROTOTYPES */
+static off_t H5B_insert_helper (hdf5_file_t *f, off_t addr,
+ const H5B_class_t *type,
+ uint8 *lt_key, intn *lt_key_changed,
+ uint8 *md_key, void *udata,
+ uint8 *rt_key, intn *rt_key_changed);
+static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, off_t addr,
+ H5B_t *b);
+static H5B_t *H5B_load (hdf5_file_t *f, off_t addr, const void *_data);
+static herr_t H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx);
+static size_t H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
+ size_t *total_nkey_size, size_t sizeof_rkey);
+
+/* H5B inherits cache-like properties from H5AC */
+static const H5AC_class_t H5AC_BT[1] = {{
+ (void*(*)(hdf5_file_t*,off_t,const void*))H5B_load,
+ (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5B_flush,
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_new
+ *
+ * Purpose: Creates a new empty B-tree leaf node.
+ *
+ * Return: Success: address of new node.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+off_t
+H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey)
+{
+ H5B_t *bt=NULL;
+ off_t addr;
+ size_t size;
+ size_t total_native_keysize;
+ intn offset, i;
+
+ /*
+ * Allocate file and memory data structures.
+ */
+ size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey);
+ if ((addr = H5MF_alloc (f, size))<=0) return 0;
+ bt = H5MM_xmalloc (sizeof(H5B_t));
+ bt->type = type;
+ bt->sizeof_rkey = sizeof_rkey;
+ bt->dirty = 1;
+ bt->ndirty = 0;
+ bt->type = type;
+ bt->level = 0;
+ bt->left = bt->right = 0;
+ bt->nchildren = 0;
+ bt->page = H5MM_xmalloc (size);
+ bt->native = H5MM_xmalloc (total_native_keysize);
+ bt->child = H5MM_xmalloc (2*type->k * sizeof(off_t));
+ bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t));
+
+ /*
+ * Initialize each entry's raw child and key pointers to point into the
+ * `page' buffer. Each native key pointer should be null until the key is
+ * translated to native format.
+ */
+ for (i=0,offset=H5B_HDR_SIZE(f);
+ i<2*type->k;
+ i++,offset+=bt->sizeof_rkey+SIZEOF_OFFSET(f)) {
+
+ bt->key[i].dirty = 0;
+ bt->key[i].rkey = bt->page + offset;
+ bt->key[i].nkey = NULL;
+ bt->child[i] = 0;
+ }
+
+ /*
+ * The last possible key...
+ */
+ bt->key[2*type->k].dirty = 0;
+ bt->key[2*type->k].rkey = bt->page + offset;
+ bt->key[2*type->k].nkey = NULL;
+
+ /*
+ * Cache the new B-tree node.
+ */
+ H5AC_set (f, H5AC_BT, addr, bt);
+ return addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_load
+ *
+ * Purpose: Loads a B-tree node from the disk.
+ *
+ * Return: Success: Pointer to a new B-tree node.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5B_t *
+H5B_load (hdf5_file_t *f, off_t addr, const void *_data)
+{
+ const H5B_class_t *type = (const H5B_class_t *)_data;
+ size_t size, total_nkey_size;
+ H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t));
+ intn i;
+ uint8 *p;
+
+ assert (type);
+ assert (type->get_sizeof_rkey);
+
+
+ bt->sizeof_rkey = (type->get_sizeof_rkey)(f);
+ size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey);
+ bt->type = type;
+ bt->dirty = 0;
+ bt->ndirty = 0;
+ bt->page = H5MM_xmalloc (size);
+ bt->native = H5MM_xmalloc (total_nkey_size);
+ bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t));
+ bt->child = H5MM_xmalloc (2 * type->k * sizeof(off_t));
+ H5F_block_read (f, addr, size, bt->page);
+ p = bt->page;
+
+ /* magic number */
+ if (memcmp (p, H5B_MAGIC, 4)) goto error;
+ p += 4;
+
+ /* node type and level */
+ if (*p++ != type->id) goto error;
+ bt->level = *p++;
+
+ /* entries used */
+ UINT16DECODE (p, bt->nchildren);
+
+ /* sibling pointers */
+ H5F_decode_offset (f, p, bt->left);
+ H5F_decode_offset (f, p, bt->right);
+
+ /* the child/key pairs */
+ for (i=0; i<2*type->k; i++) {
+
+ bt->key[i].dirty = 0;
+ bt->key[i].rkey = p;
+ p += bt->sizeof_rkey;
+ bt->key[i].nkey = NULL;
+
+ if (i<bt->nchildren) {
+ H5F_decode_offset (f, p, bt->child[i]);
+ } else {
+ bt->child[i] = 0;
+ p += SIZEOF_OFFSET(f);
+ }
+ }
+
+ bt->key[2*type->k].dirty = 0;
+ bt->key[2*type->k].rkey = p;
+ bt->key[2*type->k].nkey = NULL;
+ return bt;
+
+error:
+ if (bt) {
+ H5MM_xfree (bt->child);
+ H5MM_xfree (bt->key);
+ H5MM_xfree (bt->page);
+ H5MM_xfree (bt->native);
+ H5MM_xfree (bt);
+ }
+ return NULL;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_flush
+ *
+ * Purpose: Flushes a dirty B-tree node to disk.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5B_t *bt)
+{
+ intn i;
+ size_t size = H5B_nodesize (f, bt->type, NULL, bt->sizeof_rkey);
+ uint8 *p = bt->page;
+
+ assert (bt->type);
+ assert (bt->type->encode);
+
+ if (bt->dirty) {
+
+ /* magic number */
+ memcpy (p, H5B_MAGIC, 4);
+ p += 4;
+
+ /* node type and level */
+ *p++ = bt->type->id;
+ *p++ = bt->level;
+
+ /* entries used */
+ UINT16ENCODE (p, bt->nchildren);
+
+ /* sibling pointers */
+ H5F_encode_offset (f, p, bt->left);
+ H5F_encode_offset (f, p, bt->right);
+
+ /* child keys and pointers */
+ for (i=0; i<=bt->nchildren; i++) {
+
+ /* encode the key */
+ assert (bt->key[i].rkey == p);
+ if (bt->key[i].dirty) {
+ if (bt->key[i].nkey) {
+ (bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey);
+ }
+ bt->key[i].dirty = 0;
+ }
+ p += bt->sizeof_rkey;
+
+ /* encode the child address */
+ if (i<bt->ndirty) {
+ H5F_encode_offset (f, p, bt->child[i]);
+ } else {
+ p += SIZEOF_OFFSET(f);
+ }
+ }
+
+ /*
+ * Write the disk page. We always write the header, but we don't
+ * bother writing data for the child entries that don't exist or
+ * for the final unchanged children.
+ */
+ H5F_block_write (f, addr, size, bt->page);
+ bt->dirty = 0;
+ bt->ndirty = 0;
+ }
+
+ if (destroy) {
+ H5MM_xfree (bt->child);
+ H5MM_xfree (bt->key);
+ H5MM_xfree (bt->page);
+ H5MM_xfree (bt->native);
+ H5MM_xfree (bt);
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_find
+ *
+ * Purpose: Locate the specified information in a B-tree and return
+ * that information by filling in fields of the caller-supplied
+ * UDATA pointer depending on the type of leaf node
+ * requested. The UDATA can point to additional data passed
+ * to the key comparison function.
+ *
+ * Note: This function does not follow the left/right sibling
+ * pointers since it assumes that all nodes can be reached
+ * from the parent node.
+ *
+ * Return: Success: 0 if found, values returned through the
+ * RETVAL argument.
+ *
+ * Failure: -1 if not found.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B_find (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata)
+{
+ H5B_t *bt=NULL;
+ uint8 lt_key[256], rt_key[256];
+ intn idx=-1, lt=0, rt, cmp=1;
+
+ assert (type);
+ assert (type->sizeof_nkey < sizeof lt_key);
+ assert (type->decode);
+ assert (type->cmp);
+ assert (type->found);
+
+ /*
+ * Perform a binary search to locate the child which contains
+ * the thing for which we're searching. The comparison function
+ * may preempt the B-tree node from the cache.
+ */
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ rt = bt->nchildren;
+
+ while (lt<rt && cmp) {
+ idx = (lt + rt) / 2;
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ if (!bt) return -1;
+
+ /* the left key */
+ if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx);
+ HDmemcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey);
+
+ /* the right key */
+ if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1);
+ HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
+
+ /* compare */
+ if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) {
+ rt = idx;
+ } else {
+ lt = idx+1;
+ }
+ }
+ if (cmp) return -1;
+
+ /*
+ * Follow the link to the subtree or to the data node.
+ */
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ assert (idx>=0 && idx<bt->nchildren);
+ if (bt->level > 0) {
+ return H5B_find (f, type, bt->child[idx], udata);
+ }
+
+ return (type->found)(f, bt->child[idx], lt_key, udata, rt_key);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_split
+ *
+ * Purpose: Split a single node into two nodes. If anchor is
+ * H5B_ANCHOR_LT then the new node gets the right half of
+ * the old node. If anchor is H5B_ANCHOR_RT then the
+ * new node gets the left half of the old node.
+ *
+ * Return: Success: Address of the new node.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 3 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static off_t
+H5B_split (hdf5_file_t *f, const H5B_class_t *type, off_t addr, intn anchor)
+{
+ H5B_t *old = H5AC_find (f, H5AC_BT, addr, type);
+ H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t));
+ size_t total_nkey_size, size;
+ intn i, offset;
+ intn delta = H5B_ANCHOR_LT==anchor ? type->k : 0;
+ size_t recsize = old->sizeof_rkey + SIZEOF_OFFSET(f);
+ off_t tmp_addr, new_addr;
+ H5B_t *tmp=NULL;
+
+ /*
+ * Create the new B-tree node.
+ */
+ size = H5B_nodesize (f, type, &total_nkey_size, old->sizeof_rkey);
+ bt->dirty = 1;
+ bt->ndirty = BOUND (0, old->ndirty-delta, type->k);
+ bt->type = type;
+ bt->level = old->level;
+ bt->nchildren = type->k;
+ bt->page = H5MM_xmalloc (size);
+ bt->native = H5MM_xmalloc (total_nkey_size);
+ bt->child = H5MM_xmalloc (2*type->k * sizeof(off_t));
+ bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t));
+
+ /*
+ * Copy data into the new node from the old node.
+ */
+ memcpy (bt->page + H5B_HDR_SIZE(f),
+ old->page + H5B_HDR_SIZE(f) + delta*recsize,
+ type->k * recsize);
+ memcpy (bt->native,
+ old->native + delta * type->sizeof_nkey,
+ (type->k+1) * type->sizeof_nkey);
+
+ for (i=0,offset=H5B_HDR_SIZE(f); i<=2*type->k; i++,offset+=recsize) {
+
+ /* key */
+ if (i<=type->k) {
+ bt->key[i].dirty = old->key[delta+i].dirty;
+ bt->key[i].rkey = bt->native + offset;
+ if (old->key[delta+i].nkey) {
+ bt->key[i].nkey = bt->native + i*type->sizeof_nkey;
+ } else {
+ bt->key[i].nkey = NULL;
+ }
+ } else {
+ bt->key[i].dirty = 0;
+ bt->key[i].rkey = bt->native + offset;
+ bt->key[i].nkey = NULL;
+ }
+
+ /* child */
+ if (i<type->k) {
+ bt->child[i] = old->child[delta+i];
+ } else if (i<2*type->k) {
+ bt->child[i] = 0;
+ }
+ }
+
+
+ /*
+ * Truncate the old node.
+ */
+ delta = H5B_ANCHOR_LT ? 0 : type->k;
+ old->dirty += 1;
+ old->ndirty = BOUND (0, old->ndirty-delta, type->k);
+ old->nchildren = type->k;
+
+ if (H5B_ANCHOR_RT==anchor) {
+ memcpy (old->page + H5B_HDR_SIZE(f),
+ old->page + H5B_HDR_SIZE(f) + delta*recsize,
+ type->k * recsize);
+ memmove (old->native,
+ old->native + delta * type->sizeof_nkey,
+ (type->k+1) * type->sizeof_nkey);
+
+ for (i=0; i<=2*type->k; i++) {
+
+ if (i<=type->k) {
+ old->key[i].dirty = old->key[delta+i].dirty;
+ if (old->key[delta+i].nkey) {
+ old->key[i].nkey = old->native + i * type->sizeof_nkey;
+ } else {
+ old->key[i].nkey = NULL;
+ }
+ } else {
+ old->key[i].nkey = NULL;
+ }
+ if (i<type->k) {
+ old->child[i] = old->child[delta+i];
+ } else if (i<2*type->k) {
+ old->child[i] = 0;
+ }
+ }
+ }
+
+ /*
+ * Update sibling pointers of new node.
+ */
+ if (H5B_ANCHOR_LT==anchor) {
+ bt->left = addr;
+ bt->right = old->right;
+ } else {
+ bt->left = old->left;
+ bt->right = addr;
+ }
+
+ /*
+ * Add the new node to the cache.
+ */
+ new_addr = H5MF_alloc (f, size);
+ H5AC_set (f, H5AC_BT, new_addr, bt);
+
+ /*
+ * Update sibling pointers of old nodes.
+ */
+ old = H5AC_find (f, H5AC_BT, addr, type);
+ if (H5B_ANCHOR_LT==anchor) {
+ old->dirty += 1;
+ tmp_addr = old->right;
+ old->right = new_addr;
+ if (tmp_addr) {
+ tmp = H5AC_find (f, H5AC_BT, tmp_addr, type);
+ tmp->dirty += 1;
+ tmp->left = new_addr;
+ }
+ } else {
+ old->dirty += 1;
+ tmp_addr = old->left;
+ old->left = new_addr;
+ if (tmp_addr) {
+ tmp = H5AC_find (f, H5AC_BT, tmp_addr, type);
+ tmp->dirty += 1;
+ tmp->right = new_addr;
+ }
+ }
+
+ return new_addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_decode_key
+ *
+ * Purpose: Decode the specified key into native format.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 8 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx)
+{
+ bt->key[idx].nkey = bt->native + idx * bt->type->sizeof_nkey;
+ (bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_insert
+ *
+ * Purpose: Adds a new item to the B-tree. If the root node of
+ * the B-tree splits then the B-tree gets a new address.
+ *
+ * Return: Success: Address of the root of the B-tree. The
+ * B-tree root address may change if the old
+ * root is split.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+off_t
+H5B_insert (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata)
+{
+ uint8 lt_key[256], md_key[256], rt_key[256];
+ intn lt_key_changed=false, rt_key_changed=false;
+ off_t child, new_root;
+ intn level;
+ H5B_t *bt;
+
+ assert (type);
+ assert (type->sizeof_nkey < sizeof lt_key);
+
+ child = H5B_insert_helper (f, addr, type, lt_key, &lt_key_changed,
+ md_key, udata, rt_key, &rt_key_changed);
+ if (child<0) return 0;
+ if (0==child) return addr;
+
+ /* the current root */
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ level = bt->level;
+ if (!lt_key_changed) {
+ if (!bt->key[0].nkey) H5B_decode_key (f, bt, 0);
+ memcpy (lt_key, bt->key[0].nkey, type->sizeof_nkey);
+ }
+
+ /* the new node */
+ bt = H5AC_find (f, H5AC_BT, child, type);
+ if (!rt_key_changed) {
+ if (!bt->key[bt->nchildren].nkey) H5B_decode_key (f, bt, bt->nchildren);
+ memcpy (rt_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey);
+ }
+
+#ifdef H5B_ANCHOR_ROOT
+ {
+ /*
+ * Copy the old root node to some other file location and make the new
+ * root at the old root's previous address. This prevents the B-tree
+ * from "moving".
+ */
+ size_t size = H5B_nodesize (f, type, NULL, bt->sizeof_rkey);
+ uint8 *buf = H5MM_xmalloc (size);
+ off_t tmp_addr = H5MF_alloc (f, size);
+
+ H5AC_flush (f, H5AC_BT, addr, FALSE);
+ H5F_block_read (f, addr, size, buf);
+ H5F_block_write (f, tmp_addr, size, buf);
+ H5AC_rename (f, H5AC_BT, addr, tmp_addr);
+
+ buf = H5MM_xfree (buf);
+ new_root = addr;
+ addr = tmp_addr;
+
+ /* update the new child's left pointer */
+ bt = H5AC_find (f, H5AC_BT, child, type);
+ bt->dirty += 1;
+ bt->left = addr;
+
+ /* clear the old root at the old address */
+ bt = H5AC_find (f, H5AC_BT, new_root, type);
+ bt->dirty += 1;
+ bt->ndirty = 0;
+ bt->left = 0;
+ bt->right = 0;
+ bt->nchildren = 0;
+ }
+#else
+ /*
+ * The new root is created at a new file location.
+ */
+ new_root = H5B_new (f, type, bt->sizeof_rkey);
+#endif
+
+ /* the new root */
+ bt = H5AC_find (f, H5AC_BT, new_root, type);
+ bt->dirty += 1;
+ bt->ndirty = 2;
+ bt->level = level+1;
+ bt->nchildren = 2;
+
+ bt->child[0] = addr;
+ bt->key[0].dirty = 1;
+ bt->key[0].nkey = bt->native;
+ memcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey);
+
+ bt->child[1] = child;
+ bt->key[1].dirty = 1;
+ bt->key[1].nkey = bt->native + type->sizeof_nkey;
+ memcpy (bt->key[1].nkey, md_key, type->sizeof_nkey);
+
+ bt->key[2].dirty = 1;
+ bt->key[2].nkey = bt->native + 2 * type->sizeof_nkey;
+ memcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey);
+
+ return new_root;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_insert_child
+ *
+ * Purpose: Insert a child at the specified address with the
+ * specified left or right key.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 8 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, off_t addr,
+ intn idx, off_t child, intn anchor, void *md_key)
+{
+ H5B_t *bt;
+ size_t recsize;
+ intn i;
+
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ assert (bt);
+ bt->dirty += 1;
+ recsize = bt->sizeof_rkey + SIZEOF_OFFSET(f);
+
+ if (H5B_ANCHOR_LT==anchor) {
+ /*
+ * The MD_KEY is the left key of the new node.
+ */
+ memmove (bt->page + H5B_HDR_SIZE(f) + (idx+1)*recsize,
+ bt->page + H5B_HDR_SIZE(f) + idx*recsize,
+ (bt->nchildren-idx)*recsize + bt->sizeof_rkey);
+
+ memmove (bt->native + (idx+1) * type->sizeof_nkey,
+ bt->native + idx * type->sizeof_nkey,
+ ((bt->nchildren-idx)+1) * type->sizeof_nkey);
+
+ for (i=bt->nchildren; i>=idx; --i) {
+ bt->key[i+1].dirty = bt->key[i].dirty;
+ }
+ bt->key[idx].dirty = 1;
+ bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey;
+ memcpy (bt->key[idx].nkey, md_key, type->sizeof_nkey);
+
+ } else {
+ /*
+ * The MD_KEY is the right key of the new node.
+ */
+ memmove (bt->page + (H5B_HDR_SIZE(f) +
+ (idx+1)*recsize + bt->sizeof_rkey),
+ bt->page + (H5B_HDR_SIZE(f) +
+ idx*recsize + bt->sizeof_rkey),
+ (bt->nchildren-idx) * recsize);
+
+ memmove (bt->native + idx + 2,
+ bt->native + idx + 1,
+ (bt->nchildren-idx) * type->sizeof_nkey);
+
+ for (i=bt->nchildren; i>idx; --i) {
+ bt->key[i+1].dirty = bt->key[i].dirty;
+ }
+ bt->key[idx+1].dirty = 1;
+ bt->key[idx+1].nkey = bt->native +
+ (idx+1) * type->sizeof_nkey;
+ memcpy (bt->key[idx+1].nkey, md_key, type->sizeof_nkey);
+ }
+
+ memmove (bt->child + idx + 1,
+ bt->child + idx,
+ (bt->nchildren - idx) * sizeof(off_t));
+
+ bt->child[idx] = child;
+ bt->nchildren += 1;
+ bt->ndirty = bt->nchildren;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_insert_helper
+ *
+ * Purpose: Inserts the item UDATA into the tree rooted at ADDR and having
+ * the specified type.
+ *
+ * On return, if LT_KEY_CHANGED is non-zero, then LT_KEY is
+ * the new native left key. Similarily for RT_KEY_CHANGED
+ * and RT_KEY.
+ *
+ * If the node splits, then MD_KEY contains the key that
+ * was split between the two nodes (that is, the key that
+ * appears as the max key in the left node and the min key
+ * in the right node).
+ *
+ * Return: Success: Address of the new node if the node
+ * splits. The new node is always to the
+ * right of the previous node.
+ *
+ * 0 if the node didn't split. The MD_KEY
+ * buffer is undefined.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 9 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static off_t
+H5B_insert_helper (hdf5_file_t *f, off_t addr, const H5B_class_t *type,
+ uint8 *lt_key, intn *lt_key_changed,
+ uint8 *md_key, void *udata,
+ uint8 *rt_key, intn *rt_key_changed)
+{
+ H5B_t *bt;
+ intn lt=0, idx=-1, rt, cmp=-1;
+ intn anchor;
+ off_t child, twin=0;
+
+ assert (type);
+ assert (type->decode);
+ assert (type->cmp);
+ assert (type->new);
+
+ /*
+ * Use a binary search to find the child that will receive the new
+ * data. The comparison function may preempt the B-tree node from
+ * the cache each time through the loop. When the search completes
+ * IDX points to the child that should get the new data.
+ */
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ if (!bt) goto error;
+ rt = bt->nchildren;
+
+ while (lt<rt && cmp) {
+ idx = (lt + rt) / 2;
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ if (!bt) goto error;
+
+ /* left key */
+ if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx);
+ memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey);
+
+ /* right key */
+ if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1);
+ memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
+
+ /* compare */
+ if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) {
+ rt = idx;
+ } else {
+ lt = idx+1;
+ }
+ }
+
+ /*
+ * Adjust for boundary conditions. If adjusting at the leaf level
+ * update the left and right key buffers since the data node insert
+ * function needs them as input. Don't worry about it at higher node
+ * levels because this function uses them for output only.
+ */
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ if (cmp<0 && idx<=0) {
+ idx = 0;
+ cmp = 0;
+ if (0==bt->level && bt->nchildren) {
+ if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx);
+ memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey);
+ if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1);
+ memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
+ }
+ } else if (cmp>0 && idx+1>=bt->nchildren) {
+ idx = bt->nchildren-1;
+ cmp = 0;
+ if (0==bt->level && bt->nchildren) {
+ if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx);
+ memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey);
+ if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1);
+ memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey);
+ }
+ }
+ assert (0==cmp);
+
+ /*
+ * If there are no children, then create a new child. This can only
+ * happen at the root of the B-tree. Creating a new child may
+ * preempt the B-tree node from the cache. The left and right key
+ * buffers are output values.
+ */
+ if (0==bt->nchildren) {
+ child = (type->new)(f, lt_key, udata, rt_key);
+ if (child<=0) goto error;
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ bt->nchildren = 1;
+ bt->dirty += 1;
+ bt->ndirty = 1;
+ bt->child[0] = child;
+
+ bt->key[0].dirty = 1;
+ bt->key[0].nkey = bt->native;
+ memcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey);
+
+ bt->key[1].dirty = 1;
+ bt->key[1].nkey = bt->native + type->sizeof_nkey;
+ memcpy (bt->key[1].nkey, rt_key, type->sizeof_nkey);
+ idx = 0;
+ }
+
+ /*
+ * Insert the new data in the child B-tree node or in the data node.
+ */
+ if (bt->level > 0) {
+ child = H5B_insert_helper (f, bt->child[idx], type,
+ lt_key, lt_key_changed,
+ md_key, udata,
+ rt_key, rt_key_changed);
+ anchor = H5B_ANCHOR_LT;
+ } else {
+ child = (type->insert)(f, bt->child[idx], &anchor,
+ lt_key, lt_key_changed,
+ md_key, udata,
+ rt_key, rt_key_changed);
+ }
+ if (child<0) goto error;
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+
+ /*
+ * Update the left and right keys.
+ */
+ if (*lt_key_changed) {
+ bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey;
+ memcpy (bt->key[idx].nkey, lt_key, type->sizeof_nkey);
+ bt->dirty += 1;
+ bt->key[idx].dirty = 1;
+ if (idx>0) *lt_key_changed = false;
+ }
+ if (*rt_key_changed) {
+ bt->key[idx+1].nkey = bt->native +
+ (idx+1) * type->sizeof_nkey;
+ memcpy (bt->key[idx+1].nkey, rt_key, type->sizeof_nkey);
+ bt->dirty += 1;
+ bt->key[idx+1].dirty = 1;
+ if (idx+1<bt->nchildren) *rt_key_changed = false;
+ }
+
+ /*
+ * If the child split and the left node is anchored, then the new
+ * child node gets inserted to the right of our current position.
+ */
+ if (child && H5B_ANCHOR_LT==anchor) idx++;
+
+ /*
+ * Split this node if the child node split and this node is full.
+ * Make sure `addr' points to the node that gets the new child
+ * and that `idx' is adjusted appropriately.
+ */
+ if (child && bt->nchildren==2*type->k) {
+ twin = H5B_split (f, type, addr, anchor);
+ if (idx<=type->k) {
+ addr = H5B_ANCHOR_LT==anchor ? addr : twin;
+ } else {
+ idx -= type->k;
+ addr = H5B_ANCHOR_LT==anchor ? twin : addr;
+ }
+ }
+
+ /*
+ * If the child split, then insert the new child.
+ */
+ if (child) {
+ H5B_insert_child (f, type, addr, idx, child, anchor, md_key);
+ }
+
+ /*
+ * If this node split, return the mid key (the one that is shared
+ * by the left and right node).
+ */
+ if (twin) {
+ bt = H5AC_find (f, H5AC_BT, twin, type);
+ if (H5B_ANCHOR_LT==anchor) {
+ if (!bt->key[0].nkey) {
+ H5B_decode_key (f, bt, 0);
+ }
+ memcpy (md_key, bt->key[0].nkey, type->sizeof_nkey);
+ } else {
+ if (!bt->key[bt->nchildren].nkey) {
+ H5B_decode_key (f, bt, bt->nchildren);
+ }
+ memcpy (md_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey);
+ }
+ }
+
+ return twin;
+
+error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_list
+ *
+ * Purpose: Calls the list callback for each leaf node of the
+ * B-tree, passing it the UDATA structure.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B_list (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata)
+{
+ H5B_t *bt;
+ off_t *child=NULL;
+ off_t twin;
+ intn i, nchildren, status;
+ herr_t (*list)(hdf5_file_t*,off_t,void*);
+
+ assert (type);
+ assert (type->list);
+
+ bt = H5AC_find (f, H5AC_BT, addr, type);
+ if (!bt) return -1;
+
+ if (bt->level>0) {
+ return H5B_list (f, type, bt->child[0], udata);
+ } else {
+ child = H5MM_xmalloc (2 * type->k * sizeof(off_t));
+ list = type->list;
+ twin = addr;
+
+ while (twin) { /*for each leaf node*/
+ bt = H5AC_find (f, H5AC_BT, twin, type);
+ if (!bt) {
+ H5MM_xfree (child);
+ return -1;
+ }
+ nchildren = bt->nchildren;
+ twin = bt->right;
+ HDmemcpy (child, bt->child, nchildren * sizeof(off_t));
+ bt = NULL; /*list callback may invalidate the cache*/
+
+ for (i=0; i<nchildren; i++) {
+ status = (list)(f, child[i], udata);
+ if (status<0) {
+ H5MM_xfree (child);
+ return -1;
+ }
+ }
+ }
+ H5MM_xfree (child);
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_nodesize
+ *
+ * Purpose: Returns the number of bytes needed for this type of
+ * B-tree node. The size is the size of the header plus
+ * enough space for 2t child pointers and 2t+1 keys.
+ *
+ * If TOTAL_NKEY_SIZE is non-null, what it points to will
+ * be initialized with the total number of bytes required to
+ * hold all the key values in native order.
+ *
+ * Return: Success: Size of node in file.
+ *
+ * Failure: never fails.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 3 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type,
+ size_t *total_nkey_size, size_t sizeof_rkey)
+{
+ if (total_nkey_size) {
+ *total_nkey_size = (2 * type->k + 1) * type->sizeof_nkey;
+ }
+
+ return (H5B_HDR_SIZE(f) + /*node header */
+ 2 * type->k * SIZEOF_OFFSET(f) + /*child pointers*/
+ (2*type->k+1) * sizeof_rkey); /*keys */
+}
+
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
new file mode 100644
index 0000000..d6ecc7c
--- /dev/null
+++ b/src/H5Bprivate.h
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Bprivate.h
+ * Jul 10 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Private non-prototype header.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Bprivate_H
+#define _H5Bprivate_H
+
+#include "H5Bproto.h" /*API prototypes */
+
+
+
+#define H5B_MAGIC "TREE" /* tree node magic number */
+#define H5B_HDR_SIZE(F) (8+2*SIZEOF_OFFSET(F))
+
+#define H5B_ANCHOR_LT 0 /* left node is anchored, right is new */
+#define H5B_ANCHOR_RT 1 /* right node is anchored, left is new */
+
+
+/*
+ * Each class of object that can be pointed to by a B-link tree has a
+ * variable of this type that contains class variables and methods.
+ */
+typedef struct H5B_class_t {
+ intn id; /*id as found in file */
+ intn k; /* max children is 2k */
+ size_t sizeof_nkey; /*size of native (memory) key */
+ size_t (*get_sizeof_rkey)(hdf5_file_t*);
+ off_t (*new)(hdf5_file_t*,void*,void*,void*);
+ intn (*cmp)(hdf5_file_t*,void*,void*,void*);
+ herr_t (*found)(hdf5_file_t*,off_t,void*,void*,void*);
+ off_t (*insert)(hdf5_file_t*,off_t,int*,void*,int*,void*,void*,
+ void*,int*);
+ herr_t (*list)(hdf5_file_t*,off_t,void*);
+ void (*decode)(hdf5_file_t*,uint8*,void*);
+ void (*encode)(hdf5_file_t*,uint8*,void*);
+} H5B_class_t;
+
+/*
+ * The B-tree node as stored in memory...
+ */
+typedef struct H5B_key_t {
+ intn dirty; /*native key is more recent than raw key*/
+ uint8 *rkey; /*ptr into node->page for raw key */
+ void *nkey; /*null or ptr into node->native for key */
+} H5B_key_t;
+
+typedef struct H5B_t {
+ const H5B_class_t *type; /*type of tree */
+ size_t sizeof_rkey; /*size of raw (disk) key */
+ intn dirty; /*something in the tree is dirty */
+ intn ndirty; /*num child ptrs to emit */
+ intn level; /*node level */
+ off_t left; /*address of left sibling */
+ off_t right; /*address of right sibling */
+ intn nchildren; /*number of child pointers */
+ uint8 *page; /*disk page */
+ uint8 *native; /*array of keys in native format */
+ H5B_key_t *key; /*2k+1 key entries */
+ off_t *child; /*2k child pointers */
+} H5B_t;
+
+
+/*
+ * Library prototypes.
+ */
+herr_t H5B_debug (hdf5_file_t *f, off_t addr, const H5B_class_t *type);
+off_t H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey);
+herr_t H5B_find (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata);
+off_t H5B_insert (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata);
+herr_t H5B_list (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata);
+
+
+#endif /* !_H5Bprivate_H */
diff --git a/src/H5Bproto.h b/src/H5Bproto.h
new file mode 100644
index 0000000..3869db4
--- /dev/null
+++ b/src/H5Bproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Bproto.h
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Non-API function prototypes for B-link trees.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Bproto_H
+#define _H5Bproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5C.c b/src/H5C.c
new file mode 100644
index 0000000..847f3b5
--- /dev/null
+++ b/src/H5C.c
@@ -0,0 +1,506 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ hdf5file.c
+ HDF5 "personality template" routines
+
+ EXPORTED ROUTINES
+ H5Csetparm -- Set a parameter for a template
+ H5Cgetparm -- Get a parameter for a template
+
+ LIBRARY-SCOPED ROUTINES
+
+ LOCAL ROUTINES
+ H5C_init_interface -- initialize the interface
+ + */
+
+#include "hdf5.h"
+
+/* private header files */
+#include "H5private.h" /* Generic Functions */
+#include "H5Cprivate.h" /* Template information */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/* Define the library's default file creation template (constants in hdf5lims.h) */
+const file_create_temp_t default_file_create={
+ HDF5_USERBLOCK_DEFAULT, /* Default user-block size */
+ HDF5_OFFSETSIZE_DEFAULT, /* Default offset size */
+ HDF5_LENGTHSIZE_DEFAULT, /* Default length size */
+ HDF5_BTREEPAGE_DEFAULT, /* Default B-tree page size */
+ HDF5_BOOTBLOCK_VERSION, /* Current Boot-Block version # */
+ HDF5_SMALLOBJECT_VERSION, /* Current Small-Object heap version # */
+ HDF5_FREESPACE_VERSION, /* Current Free-Space info version # */
+ HDF5_OBJECTDIR_VERSION, /* Current Object Directory info version # */
+ HDF5_SHAREDHEADER_VERSION /* Current Shared-Header format version # */
+};
+static hatom_t default_file_id=FAIL; /* Atom for the default file-creation template */
+
+/*--------------------- Local function prototypes ----------------------------*/
+static herr_t H5C_init_interface(void);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5C_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5C_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5C_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5C_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5C_mask, ID_H5C_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ /* Initialize the atom group for the file IDs */
+ ret_value=H5Ainit_group(H5_TEMPLATE,HDF5_TEMPID_HASHSIZE,0);
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_init_interface, ret_value);
+} /* H5C_init_interface */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5C_get_default_atom
+ PURPOSE
+ Retrive an atom for a default HDF5 template.
+ USAGE
+ hatom_t H5C_create(type)
+ hobjtype_t type; IN: Type of object to retrieve default template of
+ RETURNS
+ Returns template ID (atom) of the default object for a template type on
+ success, FAIL on failure
+ DESCRIPTION
+ This is function retrieves atoms for the default templates for the
+ different types of HDF5 templates.
+--------------------------------------------------------------------------*/
+hatom_t H5C_get_default_atom(hobjtype_t type)
+{
+ CONSTR(FUNC, "H5C_create"); /* for HERROR */
+ hatom_t ret_value = FAIL;
+
+ FUNC_ENTER(H5C_mask, ID_H5C_get_default_atom, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ switch(type)
+ {
+ case H5_TEMPLATE:
+ if(default_file_id==FAIL)
+ {
+ if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)&default_file_create))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+ } /* end else */
+ HGOTO_DONE(default_file_id);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+ } /* end switch */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_get_default_atom, ret_value);
+} /* end H5C_get_default_atom() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5C_init
+ PURPOSE
+ Initialize a new HDF5 template with a copy of an existing template.
+ USAGE
+ herr_t H5C_init(dst_atm, src)
+ hatom_t dst_atm; IN: Atom for the template to initialize
+ file_create_temp_t *src; IN: Template to use to initialize with
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function copies the contents of the source template into the
+ newly created destination template.
+--------------------------------------------------------------------------*/
+herr_t H5C_init(hatom_t dst_atm, const file_create_temp_t *src)
+{
+ CONSTR(FUNC, "H5C_init"); /* for HERROR */
+ file_create_temp_t *dst; /* destination template */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER(H5C_mask, ID_H5C_init, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(src==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* Get the template to initialize */
+ if((dst=H5Aatom_object(dst_atm))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Copy in the source template */
+ HDmemcpy(dst,src,sizeof(file_create_temp_t));
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_init, ret_value);
+} /* end H5C_init() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5C_create
+ PURPOSE
+ Create a new HDF5 template.
+ USAGE
+ hatom_t H5C_create(owner_id, type, name)
+ hatom_t owner_id; IN: Group/file which owns this template
+ hobjtype_t type; IN: Type of template to create
+ const char *name; IN: Name of the template to create
+ RETURNS
+ Returns template ID (atom) on success, FAIL on failure
+ DESCRIPTION
+ This is the primary function for creating different HDF5 templates.
+ Currently the name of template is not used and may be NULL.
+--------------------------------------------------------------------------*/
+hatom_t H5C_create(hatom_t owner_id, hobjtype_t type, const char *name)
+{
+ CONSTR(FUNC, "H5C_create"); /* for HERROR */
+ hatom_t ret_value = FAIL; /* atom for template object to return */
+
+ FUNC_ENTER(H5C_mask, ID_H5C_create, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ switch(type)
+ {
+ case H5_TEMPLATE:
+ {
+ file_create_temp_t *new_create_temp; /* new template object to create */
+
+ if((new_create_temp=HDmalloc(sizeof(file_create_temp_t)))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ if((ret_value=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)new_create_temp))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+ } /* end case/block */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+ } /* end switch */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_create, ret_value);
+} /* end H5C_create() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5C_release
+ PURPOSE
+ Release access to a template object.
+ USAGE
+ herr_t H5C_release(oid)
+ hatom_t oid; IN: Template object to release access to
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function releases access to a template object
+--------------------------------------------------------------------------*/
+herr_t H5C_release(hatom_t oid)
+{
+ CONSTR(FUNC, "H5C_release"); /* for HERROR */
+ file_create_temp_t *template; /* template to destroy */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5C_mask, ID_H5C_release, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Chuck the object! :-) */
+ if((template=H5Aremove_atom(oid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ HDfree(template);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_release, ret_value);
+} /* end H5C_release() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Cgetparm
+ PURPOSE
+ Get a parameter from a template
+ USAGE
+ herr_t H5Cgetparm(tid, parm, buf)
+ hatom_t tid; IN: Template object to retrieve parameter from
+ file_create_param_t parm; IN: Paramter to retrieve
+ VOIDP buf; OUT: Pointer to buffer to store parameter in
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function retrieves the value of a specific parameter from a
+ template
+--------------------------------------------------------------------------*/
+herr_t H5Cgetparm(hatom_t tid, file_create_param_t parm, VOIDP buf)
+{
+ CONSTR(FUNC, "H5Cgetparm"); /* for HERROR */
+ file_create_temp_t *template; /* template to query */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5C_mask, ID_H5Cgetparm, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(buf==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* Get a pointer the template to query */
+ if((template=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ switch(parm)
+ {
+ case H5_USERBLOCK_SIZE:
+ *(uintn *)buf=template->userblock_size;
+ break;
+
+ case H5_OFFSET_SIZE:
+ *(uintn *)buf=template->offset_size;
+ break;
+
+ case H5_LENGTH_SIZE:
+ *(uintn *)buf=template->length_size;
+ break;
+
+ case H5_BTREE_SIZE:
+ *(uintn *)buf=template->btree_page_size;
+ break;
+
+ case H5_BOOTBLOCK_VER:
+ *(uint8 *)buf=template->bootblock_ver;
+ break;
+
+ case H5_SMALLOBJECT_VER:
+ *(uint8 *)buf=template->smallobject_ver;
+ break;
+
+ case H5_FREESPACE_VER:
+ *(uint8 *)buf=template->freespace_ver;
+ break;
+
+ case H5_OBJECTDIR_VER:
+ *(uint8 *)buf=template->objectdir_ver;
+ break;
+
+ case H5_SHAREDHEADER_VER:
+ *(uint8 *)buf=template->sharedheader_ver;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+ } /* end switch */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5Cgetparm, ret_value);
+} /* end H5Cgetparm() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Csetparm
+ PURPOSE
+ Set a parameter from a template
+ USAGE
+ herr_t H5Csetparm(tid, parm, buf)
+ hatom_t tid; IN: Template object to store parameter in
+ file_create_param_t parm; IN: Parameter to store
+ VOIDP buf; OUT: Pointer to parameter buffer
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function stores the value of a specific parameter for a template
+--------------------------------------------------------------------------*/
+herr_t H5Csetparm(hatom_t tid, file_create_param_t parm, const VOIDP buf)
+{
+ CONSTR(FUNC, "H5Csetparm"); /* for HERROR */
+ file_create_temp_t *template; /* template to query */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5C_mask, ID_H5Csetparm, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(buf==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* Get a pointer the template to query */
+ if((template=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ switch(parm)
+ {
+ case H5_USERBLOCK_SIZE:
+ template->userblock_size=*(const uintn *)buf;
+ break;
+
+ case H5_OFFSET_SIZE:
+ template->offset_size=*(const uintn *)buf;
+ break;
+
+ case H5_LENGTH_SIZE:
+ template->length_size=*(const uintn *)buf;
+ break;
+
+ case H5_BTREE_SIZE:
+ template->btree_page_size=*(const uintn *)buf;
+ break;
+
+ case H5_BOOTBLOCK_VER:
+ template->bootblock_ver=*(const uint8 *)buf;
+ break;
+
+ case H5_SMALLOBJECT_VER:
+ template->smallobject_ver=*(const uint8 *)buf;
+ break;
+
+ case H5_FREESPACE_VER:
+ template->freespace_ver=*(const uint8 *)buf;
+ break;
+
+ case H5_OBJECTDIR_VER:
+ template->objectdir_ver=*(const uint8 *)buf;
+ break;
+
+ case H5_SHAREDHEADER_VER:
+ template->sharedheader_ver=*(const uint8 *)buf;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+ } /* end switch */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5Csetparm, ret_value);
+} /* end H5Csetparm() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5C_copy
+ PURPOSE
+ Copy a template
+ USAGE
+ hatom_t H5C_copy(tid)
+ hatom_t tid; IN: Template object to copy
+ RETURNS
+ Returns template ID (atom) on success, FAIL on failure
+ DESCRIPTION
+ This function creates a new copy of a template with all the same parameter
+ settings.
+--------------------------------------------------------------------------*/
+hatom_t H5C_copy(hatom_t tid)
+{
+ CONSTR(FUNC, "H5C_copy"); /* for HERROR */
+ file_create_temp_t *template, *new_template; /* template to query */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5C_mask, ID_H5C_copy, H5C_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Get a pointer the template to query */
+ if((template=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Allocate space for the new template */
+ if((new_template=HDmalloc(sizeof(file_create_temp_t)))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+
+ /* Copy over the information from the old template */
+ HDmemcpy(new_template,template,sizeof(file_create_temp_t));
+
+ /* Register the atom for the new template */
+ if((ret_value=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)new_template))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5C_mask, ID_H5C_copy, ret_value);
+} /* end H5C_copy() */
+
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
new file mode 100644
index 0000000..4f7357f
--- /dev/null
+++ b/src/H5Cprivate.h
@@ -0,0 +1,25 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains private information about the H5C module
+ */
+
+#ifndef H5CPRIVATE_H
+#define H5CPRIVATE_H
+
+#include "H5Cproto.h"
+
+#endif /* H5CPRIVATE_H */
+
diff --git a/src/H5Cproto.h b/src/H5Cproto.h
new file mode 100644
index 0000000..0d8f26d
--- /dev/null
+++ b/src/H5Cproto.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5C module
+ */
+
+#ifndef H5CPROTO_H
+#define H5CPROTO_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5C.c */
+hatom_t H5C_create(hatom_t owner_id, hobjtype_t type, const char *name);
+hatom_t H5C_copy(hatom_t tid);
+herr_t H5C_release(hatom_t oid);
+hatom_t H5C_get_default_atom(hobjtype_t type);
+herr_t H5C_init(hatom_t dst_atm, const file_create_temp_t *src);
+herr_t H5Cgetparm(hatom_t tid, file_create_param_t parm, VOIDP buf);
+herr_t H5Csetparm(hatom_t tid, file_create_param_t parm, const VOIDP buf);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5CPROTO_H */
+
diff --git a/src/H5E.c b/src/H5E.c
new file mode 100644
index 0000000..a697f39
--- /dev/null
+++ b/src/H5E.c
@@ -0,0 +1,394 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ hdf5err.c
+ HDF error reporting routines
+
+ EXPORTED ROUTINES
+ H5Enew_err_stack -- Create a new error stack to push values on
+ H5Epush -- Push an error value on an error stack
+
+ LIBRARY-SCOPED ROUTINES
+
+ LOCAL ROUTINES
+ H5E_init_interface -- initialize the H5E interface
+ + */
+
+#define HDF5_ERR_MASTER
+#include "hdf5.h"
+#include "H5Eprivate.h" /* Private error routines */
+#undef HDF5_ERR_MASTER
+
+#include "H5private.h" /* Generic Functions */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*------------------_-- Local function prototypes ----------------------------*/
+static herr_t H5E_init_interface(void);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5E_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5E_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5E_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5E_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5_mask, ID_H5Iinit_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ /* Initialize the atom group for the error stacks */
+ ret_value=H5Ainit_group(H5_ERR,HDF5_ERRSTACK_HASHSIZE,0);
+
+ FUNC_LEAVE(H5_mask, ID_H5E_init_interface, ret_value);
+} /* H5E_init_interface */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5Enew_err_stack -- Create a new error stack
+USAGE
+ int32 H5Enew_err_stack(initial_stack_size);
+ uintn initial_stack_size; IN: Starting size of the error stack
+
+RETURNS
+ The ID of the error stack created on success, FAIL on failure.
+
+DESCRIPTION
+ Dynamically creates a new error stack to push error values onto.
+
+--------------------------------------------------------------------------*/
+int32 H5Enew_err_stack(uintn initial_stack_size)
+{
+ CONSTR(FUNC, "H5Enew_err_stack"); /* For HERROR */
+ H5E_errstack_t *new_stack=NULL; /* Pointer to the new error stack */
+ int32 ret_value = FAIL;
+
+ FUNC_ENTER(H5E_mask, ID_H5Enew_err_stack, H5E_init_interface,FAIL);
+
+ /* Allocate the stack header */
+ if((new_stack=HDmalloc(sizeof(H5E_errstack_t)))==NULL)
+ HGOTO_DONE(FAIL);
+
+ /* Initialize the stack header */
+ new_stack->stack_size=initial_stack_size;
+ new_stack->stack_top=0;
+ if((new_stack->err_stack=HDcalloc(initial_stack_size,sizeof(H5E_error_t)))==NULL)
+ {
+ HDfree(new_stack);
+ HGOTO_DONE(FAIL);
+ } /* end if */
+ new_stack->push=H5E_store; /* Set the default error handler */
+
+ /* Get an atom for the error stack */
+ ret_value=H5Aregister_atom(H5_ERR, new_stack);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5E_mask, ID_H5Enew_err_stack, ret_value);
+} /* H5Enew_err_stack */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5Edelete_err_stack -- Destroy an error stack
+USAGE
+ intn H5Edelete_err_stack(err_stack);
+ int32 err_stack; IN: Error stack to delete
+
+RETURNS
+ SUCCEED/FAIL
+
+DESCRIPTION
+ Destroys an error stack, releasing memory allocated, etc.
+
+--------------------------------------------------------------------------*/
+intn H5Edelete_err_stack(int32 err_stack)
+{
+ CONSTR(FUNC, "H5Edelete_err_stack"); /* For HERROR */
+ H5E_errstack_t *old_stack=NULL; /* Pointer to the new error stack */
+ intn ret_value = SUCCEED;
+
+ FUNC_ENTER(H5E_mask, ID_H5Edelete_err_stack, H5E_init_interface,FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ if (H5Aatom_group(err_stack)!=H5_ERR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Get the error stack to put the error on */
+ if((old_stack=H5Aremove_atom(err_stack))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Clear the error descriptions and reset the stack top */
+ for(; old_stack->stack_top>0; old_stack->stack_top--)
+ {
+ if (old_stack->err_stack[old_stack->stack_top-1].desc)
+ {
+ HDfree(old_stack->err_stack[old_stack->stack_top-1].desc);
+ old_stack->err_stack[old_stack->stack_top-1].desc=NULL;
+ } /* end if */
+ } /* end if */
+
+ HDfree(old_stack->err_stack);
+ HDfree(old_stack);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5E_mask, ID_H5Edelete_err_stack, ret_value);
+} /* H5Edelete_err_stack */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5Eclear -- Clear an error stack for later error entries
+USAGE
+ void H5Eclear(int32 err_hand)
+ int32 err_hand; IN: The ID of the error stack to push the error onto.
+
+RETURNS
+ none
+DESCRIPTION
+ Clear an error stack to allow errors to be pushed onto it.
+
+--------------------------------------------------------------------------*/
+void H5Eclear(int32 err_hand)
+{
+ CONSTR(FUNC, "H5Eclear"); /* For HERROR */
+ H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5E_mask, ID_H5Eclear, H5E_init_interface,FAIL);
+
+ /* Get the error stack for this error handler, initialized earlier in H5Enew_err_stack */
+ if (H5Aatom_group(err_hand)!=H5_ERR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Get the error stack to put the error on */
+ if((err_stack=H5Aatom_object(err_hand))==NULL)
+ HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL);
+
+ /* Clear the error descriptions and reset the stack top */
+ for(; err_stack->stack_top>0; err_stack->stack_top--)
+ {
+ if (err_stack->err_stack[err_stack->stack_top-1].desc)
+ {
+ HDfree(err_stack->err_stack[err_stack->stack_top-1].desc);
+ err_stack->err_stack[err_stack->stack_top-1].desc=NULL;
+ } /* end if */
+ } /* end if */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ PABLO_TRACE_OFF(H5E_mask, ID_H5Eclear); /* ignore ret_value set */
+} /* H5Eclear */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5E_store -- Push an error value on an error stack
+USAGE
+ void H5E_store(hdf_err_code_t err, const char *function_name, const char *file_name, intn line)
+ hdf_err_code_t err; IN: The error code which occurred.
+ const char *function_name; IN: Name of the function the error occurred within.
+ const char *file_name; IN: Name of the file the error occurred within.
+ intn line; IN: Line # in the file the error occurred on.
+
+RETURNS
+ none
+DESCRIPTION
+ Pushes an error onto an error stack for this thread. (This is the default
+ action when errors occur, but can be overridden by user's code)
+
+--------------------------------------------------------------------------*/
+void H5E_store(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line)
+{
+ CONSTR(FUNC, "H5E_store"); /* For HERROR */
+ H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5E_mask, ID_H5E_store, H5E_init_interface,FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5Eclear(errid);
+
+ /* Get the error stack to put the error on */
+ if((err_stack=H5Aatom_object(errid))==NULL)
+ HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL);
+
+ /* Check if we need to expand the stack */
+ if(err_stack->stack_top>=err_stack->stack_size)
+ {
+ H5E_error_t *old_stack=err_stack->err_stack; /* in case realloc fails */
+
+ /* Ask for new stack that's twice as large */
+ if((err_stack->err_stack=HDrealloc(old_stack,2*err_stack->stack_size))==NULL)
+ {
+ err_stack->err_stack=old_stack;
+ HGOTO_DONE(FAIL);
+ } /* end if */
+ err_stack->stack_size *= 2; /* increase the size of the stack */
+ } /* end if */
+
+ /* Push the error onto the error stack */
+ err_stack->err_stack[err_stack->stack_top].maj=maj;
+ err_stack->err_stack[err_stack->stack_top].min=min;
+ HDstrncpy(err_stack->err_stack[err_stack->stack_top].function_name,function_name,MAX_FUNC_NAME_LEN);
+ err_stack->err_stack[err_stack->stack_top].file_name=file_name;
+ err_stack->err_stack[err_stack->stack_top].line=line;
+
+ /* Increment the top of the error stack */
+ err_stack->stack_top++;
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ PABLO_TRACE_OFF(H5E_mask, ID_H5E_store); /* ignore ret_value set */
+} /* H5E_store */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5Epush -- Push an error value on an error stack
+USAGE
+ void H5Epush(hdf_err_code_t err, const char *function_name, const char *file_name, intn line)
+ hdf_err_code_t err; IN: The error code which occurred.
+ const char *function_name; IN: Name of the function the error occurred within.
+ const char *file_name; IN: Name of the file the error occurred within.
+ intn line; IN: Line # in the file the error occurred on.
+
+RETURNS
+ none
+DESCRIPTION
+ Pushes an error onto an error stack for this thread.
+
+--------------------------------------------------------------------------*/
+void H5Epush(hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line)
+{
+ CONSTR(FUNC, "H5Epush"); /* For HERROR */
+ H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5E_mask, ID_H5Epush, H5E_init_interface,FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if (function_name==NULL || file_name==NULL || H5Aatom_group(thrderrid)!=H5_ERR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Get the error stack to put the error on */
+ if((err_stack=H5Aatom_object(thrderrid))==NULL)
+ HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL);
+
+ err_stack->push(thrderrid, maj, min, function_name, file_name, line);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ PABLO_TRACE_OFF(H5E_mask, ID_H5Epush); /* ignore ret_value set */
+} /* H5Epush */
+
+/*--------------------------------------------------------------------------
+NAME
+ H5Eset_push -- Set the function to call when an error value is reported
+USAGE
+ H5E_push_func_t H5Eset_push(H5E_push_func_t func)
+ H5E_push_func_t func; IN: New function to call when an error occurs.
+
+RETURNS
+ The function pointer to the previous error function on success, NULL on
+ failure.
+DESCRIPTION
+ Changes the function which is called for errors on this thread. The thread
+ ID is implicit, ie. this function must be called within each thread whose
+ error function is to be changed.
+
+--------------------------------------------------------------------------*/
+H5E_push_func_t H5Eset_push(H5E_push_func_t func)
+{
+ CONSTR(FUNC, "H5Eset_push"); /* For HERROR */
+ H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
+ H5E_push_func_t ret_value = NULL;
+
+ FUNC_ENTER(H5E_mask, ID_H5Eset_push, H5E_init_interface,NULL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if (func==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL);
+
+ /* Get the error stack to put the error on */
+ if((err_stack=H5Aatom_object(thrderrid))==NULL)
+ HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, NULL);
+
+ ret_value=err_stack->push;
+ err_stack->push=func;
+
+done:
+ if(ret_value == NULL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5E_mask, ID_H5Eset_push, ret_value);
+} /* H5Eset_push */
+
diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h
new file mode 100644
index 0000000..9de9d69
--- /dev/null
+++ b/src/H5Eprivate.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * Header file for error values, etc.
+ */
+
+#ifndef HDF5ERR_H
+#define HDF5ERR_H
+
+#include "H5Eproto.h"
+
+/*
+ ======================================================================
+ Error codes
+
+ NOTE: Remember to update the error_messages[] structure later in this file
+ whenever errors are added/deleted from this list.
+ ======================================================================
+ */
+/*
+ * This section of code is designed to be only accessible to the actual
+ * error-management code.
+ */
+#ifdef HDF5_ERR_MASTER
+
+/*
+ * error_messages is the list of error messages in the system, kept as
+ * error_code-message pairs.
+ */
+
+typedef struct
+ {
+ hdf_maj_err_code_t error_code;
+ const char *str;
+ }
+hdf_maj_error_messages_t;
+
+static const hdf_maj_error_messages_t hdf_maj_error_messages[] =
+{
+ {H5E_NONE_MAJOR, "No error"},
+ {H5E_ARGS, "Invalid arguments to routine"},
+ {H5E_RESOURCE, "Resource unavailable"},
+ {H5E_INTERNAL, "Internal HDF5 error (too specific to document in detail)"},
+ {H5E_FILE, "File Accessability"},
+ {H5E_IO, "Low-level I/O"},
+ {H5E_FUNC, "Function Entry/Exit"},
+ {H5E_ATOM, "Object Atom"},
+};
+
+typedef struct
+ {
+ hdf_min_err_code_t error_code;
+ const char *str;
+ }
+hdf_min_error_messages_t;
+
+static const hdf_min_error_messages_t hdf_min_error_messages[] =
+{
+ {H5E_NONE_MINOR, "No error"},
+ {H5E_UNINITIALIZED, "Information is uninitialized"},
+ {H5E_UNSUPPORTED, "Feature is unsupported"},
+ {H5E_BADTYPE, "Incorrect type found"},
+ {H5E_BADRANGE, "Incorrect range of argument"},
+ {H5E_NOSPACE, "No space available for allocation"},
+ {H5E_FILEEXISTS, "File already exists"},
+ {H5E_FILEOPEN, "File already open"},
+ {H5E_CANTCREATE, "Can't create file"},
+ {H5E_CANTOPEN, "Can't open file"},
+ {H5E_NOTHDF5, "Not an HDF5 format file"},
+ {H5E_BADFILE, "Bad file ID accessed"},
+ {H5E_SEEKERROR, "File seek failed"},
+ {H5E_READERROR, "File read failed"},
+ {H5E_WRITEERROR, "File write failed"},
+ {H5E_CANTINIT, "Can't initialize interface"},
+ {H5E_ALREADYINIT, "Object already initialized"},
+ {H5E_BADATOM, "Can't find atom information"},
+ {H5E_CANTREGISTER, "Can't register new atom"}
+};
+
+/* We use a stack to hold the errors plus we keep track of the function,
+ file and line where the error occurs. */
+
+/* the structure of the error stack element */
+typedef struct error_t
+ {
+ hdf_maj_err_code_t maj; /* Major error number */
+ hdf_min_err_code_t min; /* Minor error number */
+ char function_name[MAX_FUNC_NAME_LEN]; /* function where error occur */
+ const char *file_name; /* file where error occur */
+ intn line; /* line in file where error occurs */
+ char *desc; /* optional supplied description */
+ }
+H5E_error_t;
+
+/* Structure to store error information for a thread */
+typedef struct errstack_t
+ {
+ uintn stack_size; /* Number of elements allocated in the stack */
+ uintn stack_top; /* Offset of the next open stack element */
+ H5E_error_t *err_stack; /* Pointer to the error stack */
+ H5E_push_func_t push; /* Function to call when an error is to be reported */
+ } H5E_errstack_t;
+
+#endif /* HDF5_ERR_MASTER */
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Private functions in H5E.c */
+void H5E_store(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* HDF5ERR_H */
+
diff --git a/src/H5Eproto.h b/src/H5Eproto.h
new file mode 100644
index 0000000..da011bf
--- /dev/null
+++ b/src/H5Eproto.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5E module
+ */
+
+#ifndef H5EPROTO_H
+#define H5EPROTO_H
+
+/* HERROR macro, used to facilitate error reporting. Assumes that
+ there's a variable called FUNC which holds the function name.
+ Assume that func and file are both stored in static space, or at
+ least be not corrupted in the meanwhile. */
+
+#define HERROR(maj, min) H5Epush(maj, min, FUNC, __FILE__, __LINE__)
+
+/* HRETURN_ERROR macro, used to facilitate error reporting. Makes
+ same assumptions as HERROR. IN ADDITION, this macro causes
+ a return from the calling routine */
+
+#define HRETURN_ERROR(maj, min, ret_val) {HERROR(maj, min); return(ret_val);}
+
+/* HGOTO_ERROR macro, used to facilitate error reporting. Makes
+ same assumptions as HERROR. IN ADDITION, this macro causes
+ a jump to the label 'done' which should be in every fucntion
+ Also there is an assumption of a variable 'ret_value' */
+
+#define HGOTO_ERROR(maj, min, ret_val) { HERROR(maj, min); \
+ ret_value = ret_val; goto done; }
+
+/* HGOTO_DONE macro, used to facilitate the new error reporting model.
+ This macro is just a wrapper to set the return value and jump to the 'done'
+ label. Also assumption of a variable 'ret_value' */
+
+#define HGOTO_DONE(ret_val) {ret_value = ret_val; goto done;}
+
+/* H5ECLEAR macro, used to facilitate the new error reporting model.
+ This macro is just a wrapper to clear the error stack with the thread
+ error ID */
+
+#define H5ECLEAR H5Eclear(thrderrid)
+
+/* Declare an enumerated type which holds all the valid major HDF error codes */
+typedef enum
+ {
+ H5E_NONE_MAJOR = 0, /* special zero, no error */
+ H5E_ARGS, /* Invalid arguments to routine */
+ H5E_RESOURCE, /* Resource unavailable */
+ H5E_INTERNAL, /* Internal error (too specific to document in detail) */
+ H5E_FILE, /* File Accessability */
+ H5E_IO, /* Low-level I/O */
+ H5E_FUNC, /* Function Entry/Exit */
+ H5E_ATOM /* Object Atom */
+ }
+hdf_maj_err_code_t;
+
+/* Declare an enumerated type which holds all the valid minor HDF error codes */
+typedef enum
+ {
+ H5E_NONE_MINOR = 0, /* special zero, no error */
+
+ /* Argument errors */
+ H5E_UNINITIALIZED, /* Information is unitialized */
+ H5E_UNSUPPORTED, /* Feature is unsupported */
+ H5E_BADTYPE, /* Incorrect type found */
+ H5E_BADRANGE, /* Incorrect range of argument */
+
+ /* Resource errors */
+ H5E_NOSPACE, /* No space available for allocation */
+
+ /* File accessability errors */
+ H5E_FILEEXISTS, /* File already exists */
+ H5E_FILEOPEN, /* File already open */
+ H5E_CANTCREATE, /* Can't create file */
+ H5E_CANTOPEN, /* Can't open file */
+ H5E_NOTHDF5, /* Not an HDF5 format file */
+ H5E_BADFILE, /* Bad file ID accessed */
+
+ /* Generic low-level file I/O errors */
+ H5E_SEEKERROR, /* File seek failed */
+ H5E_READERROR, /* File read failed */
+ H5E_WRITEERROR, /* File write failed */
+
+ /* Function entry/exit interface errors */
+ H5E_CANTINIT, /* Can't initialize interface */
+ H5E_ALREADYINIT, /* Object already initialized */
+
+ /* Object atom related errors */
+ H5E_BADATOM, /* Can't find atom information */
+ H5E_CANTREGISTER /* Can't register new atom */
+ }
+hdf_min_err_code_t;
+
+/* Function pointer to report errors through */
+typedef void (*H5E_push_func_t)(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line);
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5E.c */
+int32 H5Enew_err_stack(uintn initial_stack_size);
+intn H5Edelete_err_stack(int32 err_hand);
+H5E_push_func_t H5Eset_push(H5E_push_func_t func);
+void H5Epush(hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line);
+void H5Eclear(int32 err_hand);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5EPROTO_H */
+
diff --git a/src/H5F.c b/src/H5F.c
new file mode 100644
index 0000000..d75e09f
--- /dev/null
+++ b/src/H5F.c
@@ -0,0 +1,852 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*
+ FILE
+ hdf5file.c
+ HDF5 file I/O routines
+
+ EXPORTED ROUTINES
+ H5Fcreate -- Create an HDF5 file
+ H5Fclose -- Close an open HDF5 file
+
+ LIBRARY-SCOPED ROUTINES
+
+ LOCAL ROUTINES
+ H5F_init_interface -- initialize the H5F interface
+ */
+
+#define HDF5_FILE_MASTER
+#include "hdf5.h"
+#undef HDF5_FILE_MASTER
+
+/* Packages needed by this file... */
+#include "H5private.h" /*library functions */
+#include "H5ACprivate.h" /*cache */
+#include "H5Gprivate.h" /*symbol tables */
+#include "H5MMprivate.h" /*core memory management */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*--------------------- Local function prototypes ----------------------------*/
+static herr_t H5F_init_interface(void);
+static hdf5_file_t *H5F_new (void);
+static hdf5_file_t *H5F_dest (hdf5_file_t *f);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5F_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5F_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5F_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5F_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5F_mask, ID_H5F_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ /* Initialize the atom group for the file IDs */
+ ret_value=H5Ainit_group(H5_FILE,HDF5_FILEID_HASHSIZE,0);
+
+ FUNC_LEAVE(H5_mask, ID_H5F_init_interface, ret_value);
+} /* H5F_init_interface */
+
+#ifdef LATER
+/*--------------------------------------------------------------------------
+ NAME
+ H5F_encode_length_unusual -- encode an unusual length size
+ USAGE
+ void H5F_encode_length_unusual(f, p, l)
+ const hdf5_file_t *f; IN: pointer to the file record
+ uint8 **p; IN: pointer to buffer pointer to encode length in
+ uint8 *l; IN: pointer to length to encode
+ RETURNS
+ none
+ DESCRIPTION
+ Encode non-standard (i.e. not 2, 4 or 8-byte) lengths in file meta-data.
+--------------------------------------------------------------------------*/
+void H5F_encode_length_unusual(const hdf5_file_t *f, uint8 **p, uint8 *l)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5F_encode_length_unusual");
+#endif /* LATER */
+ intn i=f->file_create_parms.length_size;
+
+/* For non-little-endian platforms, encode each byte in memory backwards */
+#if ((DF_MT&0xFFF0)!=0x4440)
+ for(; i>=0; i--,(*p)++)
+ *(*p)=*(l+i);
+#else /* platform has little-endian integers */
+ for(; i>=0; i--,(*p)++)
+ *(*p)=*l;
+#endif
+
+#ifdef LATER
+done:
+ if(ret_value == FALSE)
+ { /* Error condition cleanup */
+
+ } /* end if */
+#endif /* LATER */
+
+ /* Normal function cleanup */
+
+} /* H5F_encode_length_unusual */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5F_encode_offset_unusual -- encode an unusual offset size
+ USAGE
+ void H5F_encode_offset_unusual(f, p, o)
+ const hdf5_file_t *f; IN: pointer to the file record
+ uint8 **p; IN: pointer to buffer pointer to encode offset in
+ uint8 *o; IN: pointer to offset to encode
+ RETURNS
+ none
+ DESCRIPTION
+ Encode non-standard (i.e. not 2, 4 or 8-byte) offsets in file meta-data.
+--------------------------------------------------------------------------*/
+void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5F_encode_offset_unusual");
+#endif /* LATER */
+ intn i=f->file_create_parms.offset_size;
+
+/* For non-little-endian platforms, encode each byte in memory backwards */
+#if ((DF_MT&0xFFF0)!=0x4440)
+ for(; i>=0; i--,(*p)++)
+ *(*p)=*(o+i);
+#else /* platform has little-endian integers */
+ for(; i>=0; i--,(*p)++)
+ *(*p)=*o;
+#endif
+
+#ifdef LATER
+done:
+ if(ret_value == FALSE)
+ { /* Error condition cleanup */
+
+ } /* end if */
+#endif /* LATER */
+
+ /* Normal function cleanup */
+
+} /* H5F_encode_offset_unusual */
+#endif /* LATER */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5F_compare_filename -- compare file objects for the atom API
+ USAGE
+ intn HPcompare_filename(obj, key)
+ const VOIDP obj; IN: pointer to the file record
+ const VOIDP key; IN: pointer to the name of file
+ RETURNS
+ TRUE if the key matches the obj, FALSE otherwise
+ DESCRIPTION
+ Look inside the file record for the atom API and compare the the
+ filenames.
+--------------------------------------------------------------------------*/
+intn H5F_compare_filename(const VOIDP obj, const VOIDP key)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5F_compare_filename");
+#endif /* LATER */
+
+
+#ifdef LATER
+done:
+ if(ret_value == FALSE)
+ { /* Error condition cleanup */
+
+ } /* end if */
+#endif /* LATER */
+
+ /* Normal function cleanup */
+
+ return(!HDstrcmp(((const hdf5_file_t *)obj)->filename,(const char *)key));
+} /* H5F_compare_filename */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Fget_create_template
+ PURPOSE
+ Get an atom for a copy of the file-creation template for this file
+ USAGE
+ hatom_t H5Fget_create_template(fid)
+ hatom_t fid; IN: File ID
+ RETURNS
+ Returns template ID on success, FAIL on failure
+ DESCRIPTION
+ This function returns an atom with a copy of the template parameters
+ used to create a file.
+--------------------------------------------------------------------------*/
+hatom_t H5Fget_create_template(hatom_t fid)
+{
+ CONSTR(FUNC, "H5Fget_create_template"); /* for HERROR */
+ hdf5_file_t *file=NULL; /* file struct for file to close */
+ hatom_t ret_value = FAIL;
+
+ FUNC_ENTER(H5F_mask, ID_H5Fget_create_template, H5F_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Get the file structure */
+ if((file=H5Aatom_object(fid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Create the template object to return */
+ if((ret_value=H5Mcreate(fid,H5_TEMPLATE,NULL))==FAIL)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTCREATE, FAIL);
+
+ if(H5C_init(ret_value,&(file->file_create_parms))==FAIL)
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5F_mask, ID_H5Fget_create_template, ret_value);
+} /* end H5Fget_create_template() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Fis_hdf5
+ PURPOSE
+ Check the file signature to detect an HDF5 file.
+ USAGE
+ hbool_t H5Fis_hdf5(filename)
+ const char *filename; IN: Name of the file to check
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ This function determines if a file is an HDF5 format file.
+--------------------------------------------------------------------------*/
+hbool_t H5Fis_hdf5(const char *filename)
+{
+ CONSTR(FUNC, "H5Fis_hdf5"); /* for HERROR */
+ hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */
+ uint8 temp_buf[HDF5_FILE_SIGNATURE_LEN]; /* temporary buffer for checking file signature */
+ size_t curr_off=0; /* The current offset to check in the file */
+ size_t file_len=0; /* The length of the file we are checking */
+ hbool_t ret_value = BFALSE;
+
+ FUNC_ENTER(H5F_mask, ID_H5Fis_hdf5, H5F_init_interface, BFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(filename==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, BFAIL);
+
+ /* Open the file */
+ f_handle=H5FI_OPEN(filename,0);
+ if(H5FI_OPENERR(f_handle))
+ HGOTO_ERROR(H5E_FILE, H5E_BADFILE, BFAIL);
+
+ /* Get the length of the file */
+ if(H5FI_SEEKEND(f_handle)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL);
+ file_len=H5FI_TELL(f_handle);
+
+ /* Check the offsets where the file signature is possible */
+ while(curr_off<file_len)
+ {
+ if(H5FI_SEEK(f_handle,curr_off)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL);
+ if(H5FI_READ(f_handle,temp_buf, HDF5_FILE_SIGNATURE_LEN)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL);
+ if(HDmemcmp(temp_buf,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==0)
+ {
+ ret_value=BTRUE;
+ break;
+ } /* end if */
+ if(curr_off==0)
+ curr_off=512;
+ else
+ curr_off*=2;
+ } /* end while */
+ H5FI_CLOSE(f_handle); /* close the file we opened */
+
+done:
+ if(ret_value == BFAIL)
+ { /* Error condition cleanup */
+
+ /* Check if we left a dangling file handle */
+ if(f_handle!=H5FI_INVALID_FILE)
+ H5FI_CLOSE(f_handle); /* close the file we opened */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5F_mask, ID_H5Fis_hdf5, ret_value);
+} /* end H5Fis_hdf5() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_new
+ *
+ * Purpose: Creates a new file object and initializes it. The
+ * H5Fopen and H5Fcreate functions then fill in various
+ * fields.
+ *
+ * Return: Success: Ptr to a new file struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hdf5_file_t *
+H5F_new (void)
+{
+ hdf5_file_t *f = H5MM_xcalloc (1, sizeof(hdf5_file_t));
+
+ /* Create an error stack for errors with this file */
+ f->file_err = H5Enew_err_stack(HDF5_FILE_ERRSTACK);
+
+ /* Create a cache */
+ H5AC_new (f);
+
+ /* Create a root symbol slot */
+ f->root_sym = H5MM_xcalloc (1, sizeof (H5G_entry_t));
+ f->root_sym->type = H5G_NOTHING_CACHED;
+
+ return f;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_dest
+ *
+ * Purpose: Destroys a file structure. This function does not flush
+ * the cache or anything else; it only frees memory associated
+ * with the file struct.
+ *
+ * Return: Success: NULL
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hdf5_file_t *
+H5F_dest (hdf5_file_t *f)
+{
+ if (f) {
+ H5AC_dest (f);
+ if(f->file_err!=0) H5Edelete_err_stack (f->file_err);
+ f->dir = H5MM_xfree (f->dir);
+ f->filename = H5MM_xfree (f->filename);
+ H5MM_xfree (f);
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Fcreate
+ PURPOSE
+ Create a new HDF5 file.
+ USAGE
+ int32 H5Fcreate(filename, flags)
+ const char *filename; IN: Name of the file to create
+ uintn flags; IN: Flags to indicate various options.
+ hatom_t create_temp; IN: File-creation template
+ hatom_t access_temp; IN: File-access template
+ RETURNS
+ Returns file ID on success, FAIL on failure
+ DESCRIPTION
+ This is the primary function for creating HDF5 files . The flags
+ parameter determines whether an existing file will be overwritten or not.
+ All newly created files are opened for both reading and writing. All flags
+ may be combined with the "||" (logical OR operator) to change the behavior
+ of the file open call.
+ The flags currently defined:
+ H5ACC_OVERWRITE - Truncate file, if it already exists. The file will
+ be truncated, erasing all data previously stored in the file.
+ The more complex behaviors of a file's creation and access are
+ controlled through the file-creation and file-access templates.
+
+ MODIFICATIONS:
+ Robb Matzke, 18 Jul 1997
+ File struct creation and destruction is through H5F_new() H5F_dest().
+ Writing the root symbol table entry is done with H5G_encode().
+--------------------------------------------------------------------------*/
+hatom_t H5Fcreate(const char *filename, uintn flags, hatom_t create_temp, hatom_t access_temp)
+{
+ CONSTR(FUNC, "H5Fcreate"); /* for HERROR */
+ hdf5_file_t *new_file=NULL; /* file struct for new file */
+ hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */
+ const file_create_temp_t *f_create_parms; /* pointer to the parameters to use when creating the file */
+ uint8 temp_buf[2048], *p; /* temporary buffer for encoding header */
+ intn file_exists=0; /* flag to indicate that file exists already */
+ hatom_t ret_value = FAIL;
+
+ FUNC_ENTER(H5F_mask, ID_H5Fcreate, H5F_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(filename==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* See if this file is already open */
+ if(H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename)!=NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL);
+
+ /* Check if the file already exists */
+ f_handle=H5FI_OPEN(filename,0);
+ if(!H5FI_OPENERR(f_handle))
+ {
+ file_exists=1; /* set the flag to indicate that the file already exists */
+ H5FI_CLOSE(f_handle); /* close the file we opened */
+ f_handle=H5FI_INVALID_FILE;
+ } /* end if */
+
+ /* throw an error if the file exists and we aren't allowed to overwrite it */
+ if((flags&H5ACC_OVERWRITE)==0 && file_exists)
+ HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, FAIL);
+
+ /* OK to create/overwrite the file */
+ f_handle=H5FI_CREATE(filename);
+ if(H5FI_OPENERR(f_handle))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL);
+
+ /* Create the file node */
+ if (NULL==(new_file=H5F_new()))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+
+ /* Set the non-zero elements of the file structure */
+ new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */
+ new_file->filename=HDstrdup(filename); /* make a copy of the filename */
+ new_file->acc_perm=H5ACC_WRITE; /* all new files we create have write permission */
+ new_file->file_handle=f_handle; /* keep the file handle we just opened */
+ new_file->ref_count=1; /* only 1 fid handed out so far */
+ new_file->consist_flags=0x03; /* Set file-consistency flags: write-access and "file is consistent" */
+ new_file->smallobj_off=0; /* Set the offset of the small-object heap */
+ new_file->freespace_off=0; /* Set the offset of the free-space info */
+ /* Get the file-creation template & record it */
+ if(create_temp<=0)
+ create_temp=H5C_get_default_atom(H5_TEMPLATE);
+ if((f_create_parms=H5Aatom_object(create_temp))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t));
+
+#ifdef LATER
+ /* Get the file-access template & record it */
+ if(access_temp<=0)
+ access_temp=H5CPget_default_atom(H5_TEMPLATE);
+ if((f_access_parms=H5Aatom_object(access_temp))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t));
+#endif /* LATER */
+
+ /* Create the basic skeleton of the file */
+
+ /* Seek to the correct offset to write out the file signature & boot-block */
+ if(new_file->file_create_parms.userblock_size>0)
+ if(H5FI_SEEK(new_file->file_handle,new_file->file_create_parms.userblock_size)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL);
+
+ /* Write out the file-signature */
+ if(H5FI_WRITE(new_file->file_handle,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+
+ /* Encode the boot block */
+ p=temp_buf;
+ *p++=f_create_parms->bootblock_ver; /* Encode Boot-block version # */
+ *p++=f_create_parms->smallobject_ver; /* Encode Small-Object Heap version # */
+ *p++=f_create_parms->freespace_ver; /* Encode Free-Space Info version # */
+ *p++=f_create_parms->objectdir_ver; /* Encode Object Directory Format version # */
+ *p++=f_create_parms->sharedheader_ver; /* Encode Shared-Header Info version # */
+ *p++=(uint8)f_create_parms->offset_size; /* Encode the number of bytes for the offset */
+ *p++=(uint8)f_create_parms->length_size; /* Encode the number of bytes for the length */
+ *p++=0; /* Encode the reserved byte :-) */
+ UINT32ENCODE(p,f_create_parms->btree_page_size); /* Encode the B-Tree page size */
+ UINT32ENCODE(p,new_file->consist_flags); /* Encode File-Consistancy flags */
+ H5F_encode_offset(new_file,p,new_file->smallobj_off); /* Encode offset of global small-object heap */
+ H5F_encode_offset(new_file,p,new_file->freespace_off); /* Encode offset of global free-space heap */
+ /* Predict the header length and encode it: */
+ H5F_encode_length(new_file,p,(p-temp_buf)+f_create_parms->length_size+H5F_symbol_table_size(new_file)); /* Encode length of boot-block */
+
+ /* Encode the (bogus) symbol-table entry */
+ if (H5G_encode (new_file, &p, new_file->root_sym)<0) {
+ HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL);
+ }
+
+ /* Write out the boot block */
+ if(H5FI_WRITE(new_file->file_handle,temp_buf,(size_t)(p-temp_buf))==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+ new_file->logical_len = p - temp_buf;
+
+
+ /* Get an atom for the file */
+ if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ /* Check if we left a dangling file handle */
+ if(f_handle!=H5FI_INVALID_FILE)
+ H5FI_CLOSE(f_handle); /* close the file we opened */
+
+ /* Check if we left a dangling file struct */
+ if (new_file) H5F_dest (new_file);
+ }
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5F_mask, ID_H5Fcreate, ret_value);
+} /* end H5Fcreate() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Fopen
+ PURPOSE
+ Open an existing HDF5 file.
+ USAGE
+ hatom_t H5Fopen(filename, flags, access_temp)
+ const char *filename; IN: Name of the file to create
+ uintn flags; IN: Flags to indicate various options.
+ hatom_t access_temp; IN: File-access template
+ RETURNS
+ Returns file ID on success, FAIL on failure
+ DESCRIPTION
+ This is the primary function for accessing existing HDF5 files. The
+ flags parameter determines whether writing to an existing file will be allowed
+ or not. All flags may be combined with the "||" (logical OR operator) to
+ change the behavior of the file open call.
+ The flags currently defined:
+ H5ACC_WRITE - Allow writing to the file.
+ The more complex behaviors of a file's access are controlled through
+ the file-access template.
+
+ MODIFICATIONS:
+ Robb Matzke, 18 Jul 1997
+ File struct creation and destruction is through H5F_new() H5F_dest().
+ Reading the root symbol table entry is done with H5G_decode().
+--------------------------------------------------------------------------*/
+hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp)
+{
+ CONSTR(FUNC, "H5Fopen"); /* for HERROR */
+ hdf5_file_t *new_file=NULL; /* file struct for new file */
+ hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */
+ hatom_t create_temp; /* file-creation template ID */
+ const file_create_temp_t *f_create_parms; /* pointer to the parameters to use when creating the file */
+ uint8 temp_buf[2048], *p; /* temporary buffer for encoding header */
+ size_t curr_off=0; /* The current offset to check in the file */
+ size_t file_len=0; /* The length of the file we are checking */
+ hatom_t ret_value = FAIL;
+
+ FUNC_ENTER(H5F_mask, ID_H5Fopen, H5F_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(filename==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* See if this file is already open */
+ new_file=H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename);
+
+ /* If the file is already open, check the access permissions and go ahead with it */
+ if(new_file!=NULL && new_file->acc_perm==flags)
+ {
+ /* Get an atom for the file */
+ new_file->ref_count++; /* increment the reference count for the file */
+ if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+ HGOTO_DONE(ret_value);
+ } /* end if */
+
+ /*
+ * If the file exists but has different permissions or if it's a new file,
+ * start a new file handle for it, etc.
+ */
+ if(H5Fis_hdf5(filename)==BFALSE)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL);
+
+ /* Check if the file already exists */
+ f_handle=H5FI_OPEN(filename,flags);
+ if(H5FI_OPENERR(f_handle))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPEN, FAIL);
+
+ /* Create the file node */
+ if (NULL==(new_file=H5F_new()))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+
+ /* Set the non-zero elements of the file structure */
+ new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */
+ new_file->filename=HDstrdup(filename); /* make a copy of the filename */
+ new_file->acc_perm=flags; /* set the access permissions */
+ new_file->file_handle=f_handle; /* keep the file handle we just opened */
+ new_file->ref_count=1; /* only 1 fid handed out so far */
+ create_temp=H5C_get_default_atom(H5_TEMPLATE);
+ if((f_create_parms=H5Aatom_object(create_temp))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t));
+
+#ifdef LATER
+ if(access_temp<=0)
+ access_temp=H5CPget_default_atom(H5_TEMPLATE);
+ if((f_access_parms=H5Aatom_object(access_temp))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t));
+#endif /* LATER */
+
+ /* Read the basic skeleton of the file */
+
+ /* Seek to the correct offset to read in the file signature & boot-block */
+ /* Get the length of the file */
+ if(H5FI_SEEKEND(new_file->file_handle)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL);
+ file_len=H5FI_TELL(new_file->file_handle);
+
+ /* Check the offsets where the file signature is possible */
+ while(curr_off<file_len)
+ {
+ if(H5FI_SEEK(new_file->file_handle,curr_off)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL);
+ if(H5FI_READ(new_file->file_handle,temp_buf, HDF5_FILE_SIGNATURE_LEN)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL);
+ if(HDmemcmp(temp_buf,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==0)
+ {
+ new_file->file_create_parms.userblock_size=curr_off;
+ break;
+ } /* end if */
+ if(curr_off==0)
+ curr_off=512;
+ else
+ curr_off*=2;
+ } /* end while */
+ if(curr_off>file_len)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL);
+
+ /* Read in the fixed-size part of the boot-block */
+ if(H5FI_READ(new_file->file_handle,temp_buf,16)==FAIL)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+
+ /* Decode the boot block */
+ p=temp_buf;
+ new_file->file_create_parms.bootblock_ver=*p++; /* Decode Boot-block version # */
+ new_file->file_create_parms.smallobject_ver=*p++; /* Decode Small-Object Heap version # */
+ new_file->file_create_parms.freespace_ver=*p++; /* Decode Free-Space Info version # */
+ new_file->file_create_parms.objectdir_ver=*p++; /* Decode Object Directory Format version # */
+ new_file->file_create_parms.sharedheader_ver=*p++; /* Decode Shared-Header Info version # */
+ new_file->file_create_parms.offset_size=*p++; /* Decode the number of bytes for the offset */
+ new_file->file_create_parms.length_size=*p++; /* Decode the number of bytes for the length */
+ p++; /* Decode the reserved byte :-) */
+ UINT32DECODE(p,new_file->file_create_parms.btree_page_size); /* Decode the B-Tree page size */
+ UINT32DECODE(p,new_file->consist_flags); /* Decode File-Consistancy flags */
+ H5F_decode_offset(new_file,p,new_file->smallobj_off); /* Decode offset of global small-object heap */
+ H5F_decode_offset(new_file,p,new_file->freespace_off); /* Decode offset of global free-space heap */
+ H5F_decode_length(new_file,p,new_file->logical_len); /* Decode logical length of file */
+
+ /* Decode the root symbol table entry */
+ if (H5G_decode (new_file, &p, new_file->root_sym)<0) {
+ HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL);
+ }
+
+ /* Get an atom for the file */
+ if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ /* Check if we left a dangling file handle */
+ if(f_handle!=H5FI_INVALID_FILE)
+ H5FI_CLOSE(f_handle); /* close the file we opened */
+
+ /* Check if we left a dangling file struct */
+ if(new_file) HDfree(new_file);
+ }
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5F_mask, ID_H5Fopen, ret_value);
+} /* end H5Fopen() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Fclose
+ PURPOSE
+ Close an open HDF5 file.
+ USAGE
+ int32 H5Fclose(fid)
+ int32 fid; IN: File ID of file to close
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function terminates access to an HDF5 file. If this is the last
+ file ID open for a file and if access IDs are still in use, this function
+ will fail.
+
+ MODIFICATIONS:
+ Robb Matzke, 18 Jul 1997
+ File struct destruction is through H5F_dest().
+--------------------------------------------------------------------------*/
+herr_t H5Fclose(hatom_t fid)
+{
+ CONSTR(FUNC, "H5Fclose"); /* for HERROR */
+ hdf5_file_t *file=NULL; /* file struct for file to close */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5F_mask, ID_H5Fclose, H5F_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(H5Aatom_group(fid)!=H5_FILE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Get the file handle to close */
+ if((file=H5Aatom_object(fid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Decrement the ref. count and recycle the file structure */
+ if((--file->ref_count)==0)
+ {
+ H5AC_flush (file, NULL, 0, TRUE);
+ if(file->file_handle!=H5FI_INVALID_FILE) {
+ H5FI_CLOSE(file->file_handle);
+ }
+ H5F_dest (file);
+ if(H5Aremove_atom(fid)==NULL) {
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ }
+ } /* end if */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ FUNC_LEAVE(H5F_mask, ID_H5Fclose, ret_value);
+} /* end H5Fclose() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_read
+ *
+ * Purpose: Reads some data from a file/server/etc into a buffer.
+ * The data is contiguous.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_read (hdf5_file_t *f, off_t addr, size_t size, void *buf)
+{
+ CONSTR(FUNC, "H5F_block_read"); /* for HERROR */
+
+ PABLO_TRACE_ON(H5F_mask, ID_H5F_block_read);
+
+ if (0==size) return 0;
+ addr += f->file_create_parms.userblock_size;
+
+ if (H5FI_SEEK (f->file_handle, addr)<0)
+ HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL);
+ if (H5FI_READ (f->file_handle, buf, size)<0)
+ HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL);
+ PABLO_TRACE_OFF(H5F_mask, ID_H5F_block_read);
+ return SUCCEED;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_write
+ *
+ * Purpose: Writes some data from memory to a file/server/etc. The
+ * data is contiguous.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_write (hdf5_file_t *f, off_t addr, size_t size, void *buf)
+{
+ CONSTR(FUNC, "H5F_block_write"); /* for HERROR */
+
+ PABLO_TRACE_ON(H5F_mask, ID_H5F_block_read);
+
+ if (0==size) return 0;
+ addr += f->file_create_parms.userblock_size;
+
+ if (H5FI_SEEK (f->file_handle, addr)<0)
+ HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL);
+ if (H5FI_WRITE (f->file_handle, buf, size)<0)
+ HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL);
+ PABLO_TRACE_OFF(H5F_mask, ID_H5F_block_write);
+ return SUCCEED;
+}
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
new file mode 100644
index 0000000..2151b29
--- /dev/null
+++ b/src/H5Fprivate.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains macros & information for file access
+ */
+
+#ifndef HDF5FILE_H
+#define HDF5FILE_H
+
+#include "H5Fproto.h" /* Include Public Definitions */
+
+ /*****************************************/
+ /*** This is the top level header file ***/
+ /*** and shouldn't depend on any other ***/
+ /*** packages! ***/
+ /*****************************************/
+
+
+
+#define SIZEOF_OFFSET(F) ((F)->file_create_parms.offset_size)
+#define SIZEOF_SIZE(F) ((F)->file_create_parms.length_size)
+
+/* Size of the default error stack for file IDs */
+#define HDF5_FILE_ERRSTACK 16
+
+/* Define the structure to store the file information for HDF5 files */
+typedef struct {
+ char *dir; /* Directory the file is located within */
+ char *filename; /* Filename of file */
+ uintn acc_perm; /* Access Permissions for file */
+ hdf_file_t file_handle; /* File handle for actual I/O */
+ int32 file_err; /* Error stack ID for this file */
+ uintn ref_count; /* Reference count for number of times file is opened */
+ uint32 consist_flags; /* File Consistency Flags */
+ size_t smallobj_off; /* Offset of small-object heap within the file */
+ size_t freespace_off; /* Offset of free-space info within the file */
+ size_t logical_len; /* Logical length of file */
+ struct H5AC_cache_t *cache; /* The object cache */
+ file_create_temp_t file_create_parms; /* File-creation template parameters */
+#ifdef LATER
+ file_access_temp_t file_access_parms; /* File-access template parameters */
+#endif /* LATER */
+ struct H5G_entry_t *root_sym; /* Extra for the root symbol in the file */
+ } hdf5_file_t;
+
+/* Define a macro to ease calculation of the symbol-table entry size */
+#define H5F_symbol_table_size(f) (4+ /* "Symbol-type" bytes */ \
+ f->file_create_parms.offset_size+ /* Offset bytes */ \
+ f->file_create_parms.length_size+ /* Length bytes */ \
+ 4+ /* Name offset in local heap */ \
+ 24) /* "Scratch" space */ \
+
+#ifdef NOT_YET
+#define H5F_encode_offset(f,p,o) (f->file_create_parms.offset_size==4 ? UINT32ENCODE(p,o) \
+ : f->file_create_parms.offset_size==8 ? UINT64ENCODE(p,o) \
+ : f->file_create_parms.offset_size==2 ? UINT16ENCODE(p,o) \
+ : H5FPencode_unusual_offset(f,&(p),(uint8 *)&(o)))
+#else /* NOT_YET */
+#define H5F_encode_offset(f,p,o) switch(f->file_create_parms.offset_size) { case 4: UINT32ENCODE(p,o); break;\
+ case 8: UINT64ENCODE(p,o); break;\
+ case 2: UINT16ENCODE(p,o); break;}
+#endif /* NOT_YET */
+#define H5F_decode_offset(f,p,o) switch(f->file_create_parms.offset_size) { case 4: UINT32DECODE(p,o); break;\
+ case 8: UINT64DECODE(p,o); break;\
+ case 2: UINT16DECODE(p,o); break;}
+
+#ifdef NOT_YET
+#define H5F_encode_length(f,p,l) (f->file_create_parms.length_size==4 ? UINT32ENCODE(p,l) \
+ : f->file_create_parms.length_size==8 ? UINT64ENCODE(p,l) \
+ : f->file_create_parms.length_size==2 ? UINT16ENCODE(p,l) : H5FPencode_unusual_length(f,&(p),(uint8 *)&(l)))
+#else /* NOT_YET */
+#define H5F_encode_length(f,p,l) switch(f->file_create_parms.length_size) { case 4: UINT32ENCODE(p,l); break;\
+ case 8: UINT64ENCODE(p,l); break;\
+ case 2: UINT16ENCODE(p,l); break;}
+#endif /* NOT_YET */
+
+#define H5F_decode_length(f,p,l) switch(f->file_create_parms.length_size) { case 4: UINT32DECODE(p,l); break;\
+ case 8: UINT64DECODE(p,l); break;\
+ case 2: UINT16DECODE(p,l); break;}
+
+/* Private functions, not part of the publicly documented API */
+void H5F_encode_length_unusual(const hdf5_file_t *f, uint8 **p, uint8 *l);
+void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o);
+intn H5F_compare_filename(const VOIDP obj, const VOIDP key);
+herr_t H5F_block_read (hdf5_file_t *f, off_t addr, size_t size, void *buf);
+herr_t H5F_block_write (hdf5_file_t *f, off_t addr, size_t size, void *buf);
+
+#endif /* HDF5FILE_H */
+
diff --git a/src/H5Fproto.h b/src/H5Fproto.h
new file mode 100644
index 0000000..0600179
--- /dev/null
+++ b/src/H5Fproto.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5F module
+ */
+
+#ifndef H5FPROTO_H
+#define H5FPROTO_H
+
+/* file access codes */
+#define H5ACC_WRITE 0x0001 /* User in H5Fopen to open a file with write access */
+#define H5ACC_OVERWRITE 0x0002 /* User in H5Fcreate truncate an existing file */
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5F.c */
+hbool_t H5Fis_hdf5(const char *filename);
+hatom_t H5Fcreate(const char *filename, uintn flags, hatom_t create_template, hatom_t access_template);
+hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_template);
+herr_t H5Fclose(hatom_t fid);
+hatom_t H5Fget_create_template(hatom_t fid);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5FPROTO_H */
+
diff --git a/src/H5G.c b/src/H5G.c
new file mode 100644
index 0000000..fafecac
--- /dev/null
+++ b/src/H5G.c
@@ -0,0 +1,196 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5G.c
+ * Jul 18 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose:
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+
+#include "hdf5.h"
+
+/* Packages needed by this file... */
+#include "H5Gprivate.h"
+
+/* PRIVATE PROTOTYPES */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_decode_vec
+ *
+ * Purpose: Same as H5G_decode() except it does it for an array of
+ * symbol table entries.
+ *
+ * Return: Success: 0, with *pp pointing to the first byte
+ * after the last symbol.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+{
+ intn i;
+
+ for (i=0; i<n; i++) {
+ if (H5G_decode (f, pp, ent+i)<0) return -1;
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_decode
+ *
+ * Purpose: Decodes a symbol table entry pointed to by `*pp'.
+ *
+ * Return: Success: 0 with *pp pointing to the first byte
+ * following the symbol table entry.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
+{
+ uint8 *p_ret = *pp;
+
+ H5F_decode_offset (f, *pp, ent->name_off);
+ H5F_decode_offset (f, *pp, ent->header);
+ UINT32DECODE (*pp, ent->type);
+
+ switch (ent->type) {
+ case H5G_NOTHING_CACHED:
+ break;
+
+ case H5G_CACHED_SDATA:
+ UINT32DECODE (*pp, ent->cache.sdata.nt);
+ UINT32DECODE (*pp, ent->cache.sdata.ndim);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[0]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[1]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[2]);
+ UINT32DECODE (*pp, ent->cache.sdata.dim[3]);
+ break;
+
+ case H5G_CACHED_SYMTAB:
+ UINT32DECODE (*pp, ent->cache.symtab.btree);
+ UINT32DECODE (*pp, ent->cache.symtab.heap);
+ break;
+
+ default:
+ abort();
+ }
+
+ *pp = p_ret + 2*SIZEOF_OFFSET(f) + 4 + 24;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_encode_vec
+ *
+ * Purpose: Same as H5G_encode() except it does it for an array of
+ * symbol table entries.
+ *
+ * Return: Success: 0, with *pp pointing to the first byte
+ * after the last symbol.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n)
+{
+ intn i;
+
+ for (i=0; i<n; i++) {
+ if (H5G_encode (f, pp, ent+i)<0) return -1;
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_encode
+ *
+ * Purpose: Encodes the specified symbol table entry into the buffer
+ * pointed to by *pp.
+ *
+ * Return: Success: 0, with *pp pointing to the first byte
+ * after the symbol table entry.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 18 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent)
+{
+ uint8 *p_ret = *pp;
+
+ H5F_encode_offset (f, *pp, ent->name_off);
+ H5F_encode_offset (f, *pp, ent->header);
+ UINT32ENCODE (*pp, ent->type);
+
+ switch (ent->type) {
+ case H5G_NOTHING_CACHED:
+ break;
+
+ case H5G_CACHED_SDATA:
+ UINT32ENCODE (*pp, ent->cache.sdata.nt);
+ UINT32ENCODE (*pp, ent->cache.sdata.ndim);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[0]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[1]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[2]);
+ UINT32ENCODE (*pp, ent->cache.sdata.dim[3]);
+ break;
+
+ case H5G_CACHED_SYMTAB:
+ UINT32ENCODE (*pp, ent->cache.symtab.btree);
+ UINT32ENCODE (*pp, ent->cache.symtab.heap);
+ break;
+
+ default:
+ abort();
+ }
+
+ *pp = p_ret + 2*SIZEOF_OFFSET(f) + 4 + 24;
+ return 0;
+}
+
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
new file mode 100644
index 0000000..733e637
--- /dev/null
+++ b/src/H5Gnode.c
@@ -0,0 +1,661 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: snode.c
+ * Jun 26 1997
+ * Robb Matzke <matzke@llnl.gov>
+ *
+ * Purpose: Functions for handling symbol table nodes. A
+ * symbol table node is a small collection of symbol
+ * table entries. A B-tree usually points to the
+ * symbol table nodes for any given symbol table.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "hdf5.h"
+
+/* Packages needed by this file... */
+#include "H5ACprivate.h" /*cache */
+#include "H5Bprivate.h" /*B-link trees */
+#include "H5Gprivate.h" /*me */
+#include "H5Hprivate.h" /*heap */
+#include "H5MFprivate.h" /*file memory management */
+#include "H5MMprivate.h" /*core memory management */
+
+/* PRIVATE PROTOTYPES */
+static void H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key);
+static void H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key);
+static size_t H5G_node_size (hdf5_file_t *f);
+static off_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
+static herr_t H5G_node_flush (hdf5_file_t *f, hbool_t destroy, off_t addr,
+ H5G_node_t *sym);
+static H5G_node_t *H5G_node_load (hdf5_file_t *f, off_t addr,
+ const void *_data);
+static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata,
+ void *_rt_key);
+static herr_t H5G_node_found (hdf5_file_t *f, off_t addr, void *_lt_key,
+ void *_udata, void *_rt_key);
+static off_t H5G_node_insert (hdf5_file_t *f, off_t addr, intn *anchor,
+ void *_lt_key, hbool_t *lt_key_changed,
+ void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed);
+static herr_t H5G_node_list (hdf5_file_t *f, off_t addr, void *_udata);
+static size_t H5G_node_sizeof_rkey (hdf5_file_t *f);
+
+/* H5G inherits cache-like properties from H5AC */
+static const H5AC_class_t H5AC_SNODE[1] = {{
+ (void*(*)(hdf5_file_t*,off_t,const void*))H5G_node_load,
+ (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5G_node_flush,
+}};
+
+/* H5G inherits B-tree like properties from H5B */
+static const H5B_class_t H5B_SNODE[1] = {{
+ 0, /*id */
+ 64, /*k */
+ sizeof (H5G_node_key_t), /*sizeof_nkey */
+ H5G_node_sizeof_rkey, /*get_sizeof_rkey */
+ H5G_node_new, /*new */
+ H5G_node_cmp, /*cmp */
+ H5G_node_found, /*found */
+ H5G_node_insert, /*insert */
+ H5G_node_list, /*list */
+ H5G_node_decode_key, /*decode */
+ H5G_node_encode_key, /*encode */
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_sizeof_rkey
+ *
+ * Purpose: Returns the size of a raw B-link tree key for the specified
+ * file.
+ *
+ * Return: Success: Size of the key.
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 14 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5G_node_sizeof_rkey (hdf5_file_t *f)
+{
+ return SIZEOF_OFFSET(f);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_decode_key
+ *
+ * Purpose: Decodes a raw key into a native key.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 8 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key)
+{
+ H5G_node_key_t *key = (H5G_node_key_t *)_key;
+
+ H5F_decode_offset (f, raw, key->offset);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_encode_key
+ *
+ * Purpose: Encodes a native key into a raw key.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 8 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key)
+{
+ H5G_node_key_t *key = (H5G_node_key_t *)_key;
+
+ H5F_encode_offset (f, raw, key->offset);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_size
+ *
+ * Purpose: Returns the total size of a symbol table node.
+ *
+ * Return: Success: Total size of the node in bytes.
+ *
+ * Failure: Never fails.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5G_node_size (hdf5_file_t *f)
+{
+ return H5G_HDR_SIZE(f) + (2*H5G_NODE_K) * (2*SIZEOF_OFFSET(f));
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_new
+ *
+ * Purpose: Creates a new empty symbol table. This function is called
+ * by the B-tree insert function for an empty tree. It is
+ * also called internally to split a symbol node with
+ * LT_KEY and RT_KEY null pointers.
+ *
+ * Return: Success: Address of symbol table node.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static off_t
+H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
+{
+ H5G_node_key_t *lt_key = (H5G_node_key_t*)_lt_key;
+ H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key;
+ H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t));
+ size_t size = H5G_node_size (f);
+ off_t addr = H5MF_alloc (f, size);
+
+ sym->dirty = 1;
+ sym->entry = H5MM_xcalloc (2 * H5G_NODE_K, sizeof(H5G_entry_t));
+ H5AC_set (f, H5AC_SNODE, addr, sym);
+
+ /*
+ * The left and right symbols in an empty tree are both the
+ * empty string stored at offset zero by the symtab.c functions. This
+ * allows the comparison functions to work correctly without knowing
+ * that there are no symbols.
+ */
+ if (lt_key) lt_key->offset = 0;
+ if (rt_key) rt_key->offset = 0;
+ return addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_flush
+ *
+ * Purpose: Flush a symbol table node to disk.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5G_node_t *sym)
+{
+ uint8 *buf=NULL, *p=NULL;
+ size_t size;
+
+ if (sym->dirty) {
+ size = H5G_node_size (f);
+ buf = p = H5MM_xmalloc (size);
+
+ /* magic number */
+ HDmemcpy (p, H5G_NODE_MAGIC, 4);
+ p += 4;
+
+ /* version number */
+ *p++ = H5G_NODE_VERS;
+
+ /* reserved */
+ *p++ = 0;
+
+ /* number of symbols */
+ UINT16ENCODE (p, sym->nsyms);
+
+ /* entries */
+ H5G_encode_vec (f, &p, sym->entry, sym->nsyms);
+
+
+ H5F_block_write (f, addr, p-buf, buf);
+ buf = H5MM_xfree (buf);
+ }
+
+ if (destroy) {
+ sym->entry = H5MM_xfree (sym->entry);
+ H5MM_xfree (sym);
+ }
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_load
+ *
+ * Purpose: Loads a symbol table from the file.
+ *
+ * Return: Success: Ptr to the new table.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5G_node_t *
+H5G_node_load (hdf5_file_t *f, off_t addr, const void *_udata)
+{
+ H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t));
+ size_t size = H5G_node_size (f);
+ uint8 *buf = H5MM_xmalloc (size);
+ uint8 *p = buf;
+
+
+ sym->entry = H5MM_xcalloc (2*H5G_NODE_K, sizeof(H5G_entry_t));
+ H5F_block_read (f, addr, size, buf);
+
+ /* magic */
+ if (HDmemcmp (p, H5G_NODE_MAGIC, 4)) goto error;
+ p += 4;
+
+ /* version */
+ if (H5G_NODE_VERS!=*p++) goto error;
+
+ /* reserved */
+ p++;
+
+ /* number of symbols */
+ UINT16DECODE (p, sym->nsyms);
+
+ /* entries */
+ H5G_decode_vec (f, &p, sym->entry, sym->nsyms);
+
+ H5MM_xfree (buf);
+ return sym;
+
+error:
+ H5MM_xfree (buf);
+ H5MM_xfree (sym);
+ return NULL;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_cmp
+ *
+ * Purpose: Compares two keys from a B-tree node (LEFT and RIGHT)
+ * against another key (not necessarily the same type)
+ * pointed to by UDATA.
+ *
+ * Return: Success: negative if the UDATA key is less than
+ * or equal to the LEFT key.
+ *
+ * positive if the UDATA key is greater
+ * than the RIGHT key.
+ *
+ * zero if the UDATA key falls between
+ * the LEFT key (exclusive) and the
+ * RIGHT key (inclusive).
+ *
+ * Failure: Never fails
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static intn
+H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key)
+{
+ H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
+ H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key;
+ H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
+ const char *s;
+
+ /* left side */
+ s = H5H_peek (f, udata->heap, lt_key->offset);
+ if (HDstrcmp (udata->name, s)<=0) return -1;
+
+ /* right side */
+ s = H5H_peek (f, udata->heap, rt_key->offset);
+ if (HDstrcmp (udata->name, s)>0) return 1;
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_found
+ *
+ * Purpose: The B-tree search engine has found the symbol table node
+ * which contains the requested symbol if the symbol exists.
+ * This function should examine that node for the symbol and
+ * return information about the symbol through the UDATA
+ * structure which contains the symbol name on function
+ * entry.
+ *
+ * Return: Success: 0 if found and data returned through the
+ * UDATA pointer.
+ *
+ * Failure: -1 if not found.
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 23 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_found (hdf5_file_t *f, off_t addr, void *_lt_key, void *_udata,
+ void *_rt_key)
+{
+ H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
+ H5G_node_t *sn;
+ intn lt=0, idx=0, rt, cmp=1;
+ const char *s;
+
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ if (!sn) return -1;
+ rt = sn->nsyms;
+
+ /*
+ * Binary search.
+ */
+ while (lt<rt && cmp) {
+ idx = (lt + rt) / 2;
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ s = H5H_peek (f, udata->heap, sn->entry[idx].name_off);
+ cmp = HDstrcmp (udata->name, s);
+
+ if (cmp<0) {
+ rt = idx;
+ } else {
+ lt = idx+1;
+ }
+ }
+ if (cmp) return -1;
+
+ udata->entry = sn->entry[idx];
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_insert
+ *
+ * Purpose: The B-tree insertion engine has found the symbol table node
+ * which should receive the new symbol/address pair. This
+ * function adds it to that node unless it already existed.
+ *
+ * If the node has no room for the symbol then the node is
+ * split into two nodes. The original node contains the
+ * low values and the new node contains the high values.
+ * The new symbol table entry is added to either node as
+ * appropriate. When a split occurs, this function will
+ * write the maximum key of the low node to the MID buffer
+ * and return the address of the new node.
+ *
+ * If the new key is larger than RIGHT then update RIGHT
+ * with the new key.
+ *
+ * Return: Success: Address of new node if the node was
+ * split. MID has been initialized with
+ * the high key of the left node, RIGHT
+ * has the high key of the right node.
+ *
+ * Zero if the node didn't split. RIGHT has the
+ * high key of the right node.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 24 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static off_t
+H5G_node_insert (hdf5_file_t *f, off_t addr, intn *anchor,
+ void *_lt_key, hbool_t *lt_key_changed,
+ void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed)
+{
+ H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key;
+ H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key;
+ H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata;
+
+ H5G_node_t *sn;
+ H5G_entry_t ent[2*H5G_NODE_K];
+ off_t new_node=0, offset;
+ const char *s;
+ intn idx=-1, nsyms, cmp=1;
+ intn lt=0, rt; /*binary search cntrs */
+
+ /*
+ * Symbol tables are always split so the new symbol table node is
+ * to the right of the old one.
+ */
+ *anchor = H5B_ANCHOR_LT;
+ *lt_key_changed = FALSE;
+ *rt_key_changed = FALSE;
+
+ /*
+ * Load the symbol node and buffer the entries so we don't have to
+ * worry about the cached value disappearing.
+ */
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ if (!sn) return -1;
+ HDmemcpy (ent, sn->entry, sn->nsyms * sizeof(H5G_entry_t));
+ rt = nsyms = sn->nsyms;
+ sn = NULL;
+
+ /*
+ * Where does the new symbol get inserted? We use a binary search.
+ */
+ while (lt<rt) {
+ idx = (lt + rt) / 2;
+ s = H5H_peek (f, udata->heap, ent[idx].name_off);
+ if (0==(cmp=HDstrcmp (udata->name, s))) return -1; /*already present*/
+ if (cmp<0) {
+ rt = idx;
+ } else {
+ lt = idx+1;
+ }
+ }
+ idx += cmp>0 ? 1 : 0;
+
+ /*
+ * Add the new name to the heap. The caller will check if the
+ * heap address changed and update the symbol table object header
+ * with the new heap address.
+ */
+ offset = H5H_insert (f, udata->heap, strlen(udata->name)+1, udata->name);
+
+ if (nsyms>=2*H5G_NODE_K) {
+ /*
+ * The node is full. Split it into a left and right
+ * node and return the address of the new right node (the
+ * left node is at the same address as the original node).
+ */
+
+ /* The left node */
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ HDmemset (sn->entry+H5G_NODE_K, 0, H5G_NODE_K*sizeof(H5G_entry_t));
+ sn->nsyms = H5G_NODE_K;
+ sn->dirty += 1;
+
+ if (idx<=H5G_NODE_K) {
+ memmove (sn->entry+idx+1, sn->entry+idx,
+ (H5G_NODE_K-idx) * sizeof(H5G_entry_t));
+ sn->entry[idx] = udata->entry;
+ sn->entry[idx].name_off = offset;
+ sn->nsyms += 1;
+ }
+
+ /* The middle key */
+ md_key->offset = sn->entry[sn->nsyms-1].name_off;
+
+ /* The right node */
+ new_node = H5G_node_new (f, NULL, NULL, NULL);
+ sn = H5AC_find (f, H5AC_SNODE, new_node, NULL);
+ HDmemcpy (sn->entry, ent+H5G_NODE_K,
+ H5G_NODE_K*sizeof(H5G_entry_t));
+ sn->nsyms = H5G_NODE_K;
+ sn->dirty += 1;
+
+ if (idx>H5G_NODE_K) {
+ idx -= H5G_NODE_K;
+ HDmemmove (sn->entry+idx+1, sn->entry+idx,
+ (H5G_NODE_K-idx) * sizeof (H5G_entry_t));
+ sn->entry[idx] = udata->entry;
+ sn->entry[idx].name_off = offset;
+ sn->nsyms += 1;
+
+ if (idx+1==sn->nsyms) {
+ rt_key->offset = offset;
+ *rt_key_changed = TRUE;
+ }
+ }
+
+ } else {
+ /*
+ * Add the new symbol to the node.
+ */
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ sn->dirty += 1;
+ HDmemmove (sn->entry+idx+1, sn->entry+idx,
+ (sn->nsyms-idx) * sizeof (H5G_entry_t));
+ sn->nsyms += 1;
+ sn->entry[idx] = udata->entry;
+ sn->entry[idx].name_off = offset;
+
+ if (idx+1==sn->nsyms) {
+ rt_key->offset = offset;
+ *rt_key_changed = TRUE;
+ }
+ }
+
+ return new_node;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_list
+ *
+ * Purpose: This function gets called during a directory list operation.
+ * It should fill in data in the UDATA struct.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jun 24 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_list (hdf5_file_t *f, off_t addr, void *_udata)
+{
+ H5G_node_list_t *udata = (H5G_node_list_t *)_udata;
+ H5G_entry_t *ent;
+ intn i, nsyms;
+ const char *s;
+ H5G_node_t *sn;
+
+ /*
+ * Read the symbol table and save the entry info. We save it
+ * in a separate buffer if names are requested because the name
+ * lookup may invalidate the symbol table.
+ */
+ sn = H5AC_find (f, H5AC_SNODE, addr, NULL);
+ if (!sn) return -1;
+ nsyms = sn->nsyms;
+ if (udata->name) {
+ ent = H5MM_xmalloc (nsyms * sizeof(H5G_entry_t));
+ HDmemcpy (ent, sn->entry, nsyms*sizeof(H5G_entry_t));
+ sn = NULL;
+ } else {
+ ent = sn->entry;
+ }
+
+ /*
+ * Gather the info.
+ */
+ if (udata->name || udata->entry) {
+ for (i=0; i<nsyms && udata->nused<udata->nentries; i++) {
+ if (udata->name) {
+ s = H5H_peek (f, udata->heap, ent[i].name_off);
+ udata->name[udata->nused] = H5MM_xstrdup (s);
+ }
+ if (udata->entry) {
+ udata->entry[udata->nused] = ent[i];
+ }
+ udata->nused += 1;
+ }
+ } else {
+ udata->nused += sn->nsyms;
+ }
+
+ if (!sn) H5MM_xfree (ent);
+ return 0;
+}
+
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
new file mode 100644
index 0000000..3316771
--- /dev/null
+++ b/src/H5Gprivate.h
@@ -0,0 +1,125 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Gprivate.h
+ * Jul 11 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Private stuff for the H5G package (symbol tables).
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Gprivate_H
+#define _H5Gprivate_H
+
+#include "H5Gproto.h" /*include public declarations */
+
+#include "H5Fprivate.h" /*include packages needed by this header*/
+
+#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
+#define H5G_NODE_VERS 1 /*symbol table node version number */
+#define H5G_NODE_K 64 /*min degree. max degree is twice this */
+#define H5G_HDR_SIZE(F) 8
+
+/*
+ * Various types of object header information can be cached in a symbol
+ * table entry (it's normal home is the object header to which the entry
+ * points). This datatype determines what (if anything) is cached in the
+ * symbol table entry.
+ */
+typedef enum H5G_type_t {
+ H5G_NOTHING_CACHED =0, /*nothing is cached */
+ H5G_CACHED_SDATA =1, /*simple dataset, `sdata' */
+ H5G_CACHED_SYMTAB =2 /*symbol table, `symtab' */
+} H5G_type_t;
+
+/*
+ * A symbol table entry. The two important fields are `name_off' and
+ * `header'. The remaining fields are used for caching information that
+ * also appears in the object header to which this symbol table entry
+ * points.
+ */
+typedef struct H5G_entry_t {
+ off_t name_off; /*offset of name within name heap */
+ off_t header; /*file address of object header */
+ H5G_type_t type; /*type of information cached */
+
+ union {
+ struct {
+ uint32 nt; /*number type */
+ uint32 ndim; /*number of dimensions */
+ uint32 dim[4]; /*dimension sizes */
+ } sdata;
+
+ struct {
+ off_t btree; /*file address of symbol table B-tree */
+ off_t heap; /*file address of symtab name heap */
+ } symtab;
+ } cache; /*cached data from object header */
+} H5G_entry_t;
+
+/*
+ * A symbol table node is a collection of symbol table entries. It can
+ * be thought of as the lowest level of the B-link tree that points to
+ * a collection of symbol table entries that belong to a specific symbol
+ * table or directory.
+ */
+typedef struct H5G_node_t {
+ int dirty; /*has cache been modified? */
+ int nsyms; /*number of symbols */
+ H5G_entry_t *entry; /*symbol table entries */
+} H5G_node_t;
+
+/*
+ * Each key field of the B-link tree that points to symbol table
+ * nodes consists of this structure...
+ */
+typedef struct H5G_node_key_t {
+ off_t offset; /*offset into heap for name */
+} H5G_node_key_t;
+
+/*
+ * Data exchange structure for symbol table nodes. This structure is
+ * passed through the B-link tree layer to the methods for the objects
+ * to which the B-link tree points.
+ */
+typedef struct H5G_node_ud1_t {
+
+ /* downward */
+ char *name; /*points to temporary memory */
+ off_t heap; /*symbol table heap address */
+
+ /* upward */
+ H5G_entry_t entry; /*symbol table entry */
+
+} H5G_node_ud1_t;
+
+typedef struct H5G_node_list_t {
+
+ /* downward */
+ H5G_entry_t *entry; /*array of entries, alloc'd by caller */
+ char **name; /*array of string ptrs, allocd by caller*/
+ intn nentries; /*size of the ADDR and NAME arrays */
+ off_t heap; /*heap address */
+
+ /* upward */
+ intn nused; /*num. symbols processed */
+
+} H5G_node_list_t;
+
+/*
+ * Library prototypes...
+ */
+herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
+herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
+herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent);
+herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n);
+
+
+#endif
+
diff --git a/src/H5Gproto.h b/src/H5Gproto.h
new file mode 100644
index 0000000..5c7a66d
--- /dev/null
+++ b/src/H5Gproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Gproto.h
+ * Jul 11 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Prototypes for the H5G package (symbol tables).
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Gproto_H
+#define _H5Gproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5H.c b/src/H5H.c
new file mode 100644
index 0000000..39ec56b
--- /dev/null
+++ b/src/H5H.c
@@ -0,0 +1,653 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5H.c
+ * Jul 16 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Heap functions.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include "hdf5.h"
+
+#include "H5ACprivate.h" /*cache */
+#include "H5Hprivate.h" /*self */
+#include "H5MFprivate.h" /*file memory management */
+#include "H5MMprivate.h" /*core memory management */
+
+#define H5H_MAGIC "HEAP" /*heap magic number */
+#define H5H_FREE_NULL 1 /*end of free list on disk */
+#define H5H_HDR_SIZE(F) (4+SIZEOF_SIZE(F)+2*SIZEOF_OFFSET(F))
+#define H5H_SIZEOF_FREE(F) (SIZEOF_SIZE(F)+SIZEOF_OFFSET(F))
+
+typedef struct H5H_free_t {
+ off_t offset; /*offset of free block */
+ size_t size; /*size of free block */
+ struct H5H_free_t *prev; /*previous entry in free list */
+ struct H5H_free_t *next; /*next entry in free list */
+} H5H_free_t;
+
+typedef struct H5H_t {
+ intn dirty;
+ off_t addr; /*address of data */
+ size_t disk_alloc; /*data bytes allocated on disk */
+ size_t mem_alloc; /*data bytes allocated in mem */
+ uint8 *chunk; /*the chunk, including header */
+ H5H_free_t *freelist; /*the free list */
+} H5H_t;
+
+static H5H_t *H5H_load (hdf5_file_t *f, off_t addr, const void *udata);
+static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, off_t addr,
+ H5H_t *heap);
+
+/*
+ * H5H inherits cache-like properties from H5AC
+ */
+static const H5AC_class_t H5AC_HEAP[1] = {{
+ (void*(*)(hdf5_file_t*,off_t,const void*))H5H_load,
+ (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5H_flush,
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_new
+ *
+ * Purpose: Creates a new heap data structure on disk and caches it
+ * in memory. SIZE_HINT is a hint for the initial size of the
+ * data area of the heap. If size hint is invalid then a
+ * reasonable (but probably not optimal) size will be chosen.
+ * If the heap ever has to grow, then REALLOC_HINT is the
+ * minimum amount by which the heap will grow.
+ *
+ * Return: Success: File address of new heap.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 16 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+off_t
+H5H_new (hdf5_file_t *f, size_t size_hint)
+{
+ H5H_t *heap = NULL;
+ size_t total_size; /*total heap size on disk */
+ off_t addr; /*heap file address */
+
+ assert (f);
+ size_hint = MAX (0, size_hint);
+ if (size_hint && size_hint<H5H_SIZEOF_FREE(f)) {
+ size_hint = H5H_SIZEOF_FREE(f);
+ }
+
+ /* allocate file version */
+ total_size = H5H_HDR_SIZE(f) + size_hint;
+ if ((addr = H5MF_alloc (f, total_size))<0) return -1;
+
+ /* allocate memory version */
+ heap = H5MM_xcalloc (1, sizeof(H5H_t));
+ heap->addr = addr + H5H_HDR_SIZE(f);
+ heap->disk_alloc = size_hint;
+ heap->mem_alloc = size_hint;
+ heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + size_hint);
+
+ /* free list */
+ if (size_hint) {
+ heap->freelist = H5MM_xmalloc (sizeof(H5H_free_t));
+ heap->freelist->offset = 0;
+ heap->freelist->size = size_hint;
+ heap->freelist->prev = heap->freelist->next = NULL;
+ } else {
+ heap->freelist = NULL;
+ }
+
+ /* add to cache */
+ heap->dirty = 1;
+ H5AC_set (f, H5AC_HEAP, addr, heap);
+
+ return addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_load
+ *
+ * Purpose: Loads a heap from disk.
+ *
+ * Return: Success: Ptr to heap memory data structure.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5H_t *
+H5H_load (hdf5_file_t *f, off_t addr, const void *udata)
+{
+ uint8 hdr[20], *p;
+ H5H_t *heap = H5MM_xcalloc (1, sizeof(H5H_t));
+ H5H_free_t *fl=NULL, *tail=NULL;
+ off_t free_block;
+
+ assert (addr>0);
+ assert (H5H_HDR_SIZE(f) <= sizeof hdr);
+ assert (!udata);
+
+ if (H5F_block_read (f, addr, H5H_HDR_SIZE(f), hdr)<0) goto error;
+ p = hdr;
+
+ /* magic number */
+ if (HDmemcmp (hdr, H5H_MAGIC, 4)) goto error;
+ p += 4;
+
+ /* heap data size */
+ H5F_decode_length (f, p, heap->disk_alloc);
+ heap->mem_alloc = heap->disk_alloc;
+
+ /* free list head */
+ H5F_decode_offset (f, p, free_block);
+ assert (-1==free_block || (free_block>=0 && free_block<heap->disk_alloc));
+
+ /* data */
+ H5F_decode_offset (f, p, heap->addr);
+ heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + heap->mem_alloc);
+ if (heap->disk_alloc &&
+ H5F_block_read (f, heap->addr, heap->disk_alloc,
+ heap->chunk + H5H_HDR_SIZE(f))<0) {
+ goto error;
+ }
+
+ /* free list */
+ while (H5H_FREE_NULL!=free_block) {
+ assert (free_block>=0 && free_block<heap->disk_alloc);
+ fl = H5MM_xmalloc (sizeof (H5H_free_t));
+ fl->offset = free_block;
+ fl->prev = tail;
+ fl->next = NULL;
+ if (tail) tail->next = fl;
+ tail = fl;
+ if (!heap->freelist) heap->freelist = fl;
+
+ p = heap->chunk + H5H_HDR_SIZE(f) + free_block;
+ H5F_decode_offset (f, p, free_block);
+ H5F_decode_length (f, p, fl->size);
+
+ assert (fl->offset + fl->size <= heap->disk_alloc);
+ }
+ return heap;
+
+error:
+ if (heap) {
+ heap->chunk = H5MM_xfree (heap->chunk);
+ H5MM_xfree (heap);
+ }
+ return NULL;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_flush
+ *
+ * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
+ * deletes the heap from memory.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5H_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5H_t *heap)
+{
+ uint8 *p = heap->chunk;
+ H5H_free_t *fl = heap->freelist;
+
+ if (heap->dirty) {
+
+ /*
+ * If the heap grew larger than disk storage then move the
+ * data segment of the heap to a larger contiguous block of
+ * disk storage.
+ */
+ if (heap->mem_alloc > heap->disk_alloc) {
+ H5MF_free (f, heap->addr, heap->disk_alloc);
+ heap->addr = H5MF_alloc (f, heap->mem_alloc);
+ heap->disk_alloc = heap->mem_alloc;
+ }
+
+ /*
+ * Write the header.
+ */
+ HDmemcpy (p, H5H_MAGIC, 4); p += 4;
+ H5F_encode_length (f, p, heap->mem_alloc);
+ H5F_encode_offset (f, p, fl?fl->offset:-1);
+ H5F_encode_offset (f, p, heap->addr);
+
+ /*
+ * Write the free list.
+ */
+ while (fl) {
+ p = heap->chunk + H5H_HDR_SIZE(f) + fl->offset;
+ if (fl->next) {
+ H5F_encode_offset (f, p, fl->next->offset);
+ } else {
+ H5F_encode_offset (f, p, H5H_FREE_NULL);
+ }
+ H5F_encode_length (f, p, fl->size);
+ fl = fl->next;
+ }
+
+ /*
+ * Copy buffer to disk.
+ */
+ if (heap->addr == addr + H5H_HDR_SIZE(f)) {
+ if (H5F_block_write (f, addr, H5H_HDR_SIZE(f)+heap->disk_alloc,
+ heap->chunk)<0) {
+ return -1;
+ }
+ } else {
+ if (H5F_block_write (f, addr, H5H_HDR_SIZE(f), heap->chunk)<0) {
+ return -1;
+ }
+ if (H5F_block_write (f, heap->addr, heap->disk_alloc,
+ heap->chunk + H5H_HDR_SIZE(f))<0) {
+ return -1;
+ }
+ }
+
+ heap->dirty = 0;
+ }
+
+ /*
+ * Should we destroy the memory version?
+ */
+ if (destroy) {
+ heap->chunk = H5MM_xfree (heap->chunk);
+ while (heap->freelist) {
+ fl = heap->freelist;
+ heap->freelist = fl->next;
+ H5MM_xfree (fl);
+ }
+ H5MM_xfree (heap);
+ }
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_read
+ *
+ * Purpose: Reads some object (or part of an object) from the heap
+ * whose address is ADDR in file F. OFFSET is the byte offset
+ * from the beginning of the heap at which to begin reading
+ * and SIZE is the number of bytes to read.
+ *
+ * If BUF is the null pointer then a buffer is allocated by
+ * this function.
+ *
+ * Attempting to read past the end of an object may cause this
+ * function to fail.
+ *
+ * Return: Success: BUF (or the allocated buffer)
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 16 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5H_read (hdf5_file_t *f, off_t addr, off_t offset, size_t size, void *buf)
+{
+ H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL);
+
+ assert (offset>=0 && offset<heap->mem_alloc);
+ assert (offset+size<=heap->mem_alloc);
+
+ if (!buf) buf = H5MM_xmalloc (size);
+ HDmemcpy (buf, heap->chunk+H5H_HDR_SIZE(f)+offset, size);
+ return buf;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_peek
+ *
+ * Purpose: This function is a more efficient version of H5H_read.
+ * Instead of copying a heap object into a caller-supplied
+ * buffer, this function returns a pointer directly into the
+ * cache where the heap is being held. Thus, the return pointer
+ * is valid only until the next call to the cache.
+ *
+ * The address of the heap is ADDR in file F. OFFSET is the
+ * byte offset of the object from the beginning of the heap and
+ * may include an offset into the interior of the object.
+ *
+ * Return: Success: Ptr to the object. The pointer points to
+ * a chunk of memory large enough to hold the
+ * object from the specified offset (usually
+ * the beginning of the object) to the end
+ * of the object. Do not attempt to read past
+ * the end of the object.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 16 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+const void *
+H5H_peek (hdf5_file_t *f, off_t addr, off_t offset)
+{
+ H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL);
+
+ assert (offset>=0 && offset<heap->mem_alloc);
+ return heap->chunk+H5H_HDR_SIZE(f)+offset;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_remove_free
+ *
+ * Purpose: Removes free list element FL from the specified heap.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5H_remove_free (H5H_t *heap, H5H_free_t *fl)
+{
+ if (fl->prev) fl->prev->next = fl->next;
+ if (fl->next) fl->next->prev = fl->prev;
+
+ if (!fl->prev) heap->freelist = fl->next;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_insert
+ *
+ * Purpose: Inserts a new item into the heap.
+ *
+ * Return: Success: Offset of new item within heap.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+off_t
+H5H_insert (hdf5_file_t *f, off_t addr, size_t size, const void *buf)
+{
+ H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL);
+ H5H_free_t *fl=NULL, *max_fl=NULL;
+ off_t offset = -1;
+ size_t need_more;
+
+ heap->dirty += 1;
+
+ /*
+ * Look for a free slot large enough for this object and which would
+ * leave zero or at least H5G_SIZEOF_FREE bytes left over.
+ */
+ for (fl=heap->freelist; fl; fl=fl->next) {
+ if (fl->size>size && fl->size-size>=H5H_SIZEOF_FREE(f)) {
+ offset = fl->offset;
+ fl->offset += size;
+ fl->size -= size;
+ break;
+ } else if (fl->size==size) {
+ offset = fl->offset;
+ H5H_remove_free (heap, fl);
+ break;
+ } else if (!max_fl || max_fl->offset < fl->offset) {
+ max_fl = fl;
+ }
+ }
+
+
+ /*
+ * If no free chunk was large enough, then allocate more space and
+ * add it to the free list. If the heap ends with a free chunk, we
+ * can extend that free chunk. Otherwise we'll have to make another
+ * free chunk. If the heap must expand, we double its size.
+ */
+ if (offset<0) {
+
+ need_more = MAX (2*heap->mem_alloc, H5H_SIZEOF_FREE(f));
+ need_more = MAX (need_more, size);
+
+ if (max_fl && max_fl->offset+max_fl->size==heap->mem_alloc) {
+ /*
+ * Increase the size of the maximum free block.
+ */
+ offset = max_fl->offset;
+ max_fl->offset += size;
+ max_fl->size += need_more - size;
+
+ if (max_fl->size < H5H_SIZEOF_FREE(f)) {
+ if (max_fl->size) {
+ fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n",
+ max_fl->size, __LINE__);
+ }
+ H5H_remove_free (heap, max_fl);
+ }
+
+ } else {
+ /*
+ * Create a new free list element large enough that we can
+ * take some space out of it right away.
+ */
+ offset = heap->mem_alloc;
+ if (need_more-size >= H5H_SIZEOF_FREE(f)) {
+ fl = H5MM_xmalloc (sizeof(H5H_free_t));
+ fl->offset = heap->mem_alloc + size;
+ fl->size = need_more - size;
+ fl->prev = NULL;
+ fl->next = heap->freelist;
+ if (heap->freelist) heap->freelist->prev = fl;
+ heap->freelist = fl;
+ } else if (need_more>size) {
+ fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n",
+ need_more-size, __LINE__);
+ }
+ }
+
+ fprintf (stderr, "H5H_insert: resize mem buf from %lu to %lu bytes\n",
+ (unsigned long)(heap->mem_alloc),
+ (unsigned long)(heap->mem_alloc + need_more));
+ heap->mem_alloc += need_more;
+ heap->chunk = H5MM_xrealloc (heap->chunk,
+ H5H_HDR_SIZE(f)+heap->mem_alloc);
+ }
+
+ /*
+ * Copy the data into the heap
+ */
+ HDmemcpy (heap->chunk + H5H_HDR_SIZE(f) + offset, buf, size);
+ return offset;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_write
+ *
+ * Purpose: Writes (overwrites) the object (or part of object) stored
+ * in BUF to the heap at file address ADDR in file F. The
+ * writing begins at byte offset OFFSET from the beginning of
+ * the heap and continues for SIZE bytes.
+ *
+ * Do not partially write an object to create it; the first
+ * write for an object must be for the entire object.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 16 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5H_write (hdf5_file_t *f, off_t addr, off_t offset, size_t size,
+ const void *buf)
+{
+ H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL);
+
+ assert (offset>=0 && offset<heap->mem_alloc);
+ assert (offset+size<=heap->mem_alloc);
+ assert (buf);
+
+ heap->dirty += 1;
+ HDmemcpy (heap->chunk+H5H_HDR_SIZE(f)+offset, buf, size);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5H_remove
+ *
+ * Purpose: Removes an object or part of an object from the heap at
+ * address ADDR of file F. The object (or part) to remove
+ * begins at byte OFFSET from the beginning of the heap and
+ * continues for SIZE bytes.
+ *
+ * Once part of an object is removed, one must not attempt
+ * to access that part. Removing the beginning of an object
+ * results in the object OFFSET increasing by the amount
+ * truncated. Removing the end of an object results in
+ * object truncation. Removing the middle of an object results
+ * in two separate objects, one at the original offset and
+ * one at the first offset past the removed portion.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 16 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5H_remove (hdf5_file_t *f, off_t addr, off_t offset, size_t size)
+{
+ H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL);
+ H5H_free_t *fl = heap->freelist, *fl2 = NULL;
+
+ assert (offset>=0 && offset<heap->mem_alloc);
+ assert (offset+size<=heap->mem_alloc);
+
+ heap->dirty += 1;
+
+ /*
+ * Check if this chunk can be prepended or appended to an already
+ * free chunk. It might also fall between two chunks in such a way
+ * that all three chunks can be combined into one.
+ */
+ while (fl) {
+ if (offset + size == fl->offset) {
+ fl->offset = offset;
+ fl->size += size;
+ fl2 = fl->next;
+ while (fl2) {
+ if (fl2->offset + fl2->size == fl->offset) {
+ fl->offset = fl2->offset;
+ fl->size += fl2->size;
+ H5H_remove_free (heap, fl2);
+ return 0;
+ }
+ }
+ return 0;
+
+ } else if (fl->offset + fl->size == offset) {
+ fl->size += size;
+ fl2 = fl->next;
+ while (fl2) {
+ if (fl->offset + fl->size == fl2->offset) {
+ fl->size += fl2->size;
+ H5H_remove_free (heap, fl2);
+ return 0;
+ }
+ }
+ return 0;
+ }
+
+ fl = fl->next;
+ }
+
+
+ /*
+ * The amount which is being removed must be large enough to
+ * hold the free list data. If not, the freed chunk is forever
+ * lost.
+ */
+ if (size < H5H_SIZEOF_FREE(f)) {
+ fprintf (stderr, "H5H_remove: lost %d bytes\n", size);
+ return 0;
+ }
+
+ /*
+ * Add an entry to the free list.
+ */
+ fl = H5MM_xmalloc (sizeof(H5H_free_t));
+ fl->offset = offset;
+ fl->size = size;
+ fl->prev = NULL;
+ fl->next = heap->freelist;
+ if (heap->freelist) heap->freelist->prev = fl;
+ heap->freelist = fl;
+
+ return 0;
+}
diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h
new file mode 100644
index 0000000..b90d727
--- /dev/null
+++ b/src/H5Hprivate.h
@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Hprivate.h
+ * Jul 16 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose:
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Hprivate_H
+#define _H5Hprivate_H
+
+#include "H5Hproto.h"
+#include "H5Fprivate.h"
+
+/*
+ * Library prototypes...
+ */
+off_t H5H_new (hdf5_file_t *f, size_t size_hint);
+void *H5H_read (hdf5_file_t *f, off_t addr, off_t offset, size_t size,
+ void *buf);
+const void *H5H_peek (hdf5_file_t *f, off_t addr, off_t offset);
+off_t H5H_insert (hdf5_file_t *f, off_t addr, size_t size, const void *buf);
+herr_t H5H_write (hdf5_file_t *f, off_t addr, off_t offset, size_t size,
+ const void *buf);
+herr_t H5H_remove (hdf5_file_t *f, off_t addr, off_t offset, size_t size);
+
+
+#endif
diff --git a/src/H5Hproto.h b/src/H5Hproto.h
new file mode 100644
index 0000000..fcf36f8
--- /dev/null
+++ b/src/H5Hproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5Hproto.h
+ * Jul 16 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose:
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5Hproto_H
+#define _H5Hproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5M.c b/src/H5M.c
new file mode 100644
index 0000000..6e8dc3a
--- /dev/null
+++ b/src/H5M.c
@@ -0,0 +1,257 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ hdf5meta.c
+ HDF5 "Meta-Object" routines
+
+ EXPORTED ROUTINES
+ H5Mcreate -- Create an object
+ H5Mcopy -- Copy an object
+ H5Mrelease -- Release access to an object
+
+ LIBRARY-SCOPED ROUTINES
+
+ LOCAL ROUTINES
+ H5M_init_interface -- initialize the interface
+ + */
+
+#include "hdf5.h"
+#include "H5private.h" /* Generic functions */
+#include "H5Cproto.h" /* Template interface */
+#include "H5Tproto.h" /* Datatype interface */
+#include "H5Mprivate.h" /* Meta-object interface */
+#include "H5Cprivate.h" /* Template interface */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*------------------_-- Local function prototypes ----------------------------*/
+static herr_t H5M_init_interface(void);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5M_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5M_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5M_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5CIinit_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5M_mask, ID_H5M_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ FUNC_LEAVE(H5M_mask, ID_H5M_init_interface, ret_value);
+} /* H5M_init_interface */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5M_find_type
+ PURPOSE
+ Find the type of meta-object to issue a method call on
+ USAGE
+ intn H5M_find_type(type)
+ hobjtype_t type; IN: Type of object to create
+ RETURNS
+ Returns the index of the type in the array of methods on success, or FAIL
+ on failure.
+ DESCRIPTION
+ This function performs a search to find the index of the type of a
+ meta-object in the array of function pointers.
+--------------------------------------------------------------------------*/
+static intn H5M_find_type(hobjtype_t type)
+{
+ CONSTR(FUNC, "H5M_find_type"); /* for HERROR */
+ intn i; /* local counting variable */
+ intn ret_value = FAIL;
+
+ FUNC_ENTER(H5M_mask, ID_H5M_find_type, H5M_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /*
+ * Currently this uses a stright linear search, which can easily be changed
+ * to a binary search when it becomes too slow.
+ */
+ for(i=0; i<(sizeof(meta_func_arr)/sizeof(meta_func_t)); i++)
+ if(type==meta_func_arr[i].type)
+ HGOTO_DONE(i);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5M_mask, ID_H5M_find_type, ret_value);
+} /* end H5M_find_type() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Mcreate
+ PURPOSE
+ Create a new HDF5 object.
+ USAGE
+ hatom_t H5Mcreate(owner_id, type, name)
+ hatom_t owner_id; IN: Group/file which owns this object
+ hobjtype_t type; IN: Type of object to create
+ const char *name; IN: Name of the object
+ RETURNS
+ Returns ID (atom) on success, FAIL on failure
+ DESCRIPTION
+ This function re-directs the object's creation into the appropriate
+ interface, as defined by the function pointers in hdf5fptr.h
+--------------------------------------------------------------------------*/
+hatom_t H5Mcreate(hatom_t owner_id, hobjtype_t type, const char *name)
+{
+ CONSTR(FUNC, "H5Mcreate"); /* for HERROR */
+ intn i; /* local counting variable */
+ hatom_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5M_mask, ID_H5Mcreate, H5M_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(type<=BADGROUP || type>=MAXGROUP)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ i=H5M_find_type(type);
+ if(meta_func_arr[i].create==NULL)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL);
+ ret_value=meta_func_arr[i].create(owner_id,type,name);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5M_mask, ID_H5Mcreate, ret_value);
+} /* end H5Mcreate() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Mcopy
+ PURPOSE
+ Copy an HDF5 object.
+ USAGE
+ hatom_t H5Mcopy(oid)
+ hatom_t oid; IN: Object to copy
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function re-directs the object's copy into the appropriate
+ interface, as defined by the function pointers in hdf5fptr.h
+--------------------------------------------------------------------------*/
+hatom_t H5Mcopy(hatom_t oid)
+{
+ CONSTR(FUNC, "H5Mcopy"); /* for HERROR */
+ group_t group=H5Aatom_group(oid); /* Atom group for incoming object */
+ intn i; /* local counting variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5M_mask, ID_H5Mcopy, H5M_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(group<=BADGROUP || group>=MAXGROUP)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ i=H5M_find_type(group);
+ if(meta_func_arr[i].copy==NULL)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL);
+ ret_value=meta_func_arr[i].copy(oid);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5M_mask, ID_H5Mcopy, ret_value);
+} /* end H5Mcopy() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Mrelease
+ PURPOSE
+ Release access to an HDF5 object.
+ USAGE
+ herr_t H5Mrelease(oid)
+ hatom_t oid; IN: Object to release access to
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function re-directs the object's release into the appropriate
+ interface, as defined by the function pointers in hdf5fptr.h
+--------------------------------------------------------------------------*/
+herr_t H5Mrelease(hatom_t oid)
+{
+ CONSTR(FUNC, "H5Mrelease"); /* for HERROR */
+ group_t group=H5Aatom_group(oid); /* Atom group for incoming object */
+ intn i; /* local counting variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5M_mask, ID_H5Mrelease, H5M_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(group<=BADGROUP || group>=MAXGROUP)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ i=H5M_find_type(group);
+ if(meta_func_arr[i].release==NULL)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL);
+ ret_value=meta_func_arr[i].release(oid);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5M_mask, ID_H5Mrelease, ret_value);
+} /* end H5Mrelease() */
+
diff --git a/src/H5MF.c b/src/H5MF.c
new file mode 100644
index 0000000..0bd1f4f
--- /dev/null
+++ b/src/H5MF.c
@@ -0,0 +1,88 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MF.c
+ * Jul 11 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: File memory management functions.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include "hdf5.h"
+
+#include "H5Fprivate.h"
+#include "H5MFprivate.h"
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_alloc
+ *
+ * Purpose: Allocate at least SIZE bytes of file memory and return
+ * the address where that contiguous chunk of file memory
+ * exists.
+ *
+ * Return: Success: File address of new chunk.
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 11 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+off_t
+H5MF_alloc (hdf5_file_t *f, size_t size)
+{
+ off_t addr;
+
+ assert (f);
+ assert (f->logical_len>0);
+ assert (size>0);
+
+ addr = f->logical_len;
+ f->logical_len += size;
+ return addr;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_free
+ *
+ * Purpose: Frees part of a file, making that part of the file
+ * available for reuse.
+ *
+ * Note: This version of the function doesn't do anything.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_free (hdf5_file_t *f, off_t addr, size_t size)
+{
+ if (addr<=0 || 0==size) return 0;
+
+ fprintf (stderr, "H5MF_free: lost %lu bytes of file storage\n",
+ (unsigned long)size);
+
+ return 0;
+}
+
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
new file mode 100644
index 0000000..a040eda
--- /dev/null
+++ b/src/H5MFprivate.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MFprivate.h
+ * Jul 11 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Private header file for file memory management.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5MFprivate_H
+#define _H5MFprivate_H
+
+#include "H5MFproto.h"
+
+/*
+ * Library prototypes...
+ */
+off_t H5MF_alloc (hdf5_file_t *f, size_t size);
+herr_t H5MF_free (hdf5_file_t *f, off_t addr, size_t size);
+
+#endif
diff --git a/src/H5MFproto.h b/src/H5MFproto.h
new file mode 100644
index 0000000..3b54ecd
--- /dev/null
+++ b/src/H5MFproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MFproto.h
+ * Jul 11 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Prototypes for file memory management.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5MFproto_H
+#define _H5MFproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5MM.c b/src/H5MM.c
new file mode 100644
index 0000000..725085f
--- /dev/null
+++ b/src/H5MM.c
@@ -0,0 +1,175 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MM.c
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Memory management functions.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <assert.h>
+#include "hdf5.h"
+
+#include "H5MMprivate.h"
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_xmalloc
+ *
+ * Purpose: Just like malloc(3) except it aborts on an error.
+ *
+ * Return: Success: Ptr to new memory.
+ *
+ * Failure: abort()
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5MM_xmalloc (size_t size)
+{
+ void *mem = HDmalloc (size);
+ assert (mem);
+ return mem;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_xcalloc
+ *
+ * Purpose: Just like calloc(3) except it aborts on an error.
+ *
+ * Return: Success: Ptr to memory.
+ *
+ * Failure: abort()
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5MM_xcalloc (size_t n, size_t size)
+{
+ void *mem = HDcalloc (n, size);
+ assert (mem);
+ return mem;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_xrealloc
+ *
+ * Purpose: Just like the POSIX version of realloc(3) exept it aborts
+ * on an error. Specifically, the following calls are
+ * equivalent
+ *
+ * H5MM_xrealloc (NULL, size) <==> H5MM_xmalloc (size)
+ * H5MM_xrealloc (ptr, 0) <==> H5MM_xfree (ptr)
+ * H5MM_xrealloc (NULL, 0) <==> NULL
+ *
+ * Return: Success: Ptr to new memory or NULL if the memory
+ * was freed.
+ *
+ * Failure: abort()
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5MM_xrealloc (void *mem, size_t size)
+{
+ if (!mem) {
+ if (0==size) return NULL;
+ mem = H5MM_xmalloc (size);
+
+ } else if (0==size) {
+ mem = H5MM_xfree (mem);
+
+ } else {
+ mem = realloc (mem, size);
+ assert (mem);
+ }
+
+ return mem;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_strdup
+ *
+ * Purpose: Duplicates a string. If the string to be duplicated is the
+ * null pointer, then return null. If the string to be duplicated
+ * is the empty string then return a new empty string.
+ *
+ * Return: Success: Ptr to a new string (or null if no string).
+ *
+ * Failure: abort()
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5MM_xstrdup (const char *s)
+{
+ char *mem;
+
+ if (!s) return NULL;
+ mem = H5MM_xmalloc (strlen (s)+1);
+ strcpy (mem, s);
+ return mem;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MM_xfree
+ *
+ * Purpose: Just like free(3) except null pointers are allowed as
+ * arguments, and the return value (always NULL) can be
+ * assigned to the pointer whose memory was just freed:
+ *
+ * thing = H5MM_xfree (thing);
+ *
+ * Return: Success: NULL
+ *
+ * Failure: never fails
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 10 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5MM_xfree (void *mem)
+{
+ if (mem) HDfree (mem);
+ return NULL;
+}
diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h
new file mode 100644
index 0000000..68dd73b
--- /dev/null
+++ b/src/H5MMprivate.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MMprivate.h
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Private header for memory management.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5MMprivate_H
+#define _H5MMprivate_h
+
+#include "H5MMproto.h"
+
+/*
+ * Library prototypes...
+ */
+void *H5MM_xmalloc (size_t size);
+void *H5MM_xcalloc (size_t n, size_t size);
+void *H5MM_xrealloc (void *mem, size_t size);
+char *H5MM_xstrdup (const char *s);
+void *H5MM_xfree (void *mem);
+
+
+#endif
diff --git a/src/H5MMproto.h b/src/H5MMproto.h
new file mode 100644
index 0000000..e1598f8
--- /dev/null
+++ b/src/H5MMproto.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: H5MMproto.h
+ * Jul 10 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose: Function prototypes for memory management.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5MMproto_H
+#define _H5MMproto_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/H5Mprivate.h b/src/H5Mprivate.h
new file mode 100644
index 0000000..a1fb6cc
--- /dev/null
+++ b/src/H5Mprivate.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains macros & information for meta-objects
+ */
+
+#ifndef H5MPRIVATE_H
+#define H5MPRIVATE_H
+
+#include "H5Mproto.h" /* Include Public Definitions */
+
+/*
+ * A function table record for accessing interfaces which use the "meta"
+ * interface to create/access/release objects.
+ */
+
+typedef struct meta_func_t
+ {
+ hobjtype_t type; /* Object type this interface is for */
+ hatom_t (*create) (hatom_t , hobjtype_t, const char *); /* Object creation function */
+ hatom_t (*access) (hatom_t ); /* Object access function */
+ hatom_t (*copy) (hatom_t ); /* Object copy function */
+ hatom_t (*find_name) (hatom_t , hobjtype_t, const char *); /* Find first object */
+ uint32 (*name_len) (hatom_t ); /* Get length of object name */
+ herr_t (*get_name) (hatom_t , char *); /* Get object name */
+ herr_t (*set_name) (hatom_t , const char *); /* Set object name */
+ hatom_t (*search) (hatom_t , hobjtype_t, const char *); /* Search for list of objects */
+ hatom_t (*index) (hatom_t , hobjtype_t, uint32); /* Get the OID for the n'th object */
+ herr_t (*flush) (hatom_t ); /* Flush the object to disk */
+ herr_t (*delete) (hatom_t ); /* Delete an object from file */
+ hatom_t (*get_parent) (hatom_t ); /* Get the parent object of an object */
+ herr_t (*release) (hatom_t ); /* End access to an object */
+ }
+meta_func_t;
+
+meta_func_t meta_func_arr[]={
+ { /* Template object meta-functions (defined in H5C.c) */
+ H5_TEMPLATE, /* File-Creation Template Type ID */
+ H5C_create, /* File-Creation Template Create */
+ NULL,
+ H5C_copy, /* File-Creation Template Copy */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ H5C_release /* File-Creation Template Release */
+ },
+ { /* Datatype object meta-functions (defined in H5T.c) */
+ H5_DATATYPE, /* Datatype Type ID */
+ H5T_create, /* Datatype object functions */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ H5T_release
+ }
+ };
+
+/* Private functions, not part of the publicly documented API */
+
+#endif /* H5MPRIVATE_H */
+
diff --git a/src/H5Mproto.h b/src/H5Mproto.h
new file mode 100644
index 0000000..3c06412
--- /dev/null
+++ b/src/H5Mproto.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5M module
+ */
+
+#ifndef H5MPROTO_H
+#define H5MPROTO_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5M.c */
+hatom_t H5Mcreate(hatom_t owner_id, hobjtype_t type, const char *name);
+hatom_t H5Mcopy(hatom_t oid);
+herr_t H5Mrelease(hatom_t oid);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5MPROTO_H */
+
diff --git a/src/H5P.c b/src/H5P.c
new file mode 100644
index 0000000..ad24b07
--- /dev/null
+++ b/src/H5P.c
@@ -0,0 +1,216 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ H5P.c
+ HDF5 Data-space routines
+
+ EXPORTED ROUTINES
+ H5Pcreate -- Create a data-space
+ H5Prelease -- Release access to a data-space
+
+ LIBRARY-SCOPED ROUTINES
+
+ LOCAL ROUTINES
+ H5P_init_interface -- initialize the interface
+ + */
+
+#include "hdf5.h"
+#include "H5private.h" /* Generic Functions */
+#include "H5Pprivate.h" /* Data-space functions */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*--------------------------------------------------------------------------
+NAME
+ H5P_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5P_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5P_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5P_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5P_mask, ID_H5P_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ /* Initialize the atom group for the file IDs */
+ ret_value=H5Ainit_group(H5_DATASPACE,HDF5_DATASPACEID_HASHSIZE,H5P_RESERVED_ATOMS);
+
+ FUNC_LEAVE(H5P_mask, ID_H5P_init_interface, ret_value);
+} /* H5P_init_interface */
+
+#ifdef NOT_YET
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tcreate
+ PURPOSE
+ Create a new HDF5 data-type object
+ USAGE
+ hatom_t H5Tcreate(owner_id, type, name)
+ hatom_t owner_id; IN: Group/file which owns this object
+ hobjtype_t type; IN: Type of object to create
+ const char *name; IN: Name of the object
+ RETURNS
+ Returns ID (atom) on success, FAIL on failure
+ DESCRIPTION
+ This function actually creates the data-type object.
+--------------------------------------------------------------------------*/
+hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name)
+{
+ CONSTR(FUNC, "H5T_create"); /* for HERROR */
+ h5_datatype_t *new_dt; /* new data-type object to create */
+ hatom_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tcreate, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Allocate space for the new data-type */
+ if((new_dt=HDmalloc(sizeof(h5_datatype_t)))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+
+ /* Initialize the datatype */
+ new_dt->dt.base=0; /* No Default datatype */
+ new_dt->name=HDstrdup(name); /* Make a copy of the datatype's name */
+ new_dt->ci=NULL; /* Set the complex information to NULL */
+
+ /* Register the new datatype and get an ID for it */
+ if((ret_value=H5Aregister_atom(H5_DATATYPE, (const VOIDP)new_dt))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tcreate, ret_value);
+} /* end H5T_create() */
+#endif /* NOT_YET */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Pnelem
+ PURPOSE
+ Return the number of elements in a dataspace
+ USAGE
+ uintn H5Pnelem(sid)
+ hatom_t sid; IN: Dataspace object to query
+ RETURNS
+ The number of elements in a dataspace on success, UFAIL on failure
+ DESCRIPTION
+ This function determines the number of dataset elements in a
+ dataspace. For example, a simple 3-dimensional dataspace with dimensions
+ 2, 3 and 4 would have 24 elements.
+ UFAIL is returned on an error, otherwise the number of elements is returned.
+--------------------------------------------------------------------------*/
+uintn H5Pnelem(hatom_t sid)
+{
+ CONSTR(FUNC, "H5Pnelem"); /* for HERROR */
+ uintn ret_value = UFAIL;
+
+ FUNC_ENTER(H5P_mask, ID_H5Pnelem, H5P_init_interface, UFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+#ifdef FINISH_THIS
+#else /* FINISH_THIS */
+ if(sid==H5P_SCALAR)
+ ret_value=1;
+#endif /* FINISH_THIS */
+
+done:
+ if(ret_value == UFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5P_mask, ID_H5Pnelem, ret_value);
+} /* end H5Pnelem() */
+
+#ifdef NOT_YET
+/*--------------------------------------------------------------------------
+ NAME
+ H5Trelease
+ PURPOSE
+ Release access to an HDF5 datatype object.
+ USAGE
+ herr_t H5Trelease(oid)
+ hatom_t oid; IN: Object to release access to
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function releases a datatype from active use by a user.
+--------------------------------------------------------------------------*/
+herr_t H5T_release(hatom_t oid)
+{
+ CONSTR(FUNC, "H5T_release"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5Trelease, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Chuck the object! :-) */
+ if((dt=H5Aremove_atom(oid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ if(dt->name!=NULL)
+ HDfree(dt->name);
+ if(dt->ci!=NULL)
+ {
+ } /* end if */
+ HDfree(dt);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Trelease, ret_value);
+} /* end H5T_release() */
+#endif /* NOT_YET */
+
diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h
new file mode 100644
index 0000000..bad8702
--- /dev/null
+++ b/src/H5Pprivate.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains private information about the H5P module
+ */
+
+#ifndef H5PPRIVATE_H
+#define H5PPRIVATE_H
+
+#include "H5Pproto.h"
+#define H5P_RESERVED_ATOMS 1
+
+/*------------------_-- Local function prototypes ----------------------------*/
+static herr_t H5P_init_interface(void);
+
+#endif /* H5PPRIVATE_H */
+
+
diff --git a/src/H5Pproto.h b/src/H5Pproto.h
new file mode 100644
index 0000000..218949a
--- /dev/null
+++ b/src/H5Pproto.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5P module
+ */
+
+#ifndef H5PPROTO_H
+#define H5PPROTO_H
+
+/* Define atomic datatypes */
+#define H5P_SCALAR MAKE_ATOM(H5_DATASPACE,0)
+
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5P.c */
+uintn H5Pnelem(hatom_t dim_id);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5PPROTO_H */
+
diff --git a/src/H5T.c b/src/H5T.c
new file mode 100644
index 0000000..f7bb155
--- /dev/null
+++ b/src/H5T.c
@@ -0,0 +1,662 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*LINTLIBRARY */
+/*+
+ FILE
+ H5T.c
+ HDF5 Data-type routines
+
+ EXPORTED ROUTINES
+ H5Tget_num_fields -- Get the number of fields in a compound datatype
+ H5Tis_field_atomic -- Check if a field is atomic
+ H5Tis_atomic -- Check if a datatype is atomic
+ H5Tset_type -- Set the base type of a user-defined datatype
+ H5Tadd_field -- Add a field to a compound datatype
+ H5Tsize -- Determine the size of a datatype
+
+ LIBRARY-SCOPED ROUTINES
+ H5T_create -- (Meta-Object) Create a datatype
+ H5T_release -- (Meta-Object) Release access to a datatype
+
+ LOCAL ROUTINES
+ H5T_init_interface -- initialize the interface
+ + */
+
+#include "hdf5.h"
+#include "H5private.h" /* Generic Functions */
+#include "H5Tprivate.h" /* Data-type functions */
+
+/*--------------------- Locally scoped variables -----------------------------*/
+
+/* Whether we've installed the library termination function yet for this interface */
+static intn interface_initialize = FALSE;
+
+/*------------------_-- Local function prototypes ----------------------------*/
+static herr_t H5T_init_interface(void);
+
+/*--------------------------------------------------------------------------
+NAME
+ H5T_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5T_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t H5T_init_interface(void)
+{
+#ifdef LATER
+ CONSTR(FUNC, "H5T_init_interface"); /* For HERROR */
+#endif /* LATER */
+ herr_t ret_value = SUCCEED;
+
+ /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */
+ PABLO_TRACE_ON(H5T_mask, ID_H5T_init_interface);
+
+ /* Don't call this routine again... */
+ interface_initialize = TRUE;
+
+ /* Initialize the atom group for the file IDs */
+ ret_value=H5Ainit_group(H5_DATATYPE,HDF5_DATATYPEID_HASHSIZE,H5T_RESERVED_ATOMS);
+
+ FUNC_LEAVE(H5T_mask, ID_H5T_init_interface, ret_value);
+} /* H5T_init_interface */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5T_create
+ PURPOSE
+ Create a new HDF5 data-type object
+ USAGE
+ hatom_t H5T_create(owner_id, type, name)
+ hatom_t owner_id; IN: Group/file which owns this object
+ hobjtype_t type; IN: Type of object to create
+ const char *name; IN: Name of the object
+ RETURNS
+ Returns ID (atom) on success, FAIL on failure
+ DESCRIPTION
+ This function actually creates the data-type object.
+--------------------------------------------------------------------------*/
+hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name)
+{
+ CONSTR(FUNC, "H5T_create"); /* for HERROR */
+ h5_datatype_t *new_dt; /* new data-type object to create */
+ hatom_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5T_create, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Allocate space for the new data-type */
+ if((new_dt=HDmalloc(sizeof(h5_datatype_t)))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+
+ /* Initialize the datatype */
+ new_dt->dt.base=0; /* No Default datatype */
+ new_dt->name=HDstrdup(name); /* Make a copy of the datatype's name */
+ new_dt->ci=NULL; /* Set the complex information to NULL */
+
+ /* Register the new datatype and get an ID for it */
+ if((ret_value=H5Aregister_atom(H5_DATATYPE, (const VOIDP)new_dt))==FAIL)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5T_create, ret_value);
+} /* end H5T_create() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tget_num_fields
+ PURPOSE
+ Return the number of fields in a compound datatype
+ USAGE
+ uint32 H5Tget_num_fields(tid)
+ hatom_t tid; IN: Datatype object to query
+ RETURNS
+ The number of fields in a compound datatype on success, UFAIL on failure
+ DESCRIPTION
+ This function checks the number of fields in a compound user-defined
+ datatype. UFAIL is returned on an error or if an atomic datatype is
+ queried, otherwise the number of fields is returned.
+--------------------------------------------------------------------------*/
+uint32 H5Tget_num_fields(hatom_t tid)
+{
+ CONSTR(FUNC, "H5Tget_num_fields"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ uint32 ret_value = UFAIL;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tget_num_fields, H5T_init_interface, UFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND!=dt->dt.base)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Check if the compound information has been initialized */
+ if(NULL==dt->ci)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL);
+
+ /* Grab the number of fields */
+ ret_value=dt->ci->n;
+
+done:
+ if(ret_value == UFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tget_num_fields, ret_value);
+} /* end H5Tget_num_fields() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tis_field_atomic
+ PURPOSE
+ Check if a field in a compound datatype is atomic
+ USAGE
+ hbool_t H5Tis_field_atomic(tid, fidx)
+ hatom_t tid; IN: Datatype object to query
+ uintn fidx; IN: Index of the field to query
+ RETURNS
+ BFAIL/BTRUE/BFALSE
+ DESCRIPTION
+ This function checks the basic type of field in a user-defined datatype.
+ BTRUE is returned if the datatype is atomic (i.e. not compound), BFALSE is
+ returned if the datatype is compound, BFAIL on error.
+--------------------------------------------------------------------------*/
+hbool_t H5Tis_field_atomic(hatom_t tid, uintn fidx)
+{
+ CONSTR(FUNC, "H5Tis_field_atomic"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ hbool_t ret_value = BTRUE;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tis_field_atomic, H5T_init_interface, BFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND!=dt->dt.base)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Check if the compound information has been initialized */
+ if(NULL==dt->ci)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL);
+
+ /* Check if the field is valid*/
+ if(fidx>=dt->ci->n)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL);
+
+ /* Check the base type of the field */
+ if(H5T_COMPOUND==dt->ci->flist[fidx].dt.base || H5P_SCALAR!=dt->ci->flist[fidx].dim_id)
+ ret_value=BFALSE;
+
+done:
+ if(ret_value == BFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tis_field_atomic, ret_value);
+} /* end H5Tis_field_atomic() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tis_atomic
+ PURPOSE
+ Check if a datatype is atomic
+ USAGE
+ hbool_t H5Tis_atomic(tid)
+ hatom_t tid; IN: Datatype object to query
+ RETURNS
+ BFAIL/BTRUE/BFALSE
+ DESCRIPTION
+ This function checks the basic type of a user-defined datatype. BTRUE
+ is returned if the datatype is atomic (i.e. not compound), BFALSE is
+ returned if the datatype is compound, BFAIL on error.
+--------------------------------------------------------------------------*/
+hbool_t H5Tis_atomic(hatom_t tid)
+{
+ CONSTR(FUNC, "H5Tis_atomic"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ hbool_t ret_value = BTRUE;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tis_atomic, H5T_init_interface, BFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND==dt->dt.base)
+ ret_value=BFALSE;
+
+done:
+ if(ret_value == BFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tis_atomic, ret_value);
+} /* end H5Tis_atomic() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tset_type
+ PURPOSE
+ Set the base type of a user-defined datatype
+ USAGE
+ herr_t H5Tset_type(tid, base, len, arch)
+ hatom_t tid; IN: Datatype object to modify
+ hatom_t base; IN: Base type to set the datatype to
+ uint8 len; IN: Length of the object in bytes
+ uint8 arch; IN: Architecture format to store type with
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function sets the basic type of a user-defined datatype. Each
+ datatype is either an atomic type (i.e. has no further divisions of the
+ type) or is a compound type (like a C structure). If the datatype is set
+ to a compound type, the 'len' argument is not used.
+--------------------------------------------------------------------------*/
+herr_t H5Tset_type(hatom_t tid,hatom_t base,uint8 len,uint8 arch)
+{
+ CONSTR(FUNC, "H5Tset_type"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tset_type, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+ if(base<H5T_CHAR || base>H5T_COMPOUND)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL);
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ if(dt->dt.base!=0)
+ HGOTO_ERROR(H5E_FUNC, H5E_ALREADYINIT, FAIL);
+
+ /* Set the basic datatype information */
+ dt->dt.base=base;
+ dt->dt.len=len;
+ dt->dt.arch=arch;
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tset_type, ret_value);
+} /* end H5Tset_type() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tadd_field
+ PURPOSE
+ Add a field to a compound datatype
+ USAGE
+ herr_t H5Tadd_field(tid, name, base, len, arch, space)
+ hatom_t tid; IN: Datatype object to query
+ const char *fidx; IN: Field name
+ hatom_t base; IN: Field's base type, either an atom ID for
+ an existing compound type, or an atomic
+ base type
+ uint8 len; IN: Length of an atomic base type
+ uint8 arch; IN: Architecture format of an atomic base type
+ hatom_t space; IN: The dimensionality of the field to add
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function adds a field to a user-defined compound datatype. The
+ field can either be a base/len/arch triplet or an existing compound type
+ (passed in the base argument). The space parameter is either H5P_SCALAR
+ (to indicate a scalar field) or the atom of a datatype for more complex
+ dimensionality fields.
+--------------------------------------------------------------------------*/
+herr_t H5Tadd_field(hatom_t tid, const char *name, hatom_t base, uint8 len, uint8 arch, hatom_t space)
+{
+ CONSTR(FUNC, "H5Tadd_field"); /* for HERROR */
+ h5_field_info_t *new_field; /* pointer to new field to add */
+ h5_datatype_t *dt; /* data-type object to manipulate */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tadd_field, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND!=dt->dt.base)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Check if the compound information has been initialized */
+ if(NULL==dt->ci)
+ {
+ if(NULL==(dt->ci=HDmalloc(sizeof(h5_compound_info_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ dt->ci->n=0; /* Set the number of fields to 0 */
+ dt->ci->mem_size=0; /* Set the size of the structure */
+ dt->ci->disk_size=0; /* Set the size of the structure */
+ dt->ci->flist=NULL; /* No field information yet */
+ } /* end if */
+
+ if(NULL==(new_field=HDrealloc(dt->ci->flist,(dt->ci->n+1)*sizeof(h5_field_info_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL);
+ dt->ci->n++; /* increment the number of fields */
+ dt->ci->flist=new_field; /* save the pointer to the increased array of fields */
+ new_field=&dt->ci->flist[dt->ci->n-1]; /* get a "convenience" pointer to the new field */
+
+ new_field->name=HDstrdup(name); /* copy the name */
+ new_field->name_off=0; /* name isn't stored yet */
+ new_field->struct_off=dt->ci->disk_size; /* Set the offset of the field on disk */
+ new_field->dim_id=H5Mcopy(space); /* Make a copy of the dimension space for the field */
+ if((H5Ais_reserved(base)==BTRUE) && base!=H5T_COMPOUND) /* Check if this is a "simple" datatype */
+ {
+ new_field->dt.base=base; /* Make a copy of the datatype for the field */
+ new_field->dt.len=len;
+ new_field->dt.arch=arch;
+ } /* end if */
+ else
+ {
+ new_field->dt.base=H5Mcopy(base); /* Make a copy of the datatype for the field */
+ new_field->dt.len=H5Tsize(base,len,arch,BTRUE);
+ new_field->dt.arch=arch;
+ } /* end else */
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tadd_field, ret_value);
+} /* end H5Tadd_field() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tsize
+ PURPOSE
+ Determine the size of a datatype
+ USAGE
+ uintn H5Tsize(tid, mem_flag)
+ hatom_t tid; IN: Datatype object to query
+ hbool_t mem_flag; IN: Whether the memory or disk size is desired
+ RETURNS
+ The size of the datatype on success or UFAIL on failure.
+ DESCRIPTION
+ Ths function returns the size of the datatype in bytes as it is stored
+ on disk or in memory, depending on the mem_flag. Setting the mem_flag to
+ BTRUE returns the size in memory, BFALSE returns the size on disk.
+--------------------------------------------------------------------------*/
+uintn H5Tsize(hatom_t tid, uint8 len, uint8 arch, hbool_t mem_flag)
+{
+ CONSTR(FUNC, "H5Tsize"); /* for HERROR */
+ uintn ret_value = UFAIL;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tsize, H5T_init_interface, UFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ if((H5Ais_reserved(tid)==BTRUE) && tid!=H5T_COMPOUND) /* Check if this is a "simple" datatype */
+ {
+ switch(tid)
+ {
+ case H5T_CHAR:
+ case H5T_INT:
+ case H5T_FLOAT: /* All three of thes types use the length as the number of bytes */
+ ret_value=len;
+ break;
+
+ case H5T_DATE:
+ ret_value=8; /* Number of characters for ISO 8601 format */
+ break;
+
+ case H5T_TIME:
+ ret_value=6; /* Number of characters for ISO 8601 format */
+ break;
+
+ case H5T_SPTR:
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL);
+ break;
+
+ case H5T_PPTR:
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, UFAIL);
+ } /* end switch */
+ } /* end if */
+ else
+ {
+ if(tid==H5T_COMPOUND)
+ {
+ intn i; /* local counting variable */
+ h5_datatype_t *dt; /* datatype pointer */
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND!=dt->dt.base)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Check if the compound information has been initialized */
+ if(NULL==dt->ci)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL);
+
+ /* Grab the number of fields */
+ for(i=0; i<=dt->ci->n; i++)
+ ret_value+=H5Tsize(dt->ci->flist[i].dt.base, dt->ci->flist[i].dt.len,
+ dt->ci->flist[i].dt.arch,mem_flag)*H5Pnelem(dt->ci->flist[i].dim_id);
+ } /* end if */
+ } /* end else */
+
+done:
+ if(ret_value == UFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tsize, ret_value);
+} /* end H5Tsize() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Tget_fields
+ PURPOSE
+ Determine the size of a datatype
+ USAGE
+ herr_t H5Tget_fields(tid, field_list)
+ hatom_t tid; IN: Datatype object to query
+ hoid_t *field_list; IN: Array to store list of fields
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Ths function returns the size of the datatype in bytes as it is stored
+ on disk or in memory, depending on the mem_flag. Setting the mem_flag to
+ BTRUE returns the size in memory, BFALSE returns the size on disk.
+--------------------------------------------------------------------------*/
+herr_t H5Tget_fields(hatom_t tid, hoid_t *field_list)
+{
+ CONSTR(FUNC, "H5Tsize"); /* for HERROR */
+ uintn ret_value = UFAIL;
+
+ FUNC_ENTER(H5T_mask, ID_H5Tsize, H5T_init_interface, UFAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ if((H5Ais_reserved(tid)==BTRUE) && tid!=H5T_COMPOUND) /* Check if this is a "simple" datatype */
+ {
+ switch(tid)
+ {
+ case H5T_CHAR:
+ case H5T_INT:
+ case H5T_FLOAT: /* All three of thes types use the length as the number of bytes */
+ ret_value=len;
+ break;
+
+ case H5T_DATE:
+ ret_value=8; /* Number of characters for ISO 8601 format */
+ break;
+
+ case H5T_TIME:
+ ret_value=6; /* Number of characters for ISO 8601 format */
+ break;
+
+ case H5T_SPTR:
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL);
+ break;
+
+ case H5T_PPTR:
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, UFAIL);
+ } /* end switch */
+ } /* end if */
+ else
+ {
+ if(tid==H5T_COMPOUND)
+ {
+ intn i; /* local counting variable */
+ h5_datatype_t *dt; /* datatype pointer */
+
+ /* Go get the object */
+ if((dt=H5Aatom_object(tid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+
+ /* Check the base type of the datatype */
+ if(H5T_COMPOUND!=dt->dt.base)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL);
+
+ /* Check if the compound information has been initialized */
+ if(NULL==dt->ci)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL);
+
+ /* Grab the number of fields */
+ for(i=0; i<=dt->ci->n; i++)
+ ret_value+=H5Tsize(dt->ci->flist[i].dt.base, dt->ci->flist[i].dt.len,
+ dt->ci->flist[i].dt.arch,mem_flag)*H5Pnelem(dt->ci->flist[i].dim_id);
+ } /* end if */
+ } /* end else */
+
+done:
+ if(ret_value == UFAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5Tsize, ret_value);
+} /* end H5Tsize() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5T_release
+ PURPOSE
+ Release access to an HDF5 datatype object.
+ USAGE
+ herr_t H5T_release(oid)
+ hatom_t oid; IN: Object to release access to
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function releases a datatype from active use by a user.
+--------------------------------------------------------------------------*/
+herr_t H5T_release(hatom_t oid)
+{
+ CONSTR(FUNC, "H5T_release"); /* for HERROR */
+ h5_datatype_t *dt; /* new data-type object to create */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5T_mask, ID_H5T_release, H5T_init_interface, FAIL);
+
+ /* Clear errors and check args and all the boring stuff. */
+ H5ECLEAR;
+
+ /* Chuck the object! :-) */
+ if((dt=H5Aremove_atom(oid))==NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL);
+ if(dt->name!=NULL)
+ HDfree(dt->name);
+ if(dt->ci!=NULL)
+ {
+ } /* end if */
+ HDfree(dt);
+
+done:
+ if(ret_value == FAIL)
+ { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+
+ FUNC_LEAVE(H5T_mask, ID_H5T_release, ret_value);
+} /* end H5T_release() */
+
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
new file mode 100644
index 0000000..31b2e74
--- /dev/null
+++ b/src/H5Tprivate.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains private information about the H5T module
+ */
+
+#ifndef H5TPRIVATE_H
+#define H5TPRIVATE_H
+
+#include "H5Tproto.h"
+#define H5T_RESERVED_ATOMS 8
+
+/* Structure for storing information about a field in a compound datatype */
+typedef struct {
+ char *name; /* Name of the field */
+ uintn name_off; /* Offset of name in global small-data heap */
+ uintn struct_off; /* Offset of field within structure */
+ h5_atomic_type_t dt; /* Datatype of the field */
+ hatom_t dim_id; /* dimensionality ID of the field */
+ } h5_field_info_t;
+
+/* Structure for storing information about a compound datatype */
+typedef struct {
+ uintn n; /* Number of fields */
+ uintn mem_size; /* Size of the compound structure in memory */
+ uintn disk_size; /* Size of the compound structure on disk */
+ h5_field_info_t *flist; /* List of fields in the compound object */
+ } h5_compound_info_t;
+
+/* Structure for storing information any datatype */
+typedef struct {
+ h5_atomic_type_t dt; /* Atomic type of this object */
+ char *name; /* Name of datatype */
+ h5_compound_info_t *ci; /* Information for compound datatypes */
+ } h5_datatype_t;
+
+#endif /* H5TPRIVATE_H */
+
diff --git a/src/H5Tproto.h b/src/H5Tproto.h
new file mode 100644
index 0000000..5e32b0f
--- /dev/null
+++ b/src/H5Tproto.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5T module
+ */
+
+#ifndef H5TPROTO_H
+#define H5TPROTO_H
+
+/* Define atomic datatypes */
+#define H5T_CHAR MAKE_ATOM(H5_DATATYPE,0)
+#define H5T_INT MAKE_ATOM(H5_DATATYPE,1)
+#define H5T_FLOAT MAKE_ATOM(H5_DATATYPE,2)
+#define H5T_DATE MAKE_ATOM(H5_DATATYPE,3)
+#define H5T_TIME MAKE_ATOM(H5_DATATYPE,4)
+#define H5T_SPTR MAKE_ATOM(H5_DATATYPE,5)
+#define H5T_PPTR MAKE_ATOM(H5_DATATYPE,6)
+#define H5T_COMPOUND MAKE_ATOM(H5_DATATYPE,7)
+
+typedef struct {
+ hatom_t base; /* Basic datatype */
+ uint8 len; /* Length of base-type, in bytes */
+ uint8 arch; /* Architecture of the base-type */
+ } h5_atomic_type_t;
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5T.c */
+hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name);
+uint32 H5Tget_num_fields(hatom_t tid);
+hbool_t H5Tis_field_atomic(hatom_t tid,uintn fidx);
+hbool_t H5Tis_atomic(hatom_t tid);
+herr_t H5Tset_type(hatom_t tid,hatom_t base,uint8 len,uint8 arch);
+uintn H5Tsize(hatom_t tid, uint8 len, uint8 arch, hbool_t mem_flag);
+herr_t H5T_release(hatom_t oid);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5TPROTO_H */
+
diff --git a/src/H5private.h b/src/H5private.h
new file mode 100644
index 0000000..62e7e6c
--- /dev/null
+++ b/src/H5private.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains macros & private information for general HDF5 functions
+ */
+
+#ifndef H5PRIVATE_H
+#define H5PRIVATE_H
+
+#include "H5proto.h" /* Include Public Definitions */
+
+/* Private functions, not part of the publicly documented API */
+herr_t H5_init_library(void);
+void H5_term_library(void);
+herr_t H5_init_thread(void);
+
+#endif /* H5PRIVATE_H */
+
diff --git a/src/H5proto.h b/src/H5proto.h
new file mode 100644
index 0000000..f425c76
--- /dev/null
+++ b/src/H5proto.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains function prototypes for each exported function in the H5 module
+ */
+
+#ifndef H5PROTO_H
+#define H5PROTO_H
+
+#if defined c_plusplus || defined __cplusplus
+extern "C"
+{
+#endif /* c_plusplus || __cplusplus */
+
+/* Functions in H5.c */
+herr_t H5dont_atexit(void);
+herr_t H5version(uintn *majnum, uintn *minnum, uintn *relnum, uintn *patnum);
+
+#if defined c_plusplus || defined __cplusplus
+}
+#endif /* c_plusplus || __cplusplus */
+
+#endif /* H5PROTO_H */
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..0a710ee
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,92 @@
+### Name of target
+TARGET = libhdf5.a
+
+#
+# PART 2: various choices
+#
+
+### -DDEBUG Debugging options on
+DEFS =
+
+#
+# PART 3: hardware dependend
+#
+
+### CC entry: name and arguments for the compiler (also for linking)
+### MACHINE entry: defines used for compiling (not for linking)
+### LIBS: defines used for linking
+MACHINE =
+CC=gcc -O
+LIBS =
+
+################################################
+## no changes required below this line ##
+################################################
+
+CFLAGS = -c $(MACHINE) $(DEFS)
+
+INCL = hdf5.h
+
+OBJ = H5.o H5E.o H5A.o H5F.o H5C.o H5M.o H5AC.o H5B.o H5MM.o H5MF.o H5T.o \
+ H5Gnode.o H5H.o H5G.o H5P.o
+
+$(TARGET): $(OBJ)
+ $(AR) $(ARFLAGS) $(TARGET) $(OBJ)
+ $(RANLIB) $(TARGET)
+
+all test: $(TARGET)
+
+debug: $(OBJ)
+ $(AR) $(ARFLAGS) $(TARGET) $(OBJ)
+ $(RANLIB) $(TARGET)
+
+clean:
+ -rm -f *.o core $(TARGET)
+ -rm -f *.bak
+
+###########################################################################
+
+H5.o: H5.c $(INCL) H5private.h H5proto.h
+ $(CC) $(CFLAGS) H5.c
+
+H5E.o: H5E.c $(INCL) H5Eprivate.h H5Eproto.h
+ $(CC) $(CFLAGS) H5E.c
+
+H5F.o: H5F.c $(INCL) H5Fprivate.h H5Fproto.h
+ $(CC) $(CFLAGS) H5F.c
+
+H5C.o: H5C.c $(INCL) H5Cprivate.h H5Cproto.h
+ $(CC) $(CFLAGS) H5C.c
+
+H5M.o: H5M.c $(INCL) H5Mprivate.h H5Mproto.h
+ $(CC) $(CFLAGS) H5M.c
+
+H5A.o: H5A.c $(INCL) H5Aprivate.h H5Aproto.h
+ $(CC) $(CFLAGS) H5A.c
+
+H5AC.o: H5AC.c $(INCL) H5ACprivate.h H5ACproto.h
+ $(CC) $(CFLAGS) H5AC.c
+
+H5B.o: H5B.c $(INCL) H5Bprivate.h H5Bproto.h
+ $(CC) $(CFLAGS) H5B.c
+
+H5MM.o: H5MM.c $(INCL) H5MMprivate.h H5MMproto.h
+ $(CC) $(CFLAGS) H5MM.c
+
+H5MF.o: H5MF.c $(INCL) H5MFprivate.h H5MFproto.h
+ $(CC) $(CFLAGS) H5MF.c
+
+H5T.o: H5T.c $(INCL) H5Tprivate.h H5Tproto.h
+ $(CC) $(CFLAGS) H5T.c
+
+H5Gnode.o: H5Gnode.c $(INCL) H5Gprivate.h H5Gproto.h
+ $(CC) $(CFLAGS) H5Gnode.c
+
+H5H.o: H5H.c $(INCL) H5Hprivate.h H5Hproto.h
+ $(CC) $(CFLAGS) H5H.c
+
+H5G.o: H5G.c $(INCL) H5Gprivate.h H5Gproto.h
+ $(CC) $(CFLAGS) H5G.c
+
+H5P.o: H5P.c $(INCL) H5Pprivate.h H5Pproto.h
+ $(CC) $(CFLAGS) H5P.c
diff --git a/src/h5oplat.h b/src/h5oplat.h
new file mode 100644
index 0000000..eb8627f
--- /dev/null
+++ b/src/h5oplat.h
@@ -0,0 +1,555 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+#ifndef H5OPLAT_H
+#define H5OPLAT_H
+
+/*
+ * This file contains machine definitions for older architectures which once
+ * were working, but haven't been tested in a long-time. If you wish to use
+ * and test an architecture from this file, move the entire machine's
+ * definition from this file into the hdf5plat.h file and make certain to
+ * delete the entry in this file. -QAK
+ */
+
+/*-------------------------------------------------------------------------
+ * Define options for each platform
+ *-------------------------------------------------------------------------*/
+
+#if (defined(SUN) || defined(sun) || defined(__sun__) || defined(__SUNPRO_C)) & !defined(__i386)
+#ifdef __STDC__
+#define ANSISUN
+#else /* __STDC__ */
+#define KNRSUN
+#endif /* __STDC__ */
+#endif /* SUN || sun */
+
+/*
+ * CPU: Sparc (possibly Motorola 68K?)
+ * OS: Solaris 1.x (?), SunOS 4.x
+ */
+#if defined(KNRSUN)
+
+#if !defined(SUN)
+#define SUN
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+# define BSD
+#define DUMBCC /* because it is. for later use in macros */
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <unistd.h>
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_SUN
+
+/* Define portable variable types */
+typedef void VOID;
+typedef char *VOIDP;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+typedef float float32;
+typedef double float64;
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#ifdef __GNUC__
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+#endif
+
+#endif /* SUN */
+
+/*
+ * CPU: Vax & Alpha (yeah, right! this definition is probably not really that portable! -QAK )
+ * OS: VMS, OpenVMS
+ */
+#if defined(VMS) || defined(vms)
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_VAX
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+#ifdef __alpha
+typedef int int32;
+typedef unsigned int uint32;
+#else
+typedef long int int32;
+typedef unsigned long int uint32;
+#endif
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define DF_CAPFNAMES /* fortran names are in all caps */
+#define _fcdtocp(desc) ((char *) *((char **) &desc[4])) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#define FILELIB POSIXBUFIO
+
+/*
+ Redef a couple of C routine names to avoid conflicts
+ since the VMS link command is case-insensitive
+*/
+#include "dfivms.h"
+
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* VMS */
+
+/*
+ * CPU: HP PA-RISC
+ * OS: ConvexOS
+ */
+#if defined(CONVEX) || defined(CONVEXNATIVE) || defined(__convexc__)
+
+#ifndef CONVEX
+#define CONVEX
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Set machine byte-format */
+#ifdef CONVEXNATIVE
+/* For Convex machines with native format floats */
+#define DF_MT DFMT_CONVEXNATIVE
+#else
+#define DF_MT DFMT_CONVEX
+#endif
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define RIGHT_SHIFT_IS_UNSIGNED
+#define INCLUDES_ARE_ANSI
+#define HAVE_STDC
+
+#endif /* CONVEX */
+
+
+/*
+ * CPU: MIPS
+ * OS: Ultrix
+ */
+#if defined(MIPSEL) || ((defined(mips) || defined(__mips)) && (defined(ultrix) || defined(__ultrix)))
+
+#ifndef MIPSEL
+#define MIPSEL
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+#ifndef __GNUC__
+#define DUMBCC /* because it is. for later use in macros -QAK */
+#endif /* __GNUC__ */
+
+/* Extra include files required for this platform */
+#include <sys/types.h>
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_MIPSEL
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* MIPSEL */
+
+/*
+ * CPU: Motorola 68K
+ * OS: NeXTSTEP
+ */
+#if defined(NEXT) || defined(NeXT)
+
+#ifndef NEXT
+#define NEXT
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#define isascii(c) (isprint(c) || iscntrl(c))
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_NEXT
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+
+#endif /* NEXT */
+
+/*
+ * CPU: Motorola 88K (obscure CISC chip)
+ * OS: ?
+ */
+#if defined(MOTOROLA) || defined(m88k)
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <unistd.h>
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+#ifndef O_RDONLY
+#include <fcntl.h> /* for unbuffered i/o stuff */
+#endif /*O_RDONLY*/
+
+/* Set machine byte-format */
+#define DF_MT DFMT_MOTOROLA
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#define FILELIB POSIXBUFIO
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* MOTOROLA */
+
+
+/*
+ * CPU: ? (Fujitsu VP series)
+ * OS: ? (UNIX)
+ */
+#if defined VP | defined __uxpm__
+
+#ifndef VP
+#define VP
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <memory.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_VP
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#define FILELIB POSIXBUFIO
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* VP */
+
+/*
+ * CPU: Intel I860 (in Paragon system)
+ * OS: ? (UNIX)
+ */
+#if defined I860 | defined i860
+
+#ifndef I860
+#define I860
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <sys/types.h>
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+#include <unistd.h> /* mis-using def. for SEEK_SET, but oh well */
+
+/* Set machine byte-format */
+#define DF_MT DFMT_I860
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#define FILELIB POSIXBUFIO
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* I860 */
+
+#endif /* H5OPLAT_H */
+
diff --git a/src/hdf5.h b/src/hdf5.h
new file mode 100644
index 0000000..6f3c9bc
--- /dev/null
+++ b/src/hdf5.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This is the main HDF5 include file. Put further information in a particular
+ * header file and include that here, don't fill this file with lots of gunk...
+ */
+
+#ifndef HDF5_H
+#define HDF5_H
+
+/* Standard header files needed all the time */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+/* PABLO support files */
+#ifdef HAVE_PABLO
+#define IOTRACE
+#include "IOTrace.h"
+#include "ProcIDs.h"
+#endif /* HAVE_PABLO */
+
+/* Determine the system and set up basic info. */
+#include "hdf5plat.h" /* Platform/OS/CPU detection header file (should be first header included) */
+
+/* Generic Data-Structure/Algorithm include files */
+#include "H5Aproto.h" /* Atom management routines */
+
+/* Major HDF5 Include files */
+#include "hdf5meta.h" /* File Meta-data conversion macros, etc. */
+#include "hdf5fort.h" /* Fortran macros, etc. */
+#include "hdf5port.h" /* Portability macros for easier development */
+#include "hdf5gen.h" /* General global macros */
+#include "hdf5type.h" /* General global typedefs (uses basic types defined in hdf5plat.h) */
+#include "hdf5lims.h" /* Various global limits & version numbers on things */
+#include "H5Fproto.h" /* File access information and macros */
+#include "hdf5pabl.h" /* Pablo porting macros */
+#include "H5Eproto.h" /* Error reporting information */
+#include "H5Cproto.h" /* Template information */
+#include "H5Mproto.h" /* Meta-Object information */
+#include "H5Tproto.h" /* Datatype information */
+#include "H5Pproto.h" /* Dataspace information */
+#include "H5proto.h" /* Generic Interface information */
+#include "hdf5glob.h" /* Global & thread-specific variables */
+
+#endif /* HDF5_H */
+
diff --git a/src/hdf5fort.h b/src/hdf5fort.h
new file mode 100644
index 0000000..21e9ffc
--- /dev/null
+++ b/src/hdf5fort.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains Fortran compatibility/interface macros, etc.
+ */
+
+#ifndef HDF5FORT_H
+#define HDF5FORT_H
+
+/*----------------------------------------------------------------
+** MACRO FCALLKEYW for any special fortran-C stub keyword
+**
+** MacIntosh MPW LS-fortran needs pascal since it can interface
+** best with pascal functions.
+** Microsoft C and Fortran need __fortran for Fortran callable C
+** routines.
+**
+** MACRO FRETVAL for any return value from a fortran-C stub function
+** Replaces the older FCALLKEYW macro.
+**---------------------------------------------------------------*/
+#ifdef FRETVAL
+#undef FRETVAL
+#endif
+
+#if defined(MAC) /* with LS FORTRAN */
+#ifndef ABSOFT
+# define FCALLKEYW pascal
+# define FRETVAL(x) pascal x
+#endif /* ABSOFT */
+#endif
+
+#ifndef FRETVAL /* !MAC */
+# define FCALLKEYW /*NONE*/
+# define FRETVAL(x) x
+#endif
+
+
+/*----------------------------------------------------------------
+** MACRO FNAME for any fortran callable routine name.
+**
+** This macro prepends, appends, or does not modify a name
+** passed as a macro parameter to it based on the FNAME_PRE_UNDERSCORE,
+** FNAME_POST_UNDERSCORE macros set for a specific system.
+**
+**---------------------------------------------------------------*/
+#if defined(FNAME_PRE_UNDERSCORE) && defined(FNAME_POST_UNDERSCORE)
+# define FNAME(x) _##x##_
+#endif
+#if defined(FNAME_PRE_UNDERSCORE) && !defined(FNAME_POST_UNDERSCORE)
+# define FNAME(x) _##x
+#endif
+#if !defined(FNAME_PRE_UNDERSCORE) && defined(FNAME_POST_UNDERSCORE)
+# define FNAME(x) x##_
+#endif
+#if !defined(FNAME_PRE_UNDERSCORE) && !defined(FNAME_POST_UNDERSCORE)
+# define FNAME(x) x
+#endif
+
+
+#endif /* HDF5FORT_H */
+
+
+
diff --git a/src/hdf5gen.h b/src/hdf5gen.h
new file mode 100644
index 0000000..4d01685
--- /dev/null
+++ b/src/hdf5gen.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains general macros used throughout HDF5 library & interfaces
+ */
+
+#ifndef HDF5GEN_H
+#define HDF5GEN_H
+
+/* return code - since some unix/c routines use 0 and -1 as their return
+ code, and some assumption had been made in the code about that, it is
+ important to keep these constants the same values. For explicitly
+ boolean functions, use TRUE and FALSE */
+
+#define SUCCEED 0
+#define FAIL (-1)
+
+/* boolean values, reminder: NEVER compare with numeric values */
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+#ifndef TRUE
+# define TRUE (!FALSE)
+#endif
+
+/* Function entry & exit macros */
+#define FUNC_ENTER(pablo_mask,pablo_func_id,interface_init_func,err) \
+ { PABLO_TRACE_ON(pablo_mask,pablo_func_id); \
+ if(library_initialize==FALSE) if(H5_init_library()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); \
+ if(thread_initialize==FALSE) if(H5_init_thread()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); \
+ if(interface_initialize==FALSE) if(interface_init_func()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); }
+#define FUNC_LEAVE(pablo_mask,pablo_func_id,return_value) \
+ { PABLO_TRACE_OFF(pablo_mask,pablo_func_id); return(return_value); }
+
+#endif /* HDF5GEN_H */
+
diff --git a/src/hdf5glob.h b/src/hdf5glob.h
new file mode 100644
index 0000000..2fc752d
--- /dev/null
+++ b/src/hdf5glob.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * Header file for global & thread-specific data
+ */
+
+#ifndef HDF5GLOB_H
+#define HDF5GLOB_H
+
+/* Library global variables */
+/* There should only be a few of these, don't add more unless you have a d*mn good reason! */
+
+#ifndef HDF5_MASTER
+extern
+#endif /* HDF5_MASTER */
+intn library_initialize /* Whether we've initialized library global information yet */
+#ifdef HDF5_MASTER
+= FALSE
+#endif /* HDF5_MASTER */
+;
+#ifndef HDF5_MASTER
+extern
+#endif /* HDF5_MASTER */
+intn install_atexit /* Whether to install the atexit routine */
+#ifdef HDF5_MASTER
+= TRUE
+#endif /* HDF5_MASTER */
+;
+
+/* Thread-specific variables */
+#ifndef HDF5_MASTER
+extern
+#endif /* HDF5_MASTER */
+intn thread_initialize /* Whether we've initialized thread global information yet */
+#ifdef HDF5_MASTER
+= FALSE
+#endif /* HDF5_MASTER */
+;
+
+#ifndef HDF5_MASTER
+extern
+#endif /* HDF5_MASTER */
+int32 thrderrid; /* Thread-specific "global" error-handler ID */
+
+#endif /* HDF5GLOB_H */
+
diff --git a/src/hdf5lims.h b/src/hdf5lims.h
new file mode 100644
index 0000000..dc8648d
--- /dev/null
+++ b/src/hdf5lims.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains all global hard coded limits for the library, interface
+ * particular limits are defined in the interface header file.
+ */
+
+#ifndef HDF5LIMS_H
+#define HDF5LIMS_H
+
+/* Size of an OID in bytes */
+#define HDF5_OID_SIZE 8
+
+/* Version #'s of library code */
+#define HDF5_MAJOR_VERSION 0 /* For major interface changes */
+#define HDF5_MINOR_VERSION 0 /* For minor interface changes */
+#define HDF5_RELEASE_VERSION 0 /* For interface tweaks & bug-fixes */
+#define HDF5_PATCH_VERSION 0 /* For small groups of bug fixes */
+
+/* Version #'s of the major components of the file format */
+#define HDF5_BOOTBLOCK_VERSION 0 /* Version of the boot block format */
+#define HDF5_SMALLOBJECT_VERSION 0 /* Version of the Small-Object Heap */
+#define HDF5_FREESPACE_VERSION 0 /* Version of the Free-Space Info */
+#define HDF5_OBJECTDIR_VERSION 0 /* Version of the Object Directory format */
+#define HDF5_SHAREDHEADER_VERSION 0 /* Version of the Shared-Header Info */
+
+/* Define the HDF5 file signature */
+#define HDF5_FILE_SIGNATURE "\211HDF\r\n\032\n"
+#define HDF5_FILE_SIGNATURE_LEN 8
+
+/* Maximum length of function name to push onto error stack */
+#define MAX_FUNC_NAME_LEN 32
+
+/* Default sizes of the hash-tables for various atom groups */
+#define HDF5_ERRSTACK_HASHSIZE 64
+#define HDF5_FILEID_HASHSIZE 64
+#define HDF5_TEMPID_HASHSIZE 64
+#define HDF5_DATATYPEID_HASHSIZE 64
+#define HDF5_DATASPACEID_HASHSIZE 64
+
+/* Default file-creation template values */
+#define HDF5_USERBLOCK_DEFAULT 0 /* Default to 0-byte sized user blocks */
+#define HDF5_OFFSETSIZE_DEFAULT 4 /* Default to 4-byte offsets */
+#define HDF5_LENGTHSIZE_DEFAULT 4 /* Default to 4-byte lengths */
+#define HDF5_BTREEPAGE_DEFAULT 1024 /* Default to 1024-byte B-tree pages */
+
+#endif /* HDF5LIMS_H */
+
diff --git a/src/hdf5meta.h b/src/hdf5meta.h
new file mode 100644
index 0000000..025b4e6
--- /dev/null
+++ b/src/hdf5meta.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains macros & information for file meta information
+ * (offsets, lengths, etc.)
+ */
+
+#ifndef HDF5META_H
+#define HDF5META_H
+
+/*-----------------------------------------------------*/
+/* Encode and decode macros for file meta-data */
+/* (Currently, all file meta-data is little-endian) */
+/*-----------------------------------------------------*/
+
+/* For non-little-endian platforms, encode each byte by itself */
+#if ((DF_MT&0xFFF0)!=0x4440)
+# define INT16ENCODE(p, i) \
+{ *(p) = (uint8)((uintn)(i) & 0xff); (p)++; *(p) = (uint8)(((uintn)(i) >> 8) & 0xff); (p)++; }
+
+# define UINT16ENCODE(p, i) \
+{ *(p) = (uint8)((i) & 0xff); (p)++; *(p) = (uint8)(((uintn)(i) >> 8) & 0xff); (p)++; }
+
+# define INT32ENCODE(p, i) \
+{ *(p) = (uint8)((uint32)(i) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint32)(i) >> 8) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint32)(i) >> 16) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint32)(i) >> 24) & 0xff); (p)++; }
+
+# define UINT32ENCODE(p, i) \
+{ *(p) = (uint8)((i) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; }
+#ifdef HDF5_HAVE_NATIVE_INT64
+# define INT64ENCODE(p, i) \
+{ *(p) = (uint8)((uint64)(i) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 8) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 16) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 24) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \
+ *(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; }
+
+# define UINT64ENCODE(p, i) \
+{ *(p) = (uint8)((i) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \
+ *(p) = (uint8)(((i) >> 56) & 0xff); (p)++; }
+#else /* HDF5_HAVE_NATIVE_INT64 */
+#error "Define int64 on platforms which don't support it"
+#endif /* HDF5_HAVE_NATIVE_INT64 */
+
+# define INT16DECODE(p, i) \
+{ (i) = (int16)((*(p) & 0xff)); (p)++; \
+ (i) |= (int16)((*(p) & 0xff) << 8); (p)++; }
+
+# define UINT16DECODE(p, i) \
+{ (i) = (uint16)(*(p) & 0xff); (p)++; \
+ (i) |= (uint16)((*(p) & 0xff) << 8); (p)++; }
+
+# define INT32DECODE(p, i) \
+{ (i) = (*(p) & 0xff); (p)++; \
+ (i) |= ((int32)(*(p) & 0xff) << 8); (p)++; \
+ (i) |= ((int32)(*(p) & 0xff) << 16); (p)++; \
+ (i) |= ((int32)(*(p) & 0xff) << 24); (p)++; }
+
+# define UINT32DECODE(p, i) \
+{ (i) = (uint32)(*(p) & 0xff); (p)++; \
+ (i) |= ((uint32)(*(p) & 0xff) << 8); (p)++; \
+ (i) |= ((uint32)(*(p) & 0xff) << 16); (p)++; \
+ (i) |= ((uint32)(*(p) & 0xff) << 24); (p)++; }
+
+#ifdef HDF5_HAVE_NATIVE_INT64
+#define INT64DECODE(p, i) \
+{ (i) = (*(p) & 0xff); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 8); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 16); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 24); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \
+ (i) |= ((int64)(*(p) & 0xff) << 56); (p)++; }
+
+# define UINT64DECODE(p, i) \
+{ (i) = (uint64)(*(p) & 0xff); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 8); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 16); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 24); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \
+ (i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; }
+#else /* HDF5_HAVE_NATIVE_INT64 */
+#error "Define int64 on platforms which don't support it"
+#endif /* HDF5_HAVE_NATIVE_INT64 */
+#else /* platform has little-endian integers */
+/* For little-endian platforms, make the compiler do the work */
+# define INT16ENCODE(p, i) { *((int16 *)(p)) = (int16)(i); (p)+=2; }
+# define UINT16ENCODE(p, i) { *((uint16 *)(p)) = (uint16)(i); (p)+=2; }
+# define INT32ENCODE(p, i) { *((int32 *)(p)) = (int32)(i); (p)+=4; }
+# define UINT32ENCODE(p, i) { *((uint32 *)(p)) = (uint32)(i); (p)+=4; }
+#ifdef HDF5_HAVE_NATIVE_INT64
+# define INT64ENCODE(p, i) { *((int64 *)(p)) = (int64)(i); (p)+=8; }
+# define UINT64ENCODE(p, i) { *((uint64 *)(p)) = (uint64)(i); (p)+=8; }
+#else /* HDF5_HAVE_NATIVE_INT64 */
+#error "Define int64 on platforms which don't support it"
+#endif /* HDF5_HAVE_NATIVE_INT64 */
+# define INT16DECODE(p, i) { (i) = (int16)(*(int16 *)(p)); (p)+=2; }
+# define UINT16DECODE(p, i) { (i) = (uint16)(*(uint16 *)(p)); (p)+=2; }
+# define INT32DECODE(p, i) { (i) = (int32)(*(int32 *)(p)); (p)+=4; }
+# define UINT32DECODE(p, i) { (i) = (uint32)(*(uint32 *)(p)); (p)+=4; }
+#ifdef HDF5_HAVE_NATIVE_INT64
+# define INT64DECODE(p, i) { (i) = (int64)(*(int64 *)(p)); (p)+=8; }
+# define UINT64DECODE(p, i) { (i) = (uint64)(*(uint64 *)(p)); (p)+=8; }
+#else /* HDF5_HAVE_NATIVE_INT64 */
+#error "Define int64 on platforms which don't support it"
+#endif /* HDF5_HAVE_NATIVE_INT64 */
+#endif
+
+# define NBYTEENCODE(d, s, n) { HDmemcpy(d,s,n); p+=n }
+
+/* Note! the NBYTEDECODE macro is backwards from the memcpy() routine, */
+/* in the spirit of the other DECODE macros */
+# define NBYTEDECODE(s, d, n) { HDmemcpy(d,s,n); p+=n }
+
+#endif /* HDF5I_H */
+
diff --git a/src/hdf5pabl.h b/src/hdf5pabl.h
new file mode 100644
index 0000000..0df5913
--- /dev/null
+++ b/src/hdf5pabl.h
@@ -0,0 +1,32 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * Header file for Pablo compatibility
+ */
+
+#ifndef HDF5PABL_H
+#define HDF5PABL_H
+
+#ifdef HAVE_PABLO
+#define PABLO_TRACE_ON(m, f) TRACE_ON(m,f)
+#define PABLO_TRACE_OFF(m, f) TRACE_OFF(m,f)
+#else /* no Pablo tracing enabled */
+#define PABLO_TRACE_ON(m, f)
+#define PABLO_TRACE_OFF(m, f)
+#endif /* HAVE_PABLO */
+
+#endif /* HDF5PABL_H */
+
+
diff --git a/src/hdf5plat.h b/src/hdf5plat.h
new file mode 100644
index 0000000..5c5f649
--- /dev/null
+++ b/src/hdf5plat.h
@@ -0,0 +1,750 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains platform/CPU/OS detection macros, etc.
+ */
+
+#ifndef HDF5PLAT_H
+#define HDF5PLAT_H
+
+/*--------------------------------------------------------------------------*/
+/* MT/NT constants */
+/* Six MT nibbles represent float64, float32, int64, int32, int16, and */
+/* int8 (from most significant to least significant). The unsigned */
+/* form of each type is assumed to be in the same format as the signed */
+/* type. The top two nibbles (8-bits) are currently unused. */
+/* The values for each nibble are: */
+/* 1 - Big Endian */
+/* 2 - VAX */
+/* 3 - Cray */
+/* 4 - Little Endian */
+/* 5 - Convex */
+/* 6 - Fujitsu VP */
+/*--------------------------------------------------------------------------*/
+#define DFMT_SUN 0x00111111
+#define DFMT_ALLIANT 0x00111111
+#define DFMT_IRIX 0x00111111
+#define DFMT_APOLLO 0x00111111
+#define DFMT_IBM6000 0x00111111
+#define DFMT_HP9000 0x00111111
+#define DFMT_CONVEXNATIVE 0x00551111
+#define DFMT_CONVEX 0x00111111
+#define DFMT_UNICOS 0x00333331
+#define DFMT_CTSS 0x00333331
+#define DFMT_VAX 0x00222221
+#define DFMT_MIPSEL 0x00444441
+#define DFMT_PC 0x00444441
+#define DFMT_MAC 0x00111111
+#define DFMT_SUN386 0x00444441
+#define DFMT_NEXT 0x00111111
+#define DFMT_MOTOROLA 0x00111111
+#define DFMT_ALPHA 0x00444441
+#define DFMT_VP 0x00661111
+#define DFMT_I860 0x00444441
+#define DFMT_CRAYMPP 0x00117771
+
+/* I/O library constants */
+#define POSIXUNBUFIO 1 /* POSIX-compliant un-buffered I/O */
+#define POSIXBUFIO 2 /* POSIX buffered I/O */
+#define MACIO 3 /* Macintosh I/O */
+#define WINNTIO 4 /* 32-bit Windows File I/O */
+#define PAGEBUFIO 5 /* page buffering - fmpool */
+
+#ifdef GOT_MACHINE
+#undef GOT_MACHINE
+#endif
+
+/*-------------------------------------------------------------------------
+ * Define options for each platform
+ *-------------------------------------------------------------------------*/
+
+#if (defined(SUN) || defined(sun) || defined(__sun__) || defined(__SUNPRO_C)) & !defined(__i386)
+#ifdef __STDC__
+#define ANSISUN
+#else /* __STDC__ */
+#define KNRSUN
+#endif /* __STDC__ */
+#endif /* SUN || sun */
+
+/*
+ * CPU: Sparc
+ * OS: Solaris 1.x, SunOS 4.1.x
+ */
+#if defined(ANSISUN)
+
+#if !defined(SUN)
+#define SUN
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#include <unistd.h> /* for some file I/O stuff */
+#include <sys/time.h>
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_SUN
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+
+#endif /* ANSISUN */
+
+/*
+ * CPU: IBM RS/6000 chip/PowerPC
+ * OS: AIX
+ */
+#if defined(IBM6000) || defined(_AIX)
+
+#ifndef IBM6000
+#define IBM6000
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+# define BSD
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_IBM6000
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+
+#endif /* IBM6000 */
+
+/*
+ * CPU: HP PA-RISC
+ * OS: HP/UX (ConvexOS?)
+ */
+#if defined(HP9000) || (!defined(__convexc__) && (defined(hpux) || defined(__hpux)))
+
+#ifndef HP9000
+#define HP9000
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#define HAVE_UNISTD_H /* unistd.h - close, fork,..etc */
+# define BSD
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_HP9000
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /* HP9000 */
+
+
+/*
+ * CPU: MIPS
+ * OS: IRIX
+ */
+#if defined(IRIX) || defined(IRIS4) || defined(sgi) || defined(__sgi__) || defined(__sgi)
+
+#ifndef IRIX
+#define IRIX
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+# define BSD
+#ifndef __GNUC__
+#include <memory.h>
+#endif /* __GNUC__ */
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_IRIX
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef signed char char8;
+typedef unsigned char uchar8;
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+
+#endif /* IRIX */
+
+/*
+ * CPU: Cray Vector CPU (is there a name for these? :-)
+ * OS: UNICOS
+ */
+#if (defined(UNICOS) || defined(_UNICOS)) && !defined(_CRAYMPP)
+
+#ifndef UNICOS
+#define UNICOS
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <memory.h>
+#include <fortran.h>
+#ifndef O_RDONLY
+#include <fcntl.h> /* for unbuffered i/o stuff */
+#define L_INCR 1
+#include <sys/stat.h>
+#endif /*O_RDONLY*/
+
+/* Set machine byte-format */
+#define DF_MT DFMT_UNICOS
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+#ifdef OLD_WAY /* May need to be included on other machines than the C-90 */
+typedef char *_fcd; /* Fortran character descriptor type */
+#endif /* OLD_WAY */
+typedef signed char char8;
+typedef unsigned char uchar8;
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef int int16;
+typedef unsigned int uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define DF_CAPFNAMES /* fortran names are in all caps */
+/* fcdtocp(desc) is defined in compiler header files */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define RIGHT_SHIFT_IS_UNSIGNED
+#define CHAR_IS_UNSIGNED
+
+#endif /* UNICOS */
+
+/*
+ * CPU: Cray Vector CPU (is there a name for these? :-)
+ * OS: UNICOS (on massively parallel systems, like T3D & T3E)
+ */
+#if defined(_CRAYMPP)
+
+#ifndef CRAYMPP
+#define CRAYMPP
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <memory.h>
+#include <fortran.h>
+#ifndef O_RDONLY
+#include <fcntl.h> /* for unbuffered i/o stuff */
+#define L_INCR 1
+#include <sys/stat.h>
+#endif /*O_RDONLY*/
+
+/* Set machine byte-format */
+#define DF_MT DFMT_CRAYMPP
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+#ifdef OLD_WAY /* May need to be included on other machines than the C-90 */
+typedef char *_fcd; /* Fortran character descriptor type */
+#endif /* OLD_WAY */
+typedef signed char char8;
+typedef unsigned char uchar8;
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef short int32;
+typedef unsigned short uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define DF_CAPFNAMES /* fortran names are in all caps */
+/* fcdtocp(desc) is defined in compiler header files */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define RIGHT_SHIFT_IS_UNSIGNED
+#define CHAR_IS_UNSIGNED
+
+#endif /* CRAYMPP */
+
+
+/*
+ * CPU: Motorola 68K, PowerPC (both?)
+ * OS: MacOS
+ */
+#if defined(MAC) || defined(macintosh) || defined(__MWERKS__) || defined (SYMANTEC_C)
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <memory.h> /* malloc stuff for MPW */
+#include <fcntl.h> /* unbuffered I/O stuff for MPW */
+#ifdef __MWERKS__ /* Metrowerks */
+#include <sioux.h>
+#include <console.h>
+#endif
+#ifdef SYMANTEC_C /* for SYMANTEC C */
+#include <unix.h>
+#define isascii(c) (isprint(c) || iscntrl(c))
+#else /* MPW, possibly others */
+#include <Files.h> /* for unbuffered I/O stuff */
+#endif /* SYMANTEC_C*/
+#define DF_DYNAMIC /* use dynamic allocation */
+
+/* Set machine byte-format */
+#define DF_MT DFMT_MAC
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#ifndef ABSOFT
+#define DF_CAPFNAMES /* fortran names are in all caps */
+#endif /* ABSOFT */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+void exit(int status);
+
+/* Choose the I/O package to use when interacting with the file */
+#define FILELIB MACIO
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+
+#endif /*MAC*/
+
+/*
+ * CPU: Intel x86
+ * OS: MS Windows '95, Windows NT (& Dos32?), also Linux & FreeBSD
+ */
+/* Metrowerks compilier defines some PC stuff so need to exclude this on the MAC */
+#if !(defined(__MWERKS__) || defined(MAC))
+
+#if defined INTEL86 || defined M_I86 || defined M_I386 || defined DOS386 || defined __i386 || defined UNIX386
+#ifndef INTEL86
+#define INTEL86
+#endif /* INTEL86 */
+
+#if !defined UNIX386 && (defined unix || defined __unix)
+#define UNIX386
+#endif /* UNIX386 */
+
+#if !defined DOS386 && defined M_I386
+#define DOS386
+#endif /* M_I386 && !DOS386 */
+
+#if defined _WINDOWS || defined WIN32
+#define WIN386
+#endif /* _WINDOWS | WIN32 */
+
+#if defined WIN386 || defined DOS386 || defined UNIX386
+#define INTEL386
+#endif /* WIN386 | DOS386 | UNIX386 */
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE 1
+
+/* Extra include files required for this platform */
+#include <fcntl.h>
+#ifdef UNIX386
+#include <sys/types.h> /* for unbuffered file I/O */
+#include <sys/stat.h>
+#include <unistd.h>
+#else /* !UNIX386 */
+#include <sys\types.h> /* for unbuffered file I/O */
+#include <sys\stat.h>
+#include <io.h>
+#include <conio.h> /* for debugging getch() calls */
+#include <malloc.h>
+#endif /* UNIX386 */
+#include <ctype.h> /* for character macros */
+#ifdef __WATCOMC__
+#include <stddef.h> /* for the 'fortran' pragma */
+#endif
+#if defined WIN386
+#ifndef GMEM_MOVEABLE /* check if windows header is already included */
+#include <windows.h> /* include the windows headers */
+#include <winnt.h>
+#define HAVE_BOOLEAN
+#endif /* GMEM_MOVEABLE */
+#endif /* WIN386 */
+
+/* Set machine byte-format */
+#define DF_MT DFMT_PC
+
+/* Define portable variable types */
+#ifndef VOID /* The stupid windows.h header file uses a #define instead of a typedef */
+typedef void VOID;
+#endif /* end VOID */
+typedef void * VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+typedef long int int32;
+typedef unsigned long int uint32;
+#ifdef __GNUC__
+#define HDF5_HAVE_NATIVE_INT64
+typedef long long int int64; /* 64-bit integers! */
+typedef unsigned long long int uint64;
+#endif
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef long intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#if defined UNIX386
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#elif defined INTEL386
+#define DF_CAPFNAMES /* Fortran function names need to be all-caps */
+#endif
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#if defined WIN386
+#define FILELIB WINNTIO
+#else
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+#endif /* WIN386 */
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+
+#endif /* INTEL86 */
+#endif /* !(defined(__MWERKS__) || defined(MAC)) */
+
+
+/*
+ * CPU: Alpha
+ * OS: Dec Unix (used to be called OSF/1)
+ */
+#if defined DEC_ALPHA || (defined __alpha && defined __unix__)
+
+#ifndef DEC_ALPHA
+#define DEC_ALPHA
+#endif
+
+#ifdef GOT_MACHINE
+If you get an error on this line more than one machine type has been defined.
+Please check your Makefile.
+#endif
+#define GOT_MACHINE
+
+/* Extra include files required for this platform */
+#include <sys/file.h> /* for unbuffered i/o stuff */
+#include <sys/stat.h>
+
+/* Set machine byte-format */
+#define DF_MT DFMT_ALPHA
+
+/* Define portable variable types */
+typedef void VOID;
+typedef void *VOIDP;
+typedef char char8;
+typedef unsigned char uchar8;
+typedef char int8;
+typedef unsigned char uint8;
+typedef short int int16;
+typedef unsigned short int uint16;
+#ifndef __rpc_types_h
+typedef int int32;
+typedef unsigned int uint32;
+#endif /* __rpc_types_h */
+typedef int intn;
+typedef unsigned int uintn;
+typedef float float32;
+typedef double float64;
+typedef char *_fcd; /* Fortran character descriptor type */
+typedef int intf; /* size of INTEGERs in Fortran compiler */
+
+/* Fortran compatibility macros */
+#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */
+#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */
+
+/* Choose the I/O package to use when interacting with the file */
+#ifdef HAVE_FMPOOL
+#define FILELIB PAGEBUFIO /* enable page buffering */
+#else
+#define FILELIB POSIXBUFIO
+#endif
+
+/* JPEG #define's - Look in the JPEG docs before changing - (Q) */
+
+/* Determine the memory manager we are going to use. Valid values are: */
+/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */
+/* what each does */
+#define JMEMSYS MEM_ANSI
+#ifdef __GNUC__
+#define HAVE_STDC
+#define INCLUDES_ARE_ANSI
+#endif
+
+#endif /* DEC_ALPHA */
+
+#include "h5oplat.h" /* include definitions for old, untested platforms */
+
+/* Check if we've correctly determined the platform we are compiling in/for */
+#ifndef GOT_MACHINE
+No machine type has been defined. Your Makefile needs to have someing like
+-DSUN or -DUNICOS in order for the HDF internal structures to be defined
+correctly.
+#endif
+
+#endif /* HDF5PLAT_H */
+
diff --git a/src/hdf5port.h b/src/hdf5port.h
new file mode 100644
index 0000000..bdec34f
--- /dev/null
+++ b/src/hdf5port.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This file contains portability macros to ease moving the library between
+ * the various platforms.
+ */
+
+#ifndef HDF5PORT_H
+#define HDF5PORT_H
+
+/**************************************************************************
+* Generally useful macro definitions
+**************************************************************************/
+#ifndef MIN
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) (((a)>(b)) ? (a) : (b))
+#endif
+
+/**************************************************************************
+* Macros to work around ANSI C portability problems.
+**************************************************************************/
+#ifdef DUMBCC
+#define CONSTR(v,s) char *v=s
+#else
+#define CONSTR(v,s) static const char v[]=s
+#endif
+
+/* -------------------------- File I/O Functions -------------------------- */
+/* FILELIB -- file library to use for file access: 1 stdio, 2 fcntl
+ default to stdio library i.e. POSIX buffered I/O */
+
+#ifndef FILELIB
+# define FILELIB POSIXBUFIO /* POSIX buffered I/O is the default */
+#endif /* FILELIB */
+
+#if (FILELIB == POSIXBUFIO)
+typedef FILE *hdf_file_t;
+#ifdef VMS
+/* For VMS, use "mbc=64" to improve performance */
+# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p),"r+","mbc=64") : fopen((p), "r", "mbc=64"))
+# define H5FI_CREATE(p) (fopen((p), "w+", "mbc=64"))
+#else /* !VMS */
+#if defined SUN && defined (__GNUC__)
+# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p), "r+") : fopen((p), "r"))
+# define H5FI_CREATE(p) (fopen((p), "w+"))
+#else /* !SUN w/ GNU CC */
+# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p), "rb+") : fopen((p), "rb"))
+# define H5FI_CREATE(p) (fopen((p), "wb+"))
+#endif /* !SUN w/ GNU CC */
+#endif /* VMS */
+# define H5FI_READ(f, b, n) (((size_t)(n) == (size_t)fread((b), 1, (size_t)(n), (f))) ? SUCCEED : FAIL)
+# define H5FI_WRITE(f, b, n) (((size_t)(n) == (size_t)fwrite((b), 1, (size_t)(n), (f))) ? SUCCEED : FAIL)
+# define H5FI_CLOSE(f) (fclose(f))
+# define H5FI_FLUSH(f) (fflush(f)==0 ? SUCCEED : FAIL)
+# define H5FI_SEEK(f,o) (fseek((f), (long)(o), SEEK_SET)==0 ? SUCCEED : FAIL)
+# define H5FI_SEEK_CUR(f,o) (fseek((f), (long)(o), SEEK_CUR)==0 ? SUCCEED : FAIL)
+# define H5FI_SEEKEND(f) (fseek((f), (long)0, SEEK_END)==0 ? SUCCEED : FAIL)
+# define H5FI_TELL(f) (ftell(f))
+# define H5FI_OPENERR(f) ((f) == (FILE *)NULL)
+# define H5FI_INVALID_FILE ((FILE *)NULL)
+#endif /* FILELIB == POSIXBUFIO */
+
+#if (FILELIB == POSIXUNBUFIO)
+/* using POSIX unbuffered file I/O routines to access files */
+typedef int hdf_file_t;
+# define H5FI_OPEN(p, a) (((a) & H5ACC_WRITE) ? open((p), O_RDWR) : open((p), O_RDONLY))
+# define H5FI_CREATE(p) (open((p), O_RDWR | O_CREAT | O_TRUNC))
+# define H5FI_CLOSE(f) (close(f))
+# define H5FI_FLUSH(f) (SUCCEED)
+# define H5FI_READ(f, b, n) (((n)==read((f), (char *)(b), (n))) ? SUCCEED : FAIL)
+# define H5FI_WRITE(f, b, n) (((n)==write((f), (char *)(b), (n))) ? SUCCEED : FAIL)
+# define H5FI_SEEK(f, o) (lseek((f), (off_t)(o), SEEK_SET)!=(-1) ? SUCCEED : FAIL)
+# define H5FI_SEEKEND(f) (lseek((f), (off_t)0, SEEK_END)!=(-1) ? SUCCEED : FAIL)
+# define H5FI_TELL(f) (lseek((f), (off_t)0, SEEK_CUR))
+# define H5FI_OPENERR(f) (f < 0)
+# define H5FI_INVALID_FILE ((int)-1)
+#endif /* FILELIB == POSIXUNBUFIO */
+
+#if (FILELIB == MACIO)
+/* using special routines to redirect to Mac Toolkit I/O */
+typedef short hdf_file_t;
+# define H5FI_OPEN(x,y) mopen(x,y)
+# define H5FI_CREATE(name) mopen(name, H5ACC_CREATE)
+# define H5FI_CLOSE(x) mclose(x)
+# define H5FI_FLUSH(a) (SUCCEED)
+# define H5FI_READ(a,b,c) mread(a, (char *) b, (int32) c)
+# define H5FI_WRITE(a,b,c) mwrite(a, (char *) b, (int32) c)
+# define H5FI_SEEK(x,y) mlseek(x, (int32 )y, 0)
+# define H5FI_SEEKEND(x) mlseek(x, 0L, 2)
+# define H5FI_TELL(x) mlseek(x,0L,1)
+# define H5FI_OPENERR(f) (f < 0)
+# define H5FI_INVALID_FILE ((short)-1)
+#endif /* FILELIB == MACIO */
+
+#if (FILELIB == WINNTIO)
+/* using special Windows NT functions to enable reading/writing large chunks */
+typedef HFILE hdf_file_t;
+# define H5FI_OPEN(p, a) (((a) & H5ACC_WRITE) ? _lopen((p), OF_READWRITE) : _lopen((p), OF_READ))
+# define H5FI_CREATE(p) (_lcreat((p), 0))
+# define H5FI_READ(f, b, n) (((int32)(n) == _hread((f), (b), (n))) ? SUCCEED : FAIL)
+# define H5FI_WRITE(f, b, n) (((int32)(n) == _hwrite((f), (b), (n))) ? SUCCEED : FAIL)
+# define H5FI_CLOSE(f) (_lclose(f)==0 ? SUCCEED : FAIL)
+# define H5FI_FLUSH(f) (0)
+# define H5FI_SEEK(f, o) (_llseek((f), (long)(o), 0))
+# define H5FI_SEEKEND(f) (_llseek((f), (long)0, 2))
+# define H5FI_TELL(f) (_llseek((f),0l,1))
+# define H5FI_OPENERR(f) ((f) == (HFILE)HFILE_ERROR)
+# define H5FI_INVALID_FILE ((HFILE)HFILE_ERROR)
+#endif /* FILELIB == WINNTIO */
+
+#if (FILELIB == PAGEBUFIO)
+#include "fmpio.h"
+/* using page buffered file I/O routines to access files */
+typedef MPFILE *hdf_file_t;
+# define H5FI_OPEN(p, a) (MPopen((p), (a)))
+# define H5FI_CREATE(p) (MPopen((p), H5ACC_CREATE))
+# define H5FI_CLOSE(f) (MPclose(f))
+# define H5FI_FLUSH(f) (MPflush(f))
+# define H5FI_READ(f, b, n) (MPread((f), (char *)(b), (n)))
+# define H5FI_WRITE(f, b, n) (MPwrite((f), (char *)(b), (n)))
+# define H5FI_SEEK(f, o) (MPseek((f), (off_t)(o), SEEK_SET))
+# define H5FI_SEEKEND(f) (MPseek((f), (off_t)0, SEEK_END))
+# define H5FI_TELL(f) (MPseek((f), (off_t)0, SEEK_CUR))
+# define H5FI_OPENERR(f) ((f) == (MPFILE *)NULL)
+# define H5FI_INVALID_FILE ((MPFILE *)NULL)
+#endif /* FILELIB == PAGEBUFIO */
+
+/**************************************************************************
+* Allocation functions defined differently
+**************************************************************************/
+#if !defined MALLOC_CHECK
+# define HDmalloc(s) (malloc((size_t)s))
+# define HDcalloc(a,b) (calloc((size_t)a,(size_t)b))
+# define HDfree(p) (free((void*)p))
+# define HDrealloc(p,s) (realloc((void*)p,(size_t)s))
+#endif /* !defined MALLOC_CHECK */
+/* Macro to free space and clear pointer to NULL */
+#define HDfreenclear(p) { if((p)!=NULL) HDfree(p); p=NULL; }
+
+/**************************************************************************
+* String functions defined differently
+**************************************************************************/
+
+# define HDstrcat(s1,s2) (strcat((s1),(s2)))
+# define HDstrcmp(s,t) (strcmp((s),(t)))
+# define HDstrcpy(s,d) (strcpy((s),(d)))
+# define HDstrlen(s) (strlen((const char *)(s)))
+# define HDstrncmp(s1,s2,n) (strncmp((s1),(s2),(n)))
+# define HDstrncpy(s1,s2,n) (strncpy((s1),(s2),(n)))
+# define HDstrchr(s,c) (strchr((s),(c)))
+# define HDstrrchr(s,c) (strrchr((s),(c)))
+# define HDstrtol(s,e,b) (strtol((s),(e),(b)))
+/* non-standard function, not defined on the following mahcines - */
+#if !(defined VMS || defined macintosh || defined MAC || defined __MWERKS__ || defined SYMANTEC_C || defined MIPSEL || defined NEXT || defined CONVEX || defined IBM6000 || defined ANSISUN || defined IRIX)
+# define HDstrdup(s) ((char *)strdup((const char *)(s)))
+#endif /* !(VMS | etc..) */
+
+
+/**************************************************************************
+* Memory functions defined differently
+**************************************************************************/
+
+# define HDmemcpy(dst,src,n) (memcpy((void *)(dst),(const void *)(src),(size_t)(n)))
+# define HDmemmove(dst,src,n) (memmove((void*)(dst),(const void *)(src),(size_t)(n)))
+# define HDmemset(dst,c,n) (memset((void *)(dst),(intn)(c),(size_t)(n)))
+# define HDmemcmp(dst,src,n) (memcmp((const void *)(dst),(const void *)(src),(size_t)(n)))
+
+
+/**************************************************************************
+* Misc. functions
+**************************************************************************/
+#if defined (MAC) || defined (macintosh) || defined(__MWERKS__) || defined (SYMANTEC_C)
+#define HDstat(path, result) (mstat(path))
+#else /* !macintosh */
+#define HDstat(path, result) (stat(path, result))
+#endif /* !macintosh */
+#define HDgetcwd(s,l) (getcwd(s,l))
+#define HDgetenv(s1) (getenv(s1))
+#define HDputenv(s1) (putenv(s1))
+#define HDltoa(v) (ltoa(v))
+#if defined (SUN) && defined(__GNUC__)
+#define HDatexit(f) (0) /* we punt on the SUN using gcc */
+#else /* !SUN & GCC */
+#define HDatexit(f) (atexit(f))
+#endif /* !SUN & GCC */
+
+#endif /* HDF5PORT_H */
+
diff --git a/src/hdf5type.h b/src/hdf5type.h
new file mode 100644
index 0000000..ac5ffa3
--- /dev/null
+++ b/src/hdf5type.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * Header file for library-global generic typedefs
+ */
+
+#ifndef HDF5TYPE_H
+#define HDF5TYPE_H
+
+/*
+ * Define the standard error-value return type. This type should be used for
+ * functions which return SUCCEED/FAIL, instead of intn...
+ */
+typedef intn herr_t; /* Generic error-value type */
+
+/* Object types for "meta" interface */
+typedef group_t hobjtype_t; /* Map the object in the "meta" interface to atom groups */
+
+/* File-creation template information structure */
+typedef struct {
+ /* These object aren't ref. counted, I can't think of a good reason why you'd access each one more than once */
+ /* uintn ref_count; Reference count for number of times object is accessed */
+ uintn userblock_size; /* Size of the user block in the file in bytes */
+ uintn offset_size; /* Number of bytes for offsets */
+ uintn length_size; /* Number of bytes for lengths */
+ uintn btree_page_size; /* Number of bytes for B-Tree pages */
+ uint8 bootblock_ver; /* Version # of the bootblock */
+ uint8 smallobject_ver; /* Version # of the small-object heap */
+ uint8 freespace_ver; /* Version # of the free-space information */
+ uint8 objectdir_ver; /* Version # of the object directory format */
+ uint8 sharedheader_ver; /* Version # of the shared header format */
+ } file_create_temp_t;
+
+/* Parameters to use when retrieving file-creation template information */
+typedef enum {
+ H5_USERBLOCK_SIZE, /* (uintn) Size of the user block in the file in bytes */
+ H5_OFFSET_SIZE, /* (uintn) Number of bytes for offsets */
+ H5_LENGTH_SIZE, /* (uintn) Number of bytes for lengths */
+ H5_BTREE_SIZE, /* (uintn) Number of bytes for B-Tree pages */
+ H5_BOOTBLOCK_VER, /* (uint8) Version # of the boot-block format */
+ H5_SMALLOBJECT_VER, /* (uint8) Version # of the small-object heap format */
+ H5_FREESPACE_VER, /* (uint8) Version # of the free-space info format */
+ H5_OBJECTDIR_VER, /* (uint8) Version # of the object-directory format */
+ H5_SHAREDHEADER_VER /* (uint8) Version # of the shared-header format */
+ } file_create_param_t;
+
+/* HDF boolean type */
+typedef enum {
+ BFAIL=(-1), /* error value */
+ BFALSE=0,
+ BTRUE=1
+ } hbool_t;
+
+/* Unsigned integer error value (don't really know where else to put this - QAK) */
+#define UFAIL (unsigned)(-1)
+
+#endif /* HDF5TYPE_H */
+
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..ec8bcf5
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,50 @@
+### Name of target
+TARGET = testhdf5
+
+#
+# PART 2: various choices
+#
+
+### -DDEBUG Debugging options on
+DEFS = -I../src
+
+################################################
+## no changes required below this line ##
+################################################
+
+INCL = ../src/hdf5.h testhdf5.h
+
+OBJ = testhdf5.o tmeta.o tfile.o theap.o
+
+LIBS = ../src/libhdf5.a
+
+$(TARGET): $(OBJ) $(LIBS)
+ $(CC) -o $(TARGET) $(OBJ) $(LIBS)
+
+all: $(TARGET)
+
+test: $(TARGET)
+ ./$(TARGET)
+
+debug: $(OBJ)
+ purify $(CC) -o $(TARGET) $(OBJ) $(LIBS)
+
+clean:
+ -rm -f *.o core *.core $(TARGET)
+ -rm -f *.bak *.h5
+
+###########################################################################
+
+testhdf5.o: testhdf5.c $(INCL)
+ $(CC) $(CFLAGS) $(DEFS) testhdf5.c
+
+tmeta.o: tmeta.c $(INCL)
+ $(CC) $(CFLAGS) $(DEFS) tmeta.c
+
+tfile.o: tfile.c $(INCL)
+ $(CC) $(CFLAGS) $(DEFS) tfile.c
+
+theap.o: theap.c $(INCL)
+ $(CC) $(CFLAGS) $(DEFS) theap.c
+
+
diff --git a/test/testhdf5.c b/test/testhdf5.c
new file mode 100644
index 0000000..60959fa
--- /dev/null
+++ b/test/testhdf5.c
@@ -0,0 +1,302 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+/*
+ FILE
+ testhdf5.c - HDF5 testing framework main file.
+
+ REMARKS
+ General test wrapper for HDF5 base library test programs
+
+ DESIGN
+ Each test function should be implemented as function having no
+ parameters and returning void (i.e. no return value). They should be put
+ into the list of InitTest() calls in main() below. Functions which depend
+ on other functionality should be placed below the InitTest() call for the
+ base functionality testing.
+ Each test module should include testhdf5.h and define a unique set of
+ names for test files they create.
+
+ BUGS/LIMITATIONS
+
+ EXPORTED ROUTINES/VARIABLES:
+ Two variables are exported: num_errs, and Verbosity.
+
+ */
+
+#if defined __MWERKS__
+#include <console.h>
+#endif
+
+#define MAXNUMOFTESTS 30
+#define HDF5_TEST_MASTER
+
+/* Internal Variables */
+static int Index = 0;
+
+/* ANY new test needs to have a prototype in tproto.h */
+#include "testhdf5.h"
+
+struct TestStruct
+ {
+ int NumErrors;
+ char Description[64];
+ int SkipFlag;
+ char Name[16];
+ VOID (*Call) (void);
+ }
+ Test[MAXNUMOFTESTS];
+
+static void InitTest(const char *TheName, VOID(*TheCall) (void), const char *TheDescr);
+static void usage(void);
+
+static void InitTest(const char *TheName, VOID(*TheCall) (void), const char *TheDescr)
+{
+ if (Index >= MAXNUMOFTESTS)
+ {
+ print_func("Uh-oh, too many tests added, increase MAXNUMOFTEST!\n");
+ exit(0);
+ } /* end if */
+ HDstrcpy(Test[Index].Description, TheDescr);
+ HDstrcpy(Test[Index].Name, TheName);
+ Test[Index].Call = TheCall;
+ Test[Index].NumErrors = -1;
+ Test[Index].SkipFlag = 0;
+ Index++;
+}
+
+static void usage(void)
+{
+ intn i;
+
+ print_func("Usage: testhdf5 [-v[erbose] (l[ow]|m[edium]|h[igh]|0-10)] \n");
+ print_func(" [-[e]x[clude] name+] \n");
+ print_func(" [-o[nly] name+] \n");
+ print_func(" [-b[egin] name] \n");
+ print_func(" [-s[ummary]] \n");
+ print_func(" [-c[leanoff]] \n");
+ print_func(" [-n[ocaching]] \n");
+ print_func(" [-h[elp]] \n");
+ print_func("\n\n");
+ print_func("verbose controls the amount of information displayed\n");
+ print_func("exclude to exclude tests by name\n");
+ print_func("only to name tests which should be run\n");
+ print_func("begin start at the name of the test givin\n");
+ print_func("summary prints a summary of test results at the end\n");
+ print_func("cleanoff does not delete *.hdf files after execution of tests\n");
+ print_func("nocaching do not turn on low-level DD caching\n");
+ print_func("help print out this information\n");
+ print_func("\n\n");
+ print_func("This program currently tests the following: \n\n");
+ print_func("%16s %s\n", "Name", "Description");
+ print_func("%16s %s\n", "----", "-----------");
+ for (i = 0; i < Index; i++)
+ print_func("%16s %s\n", Test[i].Name, Test[i].Description);
+ print_func("\n\n");
+} /* end usage() */
+
+/*
+ * This routine is designed to provide equivalent functionality to 'printf'
+ * and allow easy replacement for environments which don't have stdin/stdout
+ * available. (i.e. Windows & the Mac)
+ */
+int print_func(const char *format, ...)
+{
+ va_list arglist;
+ int ret_value;
+
+ va_start(arglist, format);
+ ret_value=vprintf(format, arglist);
+ va_end(arglist);
+ return(ret_value);
+}
+
+int main(int argc, char *argv[])
+{
+ int CLLoop; /* Command Line Loop */
+ int Loop, Loop1;
+ int Summary = 0;
+ int CleanUp = 1;
+ int Cache = 1;
+ uintn major, minor, release, patch;
+
+#if defined __MWERKS__
+ argc = ccommand(&argv);
+#endif
+
+#if !(defined MAC || defined __MWERKS__ || defined SYMANTEC_C)
+ /* Un-buffer the stdout and stderr */
+ setbuf(stderr, NULL);
+ setbuf(stdout, NULL);
+#endif
+
+ /* Tests are generally arranged from least to most complexity... */
+ InitTest("metadata", test_metadata, "Encode/decode metadata code");
+ InitTest("file", test_file, "Low-Level File I/O");
+ InitTest("heap", test_heap, "Object and Name Heaps");
+
+ Verbosity = 4; /* Default Verbosity is Low */
+ H5version(&major, &minor, &release, &patch);
+
+ print_func("\nFor help use: testhdf5 -help\n");
+ print_func("Built with HDF5 Library Version: %u.%ur%u, patch %u\n\n", (unsigned) major,
+ (unsigned) minor, (unsigned) release, (unsigned)patch);
+ for (CLLoop = 1; CLLoop < argc; CLLoop++)
+ {
+ if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-verbose") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-v") == 0)))
+ {
+ if (argv[CLLoop + 1][0] == 'l')
+ Verbosity = 4;
+ else if (argv[CLLoop + 1][0] == 'm')
+ Verbosity = 6;
+ else if (argv[CLLoop + 1][0] == 'h')
+ Verbosity = 10;
+ else
+ Verbosity = atoi(argv[CLLoop + 1]);
+ } /* end if */
+ if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-summary") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-s") == 0)))
+ Summary = 1;
+
+ if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-help") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-h") == 0)))
+ {
+ usage();
+ exit(0);
+ }
+
+ if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-cleanoff") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-c") == 0)))
+ CleanUp = 0;
+
+ if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-nocache") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-n") == 0)))
+ Cache = 0;
+
+ if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-exclude") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-x") == 0)))
+ {
+ Loop = CLLoop + 1;
+ while ((Loop < argc) && (argv[Loop][0] != '-'))
+ {
+ for (Loop1 = 0; Loop1 < Index; Loop1++)
+ if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
+ Test[Loop1].SkipFlag = 1;
+ Loop++;
+ } /* end while */
+ } /* end if */
+ if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-begin") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-b") == 0)))
+ {
+ Loop = CLLoop + 1;
+ while ((Loop < argc) && (argv[Loop][0] != '-'))
+ {
+ for (Loop1 = 0; Loop1 < Index; Loop1++)
+ {
+ if (HDstrcmp(argv[Loop], Test[Loop1].Name) != 0)
+ Test[Loop1].SkipFlag = 1;
+ if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
+ Loop1 = Index;
+ } /* end for */
+ Loop++;
+ } /* end while */
+ } /* end if */
+ if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-only") == 0) ||
+ (HDstrcmp(argv[CLLoop], "-o") == 0)))
+ {
+ for (Loop = 0; Loop < Index; Loop++)
+ Test[Loop].SkipFlag = 1;
+ Loop = CLLoop + 1;
+ while ((Loop < argc) && (argv[Loop][0] != '-'))
+ {
+ for (Loop1 = 0; Loop1 < Index; Loop1++)
+ if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0)
+ Test[Loop1].SkipFlag = 0;
+ Loop++;
+ } /* end while */
+ } /* end if */
+ } /* end for */
+
+#ifdef NOT_YET
+ if(Cache) /* turn on caching, unless we were instucted not to */
+ Hcache(CACHE_ALL_FILES,TRUE);
+#endif /* NOT_YET */
+
+ for (Loop = 0; Loop < Index; Loop++)
+ {
+ if (Test[Loop].SkipFlag)
+ {
+ MESSAGE(2, print_func("Skipping -- %s \n", Test[Loop].Description);
+ );
+ }
+ else
+ {
+ MESSAGE(2, print_func("Testing -- %s (%s) \n", Test[Loop].Description,
+ Test[Loop].Name);
+ );
+ MESSAGE(5, print_func("===============================================\n");
+ );
+ Test[Loop].NumErrors = num_errs;
+ (*Test[Loop].Call) ();
+ Test[Loop].NumErrors = num_errs - Test[Loop].NumErrors;
+ MESSAGE(5, print_func("===============================================\n");
+ );
+ MESSAGE(5, print_func("There were %d errors detected.\n\n", (int) Test[Loop].NumErrors);
+ );
+ } /* end else */
+ } /* end for */
+
+ MESSAGE(2, print_func("\n\n");
+ )
+ if (num_errs)
+ print_func("!!! %d Error(s) were detected !!!\n\n", (int) num_errs);
+ else
+ print_func("All tests were successful. \n\n");
+
+ if (Summary)
+ {
+ print_func("Summary of Test Results:\n");
+ print_func("Name of Test Errors Description of Test\n");
+ print_func("---------------- ------ --------------------------------------\n");
+
+ for (Loop = 0; Loop < Index; Loop++)
+ {
+ if (Test[Loop].NumErrors == -1)
+ print_func("%16s %6s %s\n", Test[Loop].Name, "N/A", Test[Loop].Description);
+ else
+ print_func("%16s %6d %s\n", Test[Loop].Name, (int) Test[Loop].NumErrors,
+ Test[Loop].Description);
+ } /* end for */
+ print_func("\n\n");
+ } /* end if */
+
+ if (CleanUp)
+ {
+ MESSAGE(2, print_func("\nCleaning Up...\n\n");
+ );
+#if !(defined DOS386 | defined WIN386)
+ system("rm -f *.hdf *.tmp");
+#else /* OLD_WAY */
+ remove("*.hdf");
+ remove("*.tmp");
+#endif /* OLD_WAY */
+ } /* end if */
+ exit(0);
+ return (0);
+} /* end main() */
diff --git a/test/testhdf5.h b/test/testhdf5.h
new file mode 100644
index 0000000..1b482d2
--- /dev/null
+++ b/test/testhdf5.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/* $Id$ */
+
+/*
+ * This header file contains information required for testing the HDF5 library.
+ */
+
+#ifndef HDF5TEST_H
+#define HDF5TEST_H
+
+/* Include required headers */
+#include "hdf5.h"
+#include <stdarg.h>
+
+/* Define these for use in all the tests */
+#ifndef HDF5_TEST_MASTER
+extern
+#endif
+int num_errs
+#ifdef HDF5_TEST_MASTER
+= 0
+#endif
+, Verbosity
+#ifdef HDF5_TEST_MASTER
+= 0
+#endif
+ ;
+
+/* Use %ld to print the value because long should cover most cases. */
+/* Used to make certain a return value _is_not_ a value */
+#define CHECK(ret, val, where) \
+do {if (Verbosity>9) print_func(" Call to routine: %15s at line %4d in %s returned %ld \n",where,(int)__LINE__,__FILE__,(long)ret);\
+if(ret == val) {print_func("*** UNEXPECTED RETURN from %s is %ld at line %4d in %s\n", where, (long)ret, (int)__LINE__,__FILE__); num_errs++;} \
+} while(0)
+
+#define CHECK_I(ret,where) { \
+ if (Verbosity>9) { \
+ print_func(" Call to routine: %15s at line %4d in %s returned %ld\n", \
+ (where), (int)__LINE__, __FILE__, (long)(ret)); \
+ if ((ret)<0) { \
+ print_func ("*** UNEXPECTED RETURN from %s is %ld line %4d in %s\n", \
+ (where), (long)(ret), (int)__LINE__, __FILE__); \
+ num_errs++; \
+ } \
+ } \
+}
+
+#define CHECK_PTR(ret,where) { \
+ if (Verbosity>9) { \
+ print_func(" Call to routine: %15s at line %4d in %s returned %p\n", \
+ (where), (int)__LINE__, __FILE__, (ret)); \
+ if (!(ret)) { \
+ print_func ("*** UNEXPECTED RETURN from %s is NULL line %4d in %s\n",\
+ (where), (int)__LINE__, __FILE__); \
+ num_errs++; \
+ } \
+ } \
+}
+
+/* Used to make certain a return value _is_ a value */
+#define VERIFY(x, val, where) \
+do {if (Verbosity>9) print_func(" Call to routine: %15s at line %4d in %s had value %ld \n",where,(int)__LINE__,__FILE__,(long)x);\
+if(x != val) {print_func("*** UNEXPECTED VALUE from %s is %ld at line %4d in %s\n", where, (long)x,(int)__LINE__,__FILE__); num_errs++;} \
+} while(0)
+
+/* Used to document process through a test and to check for errors */
+#define RESULT(ret,func) \
+do { \
+if (Verbosity>8) print_func(" Call to routine: %15s at line %4d in %s returned %ld \n",func,(int)__LINE__,__FILE__,(long)ret); \
+if (Verbosity>9) HEprint(stdout,0); \
+if(ret == FAIL) {print_func("*** UNEXPECTED RETURN from %s is %ld at line %4d in %s\n", func, (long)ret,(int)__LINE__,__FILE__); num_errs++;} \
+} while(0)
+
+/* Used to document process through a test */
+#define MESSAGE(v,a) {if (Verbosity>v) {a}}
+
+/* definitions for command strings */
+#define VERBOSITY_STR "Verbosity"
+#define SKIP_STR "Skip"
+#define TEST_STR "Test"
+#define CLEAN_STR "Cleanup"
+
+/* System command to use for Cleanup */
+#ifdef VMS
+#define CLEAN_CMD "delete *.hdf;*"
+#else
+# ifdef WIN32
+# define CLEAN_CMD "del *.hdf"
+# else
+/* default is Unix */
+# define CLEAN_CMD "rm -f *.hdf"
+# endif /* WIN32 */
+#endif /*VMS */
+
+/* Prototypes for the support routines */
+int print_func(const char *, ...);
+
+/* Prototypes for the test routines */
+void test_metadata(void);
+void test_file(void);
+void test_heap (void);
+
+#endif /* HDF5TEST_H */
+
diff --git a/test/tfile.c b/test/tfile.c
new file mode 100644
index 0000000..81c8cd2
--- /dev/null
+++ b/test/tfile.c
@@ -0,0 +1,288 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "$Revision$";
+#endif
+
+/* $Id$ */
+
+/***********************************************************
+*
+* Test program: tfile
+*
+* Test the low-level file I/O features.
+*
+*************************************************************/
+
+#include "testhdf5.h"
+
+#define F1_USERBLOCK_SIZE HDF5_USERBLOCK_DEFAULT
+#define F1_OFFSET_SIZE HDF5_OFFSETSIZE_DEFAULT
+#define F1_LENGTH_SIZE HDF5_LENGTHSIZE_DEFAULT
+#define F1_BTREEPAGE_SIZE HDF5_BTREEPAGE_DEFAULT
+#define FILE1 "tfile1.h5"
+
+#define F2_USERBLOCK_SIZE 512
+#define F2_OFFSET_SIZE 8
+#define F2_LENGTH_SIZE 8
+#define F2_BTREEPAGE_SIZE 2048
+#define FILE2 "tfile2.h5"
+
+#define F3_USERBLOCK_SIZE HDF5_USERBLOCK_DEFAULT
+#define F3_OFFSET_SIZE F2_OFFSET_SIZE
+#define F3_LENGTH_SIZE F2_LENGTH_SIZE
+#define F3_BTREEPAGE_SIZE F2_BTREEPAGE_SIZE
+#define FILE3 "tfile3.h5"
+
+/****************************************************************
+**
+** test_file_create(): Low-level file creation I/O test routine.
+**
+****************************************************************/
+static void test_file_create(void)
+{
+ hatom_t fid1,fid2,fid3; /* HDF5 File IDs */
+ hatom_t tmpl1,tmpl2; /* File creation templates */
+ uintn parm; /* File-creation parameters */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, print_func("Testing Low-Level File Creation I/O\n"););
+
+ /* Create first file */
+ fid1=H5Fcreate(FILE1,H5ACC_OVERWRITE,0,0);
+ CHECK(fid1,FAIL,"H5Fcreate");
+
+ /* Try to create first file again (should fail) */
+ fid2=H5Fcreate(FILE1,H5ACC_OVERWRITE,0,0);
+ VERIFY(fid2,FAIL,"H5Fcreate");
+
+ /* Get the file-creation template */
+ tmpl1=H5Fget_create_template(fid1);
+ CHECK(tmpl1,FAIL,"H5Fget_create_template");
+
+ /* Get the file-creation parameters */
+ ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm);
+printf("USERBLOCK_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F1_USERBLOCK_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm);
+printf("OFFSET_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F1_OFFSET_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm);
+printf("LENGTH_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F1_LENGTH_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm);
+printf("BTREE_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F1_BTREEPAGE_SIZE,"H5Cgetparm");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl1);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Double-check that the atom has been vaporized */
+ ret=H5Mrelease(tmpl1);
+ VERIFY(ret,FAIL,"H5Mrelease");
+
+ /* Create a new file with a non-standard file-creation template */
+ tmpl1=H5Mcreate(fid1,H5_TEMPLATE,NULL);
+ CHECK(tmpl1,FAIL,"H5Mcreate");
+
+ /* Set the new file-creation parameters */
+ parm=F2_USERBLOCK_SIZE;
+ ret=H5Csetparm(tmpl1,H5_USERBLOCK_SIZE,&parm);
+ CHECK(ret,FAIL,"H5Csetparm");
+
+ parm=F2_OFFSET_SIZE;
+ ret=H5Csetparm(tmpl1,H5_OFFSET_SIZE,&parm);
+ CHECK(ret,FAIL,"H5Csetparm");
+
+ parm=F2_LENGTH_SIZE;
+ ret=H5Csetparm(tmpl1,H5_LENGTH_SIZE,&parm);
+ CHECK(ret,FAIL,"H5Csetparm");
+
+ parm=F2_BTREEPAGE_SIZE;
+ ret=H5Csetparm(tmpl1,H5_BTREE_SIZE,&parm);
+ CHECK(ret,FAIL,"H5Csetparm");
+
+ /* Try to create second file, with non-standard file-creation template params */
+ fid2=H5Fcreate(FILE2,H5ACC_OVERWRITE,tmpl1,0);
+ CHECK(fid2,FAIL,"H5Fcreate");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl1);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Get the file-creation template */
+ tmpl1=H5Fget_create_template(fid2);
+ CHECK(tmpl1,FAIL,"H5Fget_create_template");
+
+ /* Get the file-creation parameters */
+ ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm);
+printf("USERBLOCK_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_USERBLOCK_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm);
+printf("OFFSET_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_LENGTH_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm);
+printf("LENGTH_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_OFFSET_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm);
+printf("BTREE_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_BTREEPAGE_SIZE,"H5Cgetparm");
+
+ /* Clone the file-creation template */
+ tmpl2=H5Mcopy(tmpl1);
+ CHECK(tmpl2,FAIL,"H5Mcopy");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl1);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Set the new file-creation parameter */
+ parm=F3_USERBLOCK_SIZE;
+ ret=H5Csetparm(tmpl2,H5_USERBLOCK_SIZE,&parm);
+ CHECK(ret,FAIL,"H5Csetparm");
+
+ /* Try to create second file, with non-standard file-creation template params */
+ fid3=H5Fcreate(FILE3,H5ACC_OVERWRITE,tmpl2,0);
+ CHECK(fid3,FAIL,"H5Fcreate");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl2);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Get the file-creation template */
+ tmpl1=H5Fget_create_template(fid3);
+ CHECK(tmpl1,FAIL,"H5Fget_create_template");
+
+ /* Get the file-creation parameters */
+ ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm);
+printf("USERBLOCK_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F3_USERBLOCK_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm);
+printf("OFFSET_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F3_LENGTH_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm);
+printf("LENGTH_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F3_OFFSET_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm);
+printf("BTREE_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F3_BTREEPAGE_SIZE,"H5Cgetparm");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl1);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Close first file */
+ ret=H5Fclose(fid1);
+ CHECK(ret,FAIL,"H5Fclose");
+
+ /* Close second file */
+ ret=H5Fclose(fid2);
+ CHECK(ret,FAIL,"H5Fclose");
+
+ /* Close third file */
+ ret=H5Fclose(fid3);
+ CHECK(ret,FAIL,"H5Fclose");
+} /* test_file_create() */
+
+
+/****************************************************************
+**
+** test_file_open(): Low-level file open I/O test routine.
+**
+****************************************************************/
+static void test_file_open(void)
+{
+ hatom_t fid1,fid2,fid3; /* HDF5 File IDs */
+ hatom_t tmpl1,tmpl2; /* File creation templates */
+ uintn parm; /* File-creation parameters */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, print_func("Testing Low-Level File Opening I/O\n"););
+
+ /* Open second file */
+ fid1=H5Fopen(FILE2,H5ACC_WRITE,0);
+ CHECK(fid1,FAIL,"H5Fooen");
+
+ /* Get the file-creation template */
+ tmpl1=H5Fget_create_template(fid1);
+ CHECK(tmpl1,FAIL,"H5Fget_create_template");
+
+ /* Get the file-creation parameters */
+ ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm);
+printf("USERBLOCK_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_USERBLOCK_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm);
+printf("OFFSET_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_OFFSET_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm);
+printf("LENGTH_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_LENGTH_SIZE,"H5Cgetparm");
+
+ ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm);
+printf("BTREE_SIZE=%u\n",parm);
+ CHECK(ret,FAIL,"H5Cgetparm");
+ VERIFY(parm,F2_BTREEPAGE_SIZE,"H5Cgetparm");
+
+ /* Release file-creation template */
+ ret=H5Mrelease(tmpl1);
+ CHECK(ret,FAIL,"H5Mrelease");
+
+ /* Close first file */
+ ret=H5Fclose(fid1);
+ CHECK(ret,FAIL,"H5Fclose");
+} /* test_file_open() */
+
+
+/****************************************************************
+**
+** test_file(): Main low-level file I/O test routine.
+**
+****************************************************************/
+void test_file(void)
+{
+ /* Output message about test being performed */
+ MESSAGE(5, print_func("Testing Low-Level File I/O\n"););
+
+ test_file_create(); /* Test file creation (also creation templates) */
+ test_file_open(); /* Test file opening */
+} /* test_file() */
+
diff --git a/test/theap.c b/test/theap.c
new file mode 100644
index 0000000..41a9cbc
--- /dev/null
+++ b/test/theap.c
@@ -0,0 +1,87 @@
+/*-------------------------------------------------------------------------
+ * Copyright (C) 1997 National Center for Supercomputing Applications.
+ * All rights reserved.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Created: theap.c
+ * Jul 17 1997
+ * Robb Matzke <robb@maya.nuance.com>
+ *
+ * Purpose:
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "testhdf5.h"
+
+#include "H5ACprivate.h"
+#include "H5Fprivate.h"
+#include "H5Hprivate.h"
+
+#define NOBJS 40
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_heap
+ *
+ * Purpose: Test name and object heaps.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * robb@maya.nuance.com
+ * Jul 17 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+test_heap (void)
+{
+ int i, j;
+ hatom_t fid;
+ hdf5_file_t *f;
+ off_t heap;
+ char buf[NOBJS+8];
+ const char *s;
+ off_t obj[NOBJS];
+
+ MESSAGE (5, print_func("Testing Heaps\n"););
+
+ /* Create the file */
+ fid = H5Fcreate ("theap.h5", H5ACC_OVERWRITE, 0, 0);
+ CHECK (fid, FAIL, "H5Fcreate");
+ f = H5Aatom_object (fid);
+ CHECK (f, NULL, "H5Aatom_object");
+
+ /* Create a new heap */
+ heap = H5H_new (f, 0);
+ CHECK_I (heap, "H5H_new");
+
+ /* Add stuff to the heap */
+ for (i=0; i<NOBJS; i++) {
+ fprintf (stderr, "%d\n", i);
+ sprintf (buf, "%03d-", i);
+ for (j=4; j<i; j++) buf[j] = '0' + j%10;
+ if (j>4) buf[j] = '\0';
+
+ obj[i] = H5H_insert (f, heap, strlen(buf)+1, buf);
+ CHECK_I (heap, "H5H_insert");
+ }
+
+ /* Flush the cache and invalidate everything */
+ H5AC_flush (f, NULL, 0, TRUE);
+
+ /* Read the objects back out */
+ for (i=0; i<NOBJS; i++) {
+ s = H5H_peek (f, heap, obj[i]);
+ print_func ("object is `%s'\n", s);
+ }
+
+ /* Close the file */
+ H5Fclose (fid);
+}
+
diff --git a/test/tmeta.c b/test/tmeta.c
new file mode 100644
index 0000000..7ef7d73
--- /dev/null
+++ b/test/tmeta.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "$Revision$";
+#endif
+
+/* $Id$ */
+
+/***********************************************************
+*
+* Test program: tmeta
+*
+* Test the basic meta-data encode/decode macros calls.
+*
+*************************************************************/
+
+#include "testhdf5.h"
+
+#define TEST_INT16_VALUE -7641
+#define TEST_UINT16_VALUE 45002
+#define TEST_INT32_VALUE -981236
+#define TEST_UINT32_VALUE 3476589
+
+uint8 compar_buffer[]={
+ /* Little-endian encoded version of the 16-bit signed integer */
+ (uint8)((TEST_INT16_VALUE)&0xff), (uint8)((TEST_INT16_VALUE>>8)&0xff),
+ /* Little-endian encoded version of the 16-bit unsigned integer */
+ (uint8)((TEST_UINT16_VALUE)&0xff), (uint8)((TEST_UINT16_VALUE>>8)&0xff),
+ /* Little-endian encoded version of the 32-bit signed integer */
+ (uint8)((TEST_INT32_VALUE)&0xff), (uint8)((TEST_INT32_VALUE>>8)&0xff),
+ (uint8)((TEST_INT32_VALUE>>16)&0xff), (uint8)((TEST_INT32_VALUE>>24)&0xff),
+ /* Little-endian encoded version of the 32-bit unsigned integer */
+ (uint8)((TEST_UINT32_VALUE)&0xff), (uint8)((TEST_UINT32_VALUE>>8)&0xff),
+ (uint8)((TEST_UINT32_VALUE>>16)&0xff), (uint8)((TEST_UINT32_VALUE>>24)&0xff),
+ };
+
+uint8 encode_buffer[sizeof(compar_buffer)];
+
+/****************************************************************
+**
+** test_metadata(): Main meta-data encode/decode testing routine.
+**
+****************************************************************/
+void test_metadata(void)
+{
+ int16 ei16=TEST_INT16_VALUE; /* variables to hold the values to encode */
+ uint16 eu16=TEST_UINT16_VALUE;
+ int32 ei32=TEST_INT32_VALUE;
+ uint32 eu32=TEST_UINT32_VALUE;
+ int16 di16; /* variables to hold the decoded values */
+ uint16 du16;
+ int32 di32;
+ uint32 du32;
+ uint8 *p; /* pointer into the buffer being en/de-coded */
+
+ /* Output message about test being performed */
+ MESSAGE(5, print_func("Testing Metadata encode/decode code\n"););
+
+ /* Start by encoding the values above */
+ p=encode_buffer;
+ INT16ENCODE(p,ei16); /* Encode the int16 value */
+ UINT16ENCODE(p,eu16); /* Encode the uint16 value */
+ INT32ENCODE(p,ei32); /* Encode the int32 value */
+ UINT32ENCODE(p,eu32); /* Encode the uint32 value */
+
+ /* Check if we got what we asked for */
+ if(HDmemcmp(encode_buffer,compar_buffer,sizeof(compar_buffer))!=0)
+ {
+ uintn u; /* local counting variable */
+
+ for(u=0; u<sizeof(compar_buffer); u++)
+ {
+ if(compar_buffer[u]!=encode_buffer[u])
+ {
+ print_func("Error encoding meta-data at offset %u, wanted: %u, got: %u\n",(unsigned)u,(unsigned)compar_buffer[u],(unsigned)encode_buffer[u]);
+ num_errs++;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
+ /* Test decoding macros */
+ p=encode_buffer;
+ INT16DECODE(p,di16); /* Decode the int16 value */
+ UINT16DECODE(p,du16); /* Decode the uint16 value */
+ INT32DECODE(p,di32); /* Decode the int32 value */
+ UINT32DECODE(p,du32); /* Decode the uint32 value */
+
+ /* Check the values decoded */
+ if(di16!=TEST_INT16_VALUE)
+ {
+ print_func("Error decoding int16 meta-data wanted: %d, got: %d\n",(int)TEST_INT16_VALUE,(int)di16);
+ num_errs++;
+ } /* end if */
+ if(du16!=TEST_UINT16_VALUE)
+ {
+ print_func("Error decoding uint16 meta-data wanted: %u, got: %u\n",(unsigned)TEST_UINT16_VALUE,(unsigned)du16);
+ num_errs++;
+ } /* end if */
+ if(di32!=TEST_INT32_VALUE)
+ {
+ print_func("Error decoding int32 meta-data wanted: %ld, got: %ld\n",(long)TEST_INT32_VALUE,(long)di32);
+ num_errs++;
+ } /* end if */
+ if(du32!=TEST_UINT32_VALUE)
+ {
+ print_func("Error decoding uint32 meta-data wanted: %lu, got: %lu\n",(unsigned long)TEST_UINT32_VALUE,(unsigned long)du32);
+ num_errs++;
+ } /* end if */
+} /* test_metadata() */
+