diff options
author | Allen Byrne <50328838+byrnHDF@users.noreply.github.com> | 2022-08-09 23:11:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-09 23:11:14 (GMT) |
commit | 4c66bf627ec4b963f026bbfa7101127271644f79 (patch) | |
tree | 4a4352a58dde0a80f7f72eab56484ddd94ec2294 /src | |
parent | fc9f31ad8c8ff4122e8bb2997e0a2bfa89cb054b (diff) | |
download | hdf5-4c66bf627ec4b963f026bbfa7101127271644f79.zip hdf5-4c66bf627ec4b963f026bbfa7101127271644f79.tar.gz hdf5-4c66bf627ec4b963f026bbfa7101127271644f79.tar.bz2 |
Merge UG from 1.10 and add prelim vol section (#1980)
* Merge UG from 1.10 and add prelim vol section
* Spelling fixes
* Merge format and autotools javadoc from 1.10
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Amodule.h | 346 | ||||
-rw-r--r-- | src/H5Dmodule.h | 2956 | ||||
-rw-r--r-- | src/H5Emodule.h | 578 | ||||
-rw-r--r-- | src/H5Epublic.h | 8 | ||||
-rw-r--r-- | src/H5FDmpio.h | 6 | ||||
-rw-r--r-- | src/H5FDsec2.h | 16 | ||||
-rw-r--r-- | src/H5FDstdio.h | 2 | ||||
-rw-r--r-- | src/H5Fmodule.h | 1443 | ||||
-rw-r--r-- | src/H5Gmodule.h | 924 | ||||
-rw-r--r-- | src/H5Gpublic.h | 10 | ||||
-rw-r--r-- | src/H5Imodule.h | 3 | ||||
-rw-r--r-- | src/H5Lmodule.h | 3 | ||||
-rw-r--r-- | src/H5Mmodule.h | 16 | ||||
-rw-r--r-- | src/H5Omodule.h | 3 | ||||
-rw-r--r-- | src/H5Opublic.h | 4 | ||||
-rw-r--r-- | src/H5PLmodule.h | 5 | ||||
-rw-r--r-- | src/H5Pmodule.h | 960 | ||||
-rw-r--r-- | src/H5Ppublic.h | 80 | ||||
-rw-r--r-- | src/H5Rmodule.h | 23 | ||||
-rw-r--r-- | src/H5Smodule.h | 1492 | ||||
-rw-r--r-- | src/H5Tmodule.h | 3832 | ||||
-rw-r--r-- | src/H5VLmodule.h | 92 | ||||
-rw-r--r-- | src/H5VLpublic.h | 2 | ||||
-rw-r--r-- | src/H5Zmodule.h | 3 | ||||
-rw-r--r-- | src/H5Zpublic.h | 2 | ||||
-rw-r--r-- | src/H5module.h | 1404 | ||||
-rw-r--r-- | src/H5private.h | 2 |
27 files changed, 14021 insertions, 194 deletions
diff --git a/src/H5Amodule.h b/src/H5Amodule.h index 9f86ddd..e3bfe6f 100644 --- a/src/H5Amodule.h +++ b/src/H5Amodule.h @@ -29,30 +29,92 @@ #define H5_MY_PKG_ERR H5E_ATTR #define H5_MY_PKG_INIT YES -/**\defgroup H5A H5A +/** \page H5A_UG HDF5 Attributes * - * Use the functions in this module to manage HDF5 attributes. + * \section sec_attribute HDF5 Attributes * - * Like HDF5 datasets, HDF5 attributes are array variables which have an element - * datatype and a shape (dataspace). However, they perform a different function: - * Attributes decorate other HDF5 objects, and are typically used to - * represent application metadata. Unlike datasets, the HDF5 library does not - * support partial I/O operations for attributes and they cannot be compressed - * or extended. + * An HDF5 attribute is a small metadata object describing the nature and/or intended usage of a primary data + * object. A primary data object may be a dataset, group, or committed datatype. * + * \subsection subsec_attribute_intro Introduction + * + * Attributes are assumed to be very small as data objects go, so storing them as standard HDF5 datasets would + * be quite inefficient. HDF5 attributes are therefore managed through a special attributes interface, + * \ref H5A, which is designed to easily attach attributes to primary data objects as small datasets + * containing metadata information and to minimize storage requirements. + * + * Consider, as examples of the simplest case, a set of laboratory readings taken under known temperature and + * pressure conditions of 18.0 degrees Celsius and 0.5 atmospheres, respectively. The temperature and pressure + * stored as attributes of the dataset could be described as the following name/value pairs: + * \li temp=18.0 + * \li pressure=0.5 + * + * While HDF5 attributes are not standard HDF5 datasets, they have much in common: + * \li An attribute has a user-defined dataspace and the included metadata has a user-assigned datatype + * \li Metadata can be of any valid HDF5 datatype + * \li Attributes are addressed by name + * + * But there are some very important differences: + * \li There is no provision for special storage such as compression or chunking + * \li There is no partial I/O or sub-setting capability for attribute data + * \li Attributes cannot be shared + * \li Attributes cannot have attributes + * \li Being small, an attribute is stored in the object header of the object it describes and is thus + * attached directly to that object + * + * \subsection subsec_error_H5A Attribute Function Summaries + * @see H5A reference manual + * + * \subsection subsec_attribute_program Programming Model for Attributes + * + * The figure below shows the UML model for an HDF5 attribute and its associated dataspace and datatype. * <table> - * <tr><th>Create</th><th>Read</th></tr> + * <tr> + * <td> + * \image html UML_Attribute.jpg "The UML model for an HDF5 attribute" + * </td> + * </tr> + * </table> + * + * Creating an attribute is similar to creating a dataset. To create an attribute, the application must + * specify the object to which the attribute is attached, the datatype and dataspace of the attribute + * data, and the attribute creation property list. + * + * The following steps are required to create and write an HDF5 attribute: + * \li Obtain the object identifier for the attribute’s primary data object + * \li Define the characteristics of the attribute and specify the attribute creation property list + * <ul> <li> Define the datatype</li> + * <li> Define the dataspace</li> + * <li> Specify the attribute creation property list</li></ul> + * \li Create the attribute + * \li Write the attribute data (optional) + * \li Close the attribute (and datatype, dataspace, and attribute creation property list, if necessary) + * \li Close the primary data object (if appropriate) + * + * The following steps are required to open and read/write an existing attribute. Since HDF5 attributes + * allow no partial I/O, you need specify only the attribute and the attribute’s memory datatype to read it: + * \li Obtain the object identifier for the attribute’s primary data object + * \li Obtain the attribute’s name or index + * \li Open the attribute + * \li Get attribute dataspace and datatype (optional) + * \li Specify the attribute’s memory type + * \li Read and/or write the attribute data + * \li Close the attribute + * \li Close the primary data object (if appropriate) + * + * <table> + * <tr><th>Create</th><th>Update</th></tr> * <tr valign="top"> * <td> * \snippet{lineno} H5A_examples.c create * </td> * <td> - * \snippet{lineno} H5A_examples.c read + * \snippet{lineno} H5A_examples.c update * </td> - * <tr><th>Update</th><th>Delete</th></tr> + * <tr><th>Read</th><th>Delete</th></tr> * <tr valign="top"> * <td> - * \snippet{lineno} H5A_examples.c update + * \snippet{lineno} H5A_examples.c read * </td> * <td> * \snippet{lineno} H5A_examples.c delete @@ -60,6 +122,266 @@ * </tr> * </table> * + * \subsection subsec_attribute_work Working with Attributes + * + * \subsubsection subsubsec_attribute_work_struct The Structure of an Attribute + * + * An attribute has two parts: name and value(s). + * + * HDF5 attributes are sometimes discussed as name/value pairs in the form name=value. + * + * An attribute’s name is a null-terminated ASCII or UTF-8 character string. Each attribute attached to an + * object has a unique name. + * + * The value portion of the attribute contains one or more data elements of the same datatype. + * + * HDF5 attributes have all the characteristics of HDF5 datasets except that there is no partial I/O + * capability. In other words, attributes can be written and read only in full with no sub-setting. + * + * \subsubsection subsubsec_attribute_work_create Creating, Writing, and Reading Attributes + * + * If attributes are used in an HDF5 file, these functions will be employed: \ref H5Acreate, \ref H5Awrite, + * and \ref H5Aread. \ref H5Acreate and \ref H5Awrite are used together to place the attribute in the file. If + * an attribute is to be used and is not currently in memory, \ref H5Aread generally comes into play + * usually in concert with one each of the H5Aget_* and H5Aopen_* functions. + * + * To create an attribute, call H5Acreate: + * \code + * hid_t H5Acreate (hid_t loc_id, const char *name, + * hid_t type_id, hid_t space_id, hid_t create_plist, + * hid_t access_plist) + * \endcode + * loc_id identifies the object (dataset, group, or committed datatype) to which the attribute is to be + * attached. name, type_id, space_id, and create_plist convey, respectively, the attribute’s name, datatype, + * dataspace, and attribute creation property list. The attribute’s name must be locally unique: it must be + * unique within the context of the object to which it is attached. + * + * \ref H5Acreate creates the attribute in memory. The attribute does not exist in the file until + * \ref H5Awrite writes it there. + * + * To write or read an attribute, call H5Awrite or H5Aread, respectively: + * \code + * herr_t H5Awrite (hid_t attr_id, hid_t mem_type_id, const void *buf) + * herr_t H5Aread (hid_t attr_id, hid_t mem_type_id, void *buf) + * \endcode + * attr_id identifies the attribute while mem_type_id identifies the in-memory datatype of the attribute data. + * + * \ref H5Awrite writes the attribute data from the buffer buf to the file. \ref H5Aread reads attribute data + * from the file into buf. + * + * The HDF5 Library converts the metadata between the in-memory datatype, mem_type_id, and the in-file + * datatype, defined when the attribute was created, without user intervention. + * + * \subsubsection subsubsec_attribute_work_access Accessing Attributes by Name or Index + * + * Attributes can be accessed by name or index value. The use of an index value makes it possible to iterate + * through all of the attributes associated with a given object. + * + * To access an attribute by its name, use the \ref H5Aopen_by_name function. \ref H5Aopen_by_name returns an + * attribute identifier that can then be used by any function that must access an attribute such as \ref + * H5Aread. Use the function \ref H5Aget_name to determine an attribute’s name. + * + * To access an attribute by its index value, use the \ref H5Aopen_by_idx function. To determine an attribute + * index value when it is not already known, use the H5Oget_info function. \ref H5Aopen_by_idx is generally + * used in the course of opening several attributes for later access. Use \ref H5Aiterate if the intent is to + * perform the same operation on every attribute attached to an object. + * + * \subsubsection subsubsec_attribute_work_info Obtaining Information Regarding an Object’s Attributes + * + * In the course of working with HDF5 attributes, one may need to obtain any of several pieces of information: + * \li An attribute name + * \li The dataspace of an attribute + * \li The datatype of an attribute + * \li The number of attributes attached to an object + * + * To obtain an attribute’s name, call H5Aget_name with an attribute identifier, attr_id: + * \code + * ssize_t H5Aget_name (hid_t attr_id, size_t buf_size, char *buf) + * \endcode + * As with other attribute functions, attr_id identifies the attribute; buf_size defines the size of the + * buffer; and buf is the buffer to which the attribute’s name will be read. + * + * If the length of the attribute name, and hence the value required for buf_size, is unknown, a first call + * to \ref H5Aget_name will return that size. If the value of buf_size used in that first call is too small, + * the name will simply be truncated in buf. A second \ref H5Aget_name call can then be used to retrieve the + * name in an appropriately-sized buffer. + * + * To determine the dataspace or datatype of an attribute, call \ref H5Aget_space or \ref H5Aget_type, + * respectively: \code hid_t H5Aget_space (hid_t attr_id) hid_t H5Aget_type (hid_t attr_id) \endcode \ref + * H5Aget_space returns the dataspace identifier for the attribute attr_id. \ref H5Aget_type returns the + * datatype identifier for the attribute attr_id. + * + * To determine the number of attributes attached to an object, use the \ref H5Oget_info function. The + * function signature is below. \code herr_t H5Oget_info( hid_t object_id, H5O_info_t *object_info ) \endcode + * The number of attributes will be returned in the object_info buffer. This is generally the preferred first + * step in determining attribute index values. If the call returns N, the attributes attached to the object + * object_id have index values of 0 through N-1. + * + * \subsubsection subsubsec_attribute_work_iterate Iterating across an Object’s Attributes + * + * It is sometimes useful to be able to perform the identical operation across all of the attributes attached + * to an object. At the simplest level, you might just want to open each attribute. At a higher level, you + * might wish to perform a rather complex operation on each attribute as you iterate across the set. + * + * To iterate an operation across the attributes attached to an object, one must make a series of calls to + * \ref H5Aiterate + * \code + * herr_t H5Aiterate (hid_t obj_id, H5_index_t index_type, + * H5_iter_order_t order, hsize_t *n, H5A_operator2_t op, + * void *op_data) + * \endcode + * \ref H5Aiterate successively marches across all of the attributes attached to the object specified in + * loc_id, performing the operation(s) specified in op_func with the data specified in op_data on each + * attribute. + * + * When \ref H5Aiterate is called, index contains the index of the attribute to be accessed in this call. When + * \ref H5Aiterate returns, index will contain the index of the next attribute. If the returned index is the + * null pointer, then all attributes have been processed, and the iterative process is complete. + * + * op_func is a user-defined operation that adheres to the \ref H5A_operator_t prototype. This prototype and + * certain requirements imposed on the operator’s behavior are described in the \ref H5Aiterate entry in the + * \ref RM. + * + * op_data is also user-defined to meet the requirements of op_func. Beyond providing a parameter with which + * to pass this data, HDF5 provides no tools for its management and imposes no restrictions. + * + * \subsubsection subsubsec_attribute_work_delete Deleting an Attribute + * + * Once an attribute has outlived its usefulness or is no longer appropriate, it may become necessary to + * delete it. + * + * To delete an attribute, call \ref H5Adelete + * \code + * herr_t H5Adelete (hid_t loc_id, const char *name) + * \endcode + * \ref H5Adelete removes the attribute name from the group, dataset, or committed datatype specified in + * loc_id. + * + * \ref H5Adelete must not be called if there are any open attribute identifiers on the object loc_id. Such a + * call can cause the internal attribute indexes to change; future writes to an open attribute would then + * produce unintended results. + * + * \subsubsection subsubsec_attribute_work_close Closing an Attribute + * + * As is the case with all HDF5 objects, once access to an attribute it is no longer needed, that attribute + * must be closed. It is best practice to close it as soon as practicable; it is mandatory that it be closed + * prior to the H5close call closing the HDF5 Library. + * + * To close an attribute, call \ref H5Aclose + * \code + * herr_t H5Aclose (hid_t attr_id) + * \endcode + * \ref H5Aclose closes the specified attribute by terminating access to its identifier, attr_id. + * + * \subsection subsec_attribute_special Special Issues + * + * Some special issues for attributes are discussed below. + * + * <h4>Large Numbers of Attributes Stored in Dense Attribute Storage</h4> + * + * The dense attribute storage scheme was added in version 1.8 so that datasets, groups, and committed + * datatypes that have large numbers of attributes could be processed more quickly. + * + * Attributes start out being stored in an object's header. This is known as compact storage. For more + * information, see "Storage Strategies." + * + * As the number of attributes grows, attribute-related performance slows. To improve performance, dense + * attribute storage can be initiated with the H5Pset_attr_phase_change function. See the HDF5 Reference + * Manual for more information. + * + * When dense attribute storage is enabled, a threshold is defined for the number of attributes kept in + * compact storage. When the number is exceeded, the library moves all of the attributes into dense storage + * at another location. The library handles the movement of attributes and the pointers between the locations + * automatically. If some of the attributes are deleted so that the number falls below the threshold, then + * the attributes are moved back to compact storage by the library. + * + * The improvements in performance from using dense attribute storage are the result of holding attributes + * in a heap and indexing the heap with a B-tree. + * + * Note that there are some disadvantages to using dense attribute storage. One is that this is a new feature. + * Datasets, groups, and committed datatypes that use dense storage cannot be read by applications built with + * earlier versions of the library. Another disadvantage is that attributes in dense storage cannot be + * compressed. + * + * <h4>Large Attributes Stored in Dense Attribute Storage</h4> + * + * We generally consider the maximum size of an attribute to be 64K bytes. The library has two ways of storing + * attributes larger than 64K bytes: in dense attribute storage or in a separate dataset. Using dense + * attribute storage is described in this section, and storing in a separate dataset is described in the next + * section. + * + * To use dense attribute storage to store large attributes, set the number of attributes that will be stored + * in compact storage to 0 with the H5Pset_attr_phase_change function. This will force all attributes to be + * put into dense attribute storage and will avoid the 64KB size limitation for a single attribute in compact + * attribute storage. + * + * The example code below illustrates how to create a large attribute that will be kept in dense storage. + * + * <table> + * <tr><th>Create</th></tr> + * <tr valign="top"> + * <td> + * \snippet{lineno} H5A_examples.c create + * </td> + * </tr> + * </table> + * + * <h4>Large Attributes Stored in a Separate Dataset</h4> + * + * In addition to dense attribute storage (see above), a large attribute can be stored in a separate dataset. + * In the figure below, DatasetA holds an attribute that is too large for the object header in Dataset1. By + * putting a pointer to DatasetA as an attribute in Dataset1, the attribute becomes available to those + * working with Dataset1. + * This way of handling large attributes can be used in situations where backward compatibility is important + * and where compression is important. Applications built with versions before 1.8.x can read large + * attributes stored in separate datasets. Datasets can be compressed while attributes cannot. + * <table> + * <tr> + * <td> + * \image html Shared_Attribute.jpg "A large or shared HDF5 attribute and its associated dataset(s)" + * </td> + * </tr> + * </table> + * Note: In the figure above, DatasetA is an attribute of Dataset1 that is too large to store in Dataset1's + * header. DatasetA is associated with Dataset1 by means of an object reference pointer attached as an + * attribute to Dataset1. The attribute in DatasetA can be shared among multiple datasets by means of + * additional object reference pointers attached to additional datasets. + * + * <h4>Shared Attributes</h4> + * + * Attributes written and managed through the \ref H5A interface cannot be shared. If shared attributes are + * required, they must be handled in the manner described above for large attributes and illustrated in + * the figure above. + * + * <h4>Attribute Names</h4> + * + * While any ASCII or UTF-8 character may be used in the name given to an attribute, it is usually wise + * to avoid the following kinds of characters: + * \li Commonly used separators or delimiters such as slash, backslash, colon, and semi-colon (\, /, :, ;) + * \li Escape characters + * \li Wild cards such as asterisk and question mark (*, ?) + * NULL can be used within a name, but HDF5 names are terminated with a NULL: whatever comes after the NULL + * will be ignored by HDF5. + * + * The use of ASCII or UTF-8 characters is determined by the character encoding property. See + * #H5Pset_char_encoding in the \ref RM. + * + * <h4>No Special I/O or Storage</h4> + * + * HDF5 attributes have all the characteristics of HDF5 datasets except the following: + * \li Attributes are written and read only in full: there is no provision for partial I/O or sub-setting + * \li No special storage capability is provided for attributes: there is no compression or chunking, and + * attributes are not extendable + * + * Previous Chapter \ref sec_dataspace - Next Chapter \ref sec_error + * + * \defgroup H5A Attributes (H5A) + * + * An HDF5 attribute is a small metadata object describing the nature and/or intended usage of a primary data + * object. A primary data object may be a dataset, group, or committed datatype. + * + * @see sec_attribute + * */ #endif /* H5Amodule_H */ diff --git a/src/H5Dmodule.h b/src/H5Dmodule.h index 596fd48..4ad3709 100644 --- a/src/H5Dmodule.h +++ b/src/H5Dmodule.h @@ -29,7 +29,2961 @@ #define H5_MY_PKG_ERR H5E_DATASET #define H5_MY_PKG_INIT YES -/**\defgroup H5D H5D +/** \page H5D_UG HDF5 Datasets + * + * \section sec_dataset HDF5 Datasets + * + * \subsection subsec_dataset_intro Introduction + * + * An HDF5 dataset is an object composed of a collection of data elements, or raw data, and + * metadata that stores a description of the data elements, data layout, and all other information + * necessary to write, read, and interpret the stored data. From the viewpoint of the application the + * raw data is stored as a one-dimensional or multi-dimensional array of elements (the raw data), + * those elements can be any of several numerical or character types, small arrays, or even + * compound types similar to C structs. The dataset object may have attribute objects. See the + * figure below. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig1.gif "Application view of a dataset" + * </td> + * </tr> + * </table> + * + * A dataset object is stored in a file in two parts: a header and a data array. The header contains + * information that is needed to interpret the array portion of the dataset, as well as metadata (or + * pointers to metadata) that describes or annotates the dataset. Header information includes the + * name of the object, its dimensionality, its number-type, information about how the data itself is + * stored on disk (the storage layout), and other information used by the library to speed up access + * to the dataset or maintain the file’s integrity. + * + * The HDF5 dataset interface, comprising the @ref H5D functions, provides a mechanism for managing + * HDF5 datasets including the transfer of data between memory and disk and the description of + * dataset properties. + * + * A dataset is used by other HDF5 APIs, either by name or by an identifier. For more information, + * \see \ref api-compat-macros. + * + * \subsubsection subsubsec_dataset_intro_link Link/Unlink + * A dataset can be added to a group with one of the H5Lcreate calls, and deleted from a group with + * #H5Ldelete. The link and unlink operations use the name of an object, which may be a dataset. + * The dataset does not have to open to be linked or unlinked. + * + * \subsubsection subsubsec_dataset_intro_obj Object Reference + * A dataset may be the target of an object reference. The object reference is created by + * #H5Rcreate with the name of an object which may be a dataset and the reference type + * #H5R_OBJECT. The dataset does not have to be open to create a reference to it. + * + * An object reference may also refer to a region (selection) of a dataset. The reference is created + * with #H5Rcreate and a reference type of #H5R_DATASET_REGION. + * + * An object reference can be accessed by a call to #H5Rdereference. When the reference is to a + * dataset or dataset region, the #H5Rdereference call returns an identifier to the dataset just as if + * #H5Dopen has been called. + * + * \subsubsection subsubsec_dataset_intro_attr Adding Attributes + * A dataset may have user-defined attributes which are created with #H5Acreate and accessed + * through the @ref H5A API. To create an attribute for a dataset, the dataset must be open, and the + * identifier is passed to #H5Acreate. The attributes of a dataset are discovered and opened using + * #H5Aopen_name, #H5Aopen_idx, or #H5Aiterate; these functions use the identifier of the dataset. + * An attribute can be deleted with #H5Adelete which also uses the identifier of the dataset. + * + * \subsection subsec_dataset_function Dataset Function Summaries + * Functions that can be used with datasets (@ref H5D functions) and property list functions that can + * used with datasets (@ref H5P functions) are listed below. + * + * <table> + * <caption>Dataset functions</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Dcreate</td> + * <td>Creates a dataset at the specified location. The + * C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Dcreate_anon</td> + * <td>Creates a dataset in a file without linking it into the file structure.</td> + * </tr> + * <tr> + * <td>#H5Dopen</td> + * <td>Opens an existing dataset. The C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Dclose</td> + * <td>Closes the specified dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_space</td> + * <td>Returns an identifier for a copy of the dataspace for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_space_status</td> + * <td>Determines whether space has been allocated for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_type</td> + * <td>Returns an identifier for a copy of the datatype for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_create_plist</td> + * <td>Returns an identifier for a copy of the dataset creation property list for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_access_plist</td> + * <td>Returns the dataset access property list associated with a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dget_offset</td> + * <td>Returns the dataset address in a file.</td> + * </tr> + * <tr> + * <td>#H5Dget_storage_size</td> + * <td>Returns the amount of storage required for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Dvlen_get_buf_size</td> + * <td>Determines the number of bytes required to store variable-length (VL) data.</td> + * </tr> + * <tr> + * <td>#H5Dvlen_reclaim</td> + * <td>Reclaims VL datatype memory buffers.</td> + * </tr> + * <tr> + * <td>#H5Dread</td> + * <td>Reads raw data from a dataset into a buffer.</td> + * </tr> + * <tr> + * <td>#H5Dwrite</td> + * <td>Writes raw data from a buffer to a dataset.</td> + * </tr> + * <tr> + * <td>#H5Diterate</td> + * <td>Iterates over all selected elements in a dataspace.</td> + * </tr> + * <tr> + * <td>#H5Dgather</td> + * <td>Gathers data from a selection within a memory buffer.</td> + * </tr> + * <tr> + * <td>#H5Dscatter</td> + * <td>Scatters data into a selection within a memory buffer.</td> + * </tr> + * <tr> + * <td>#H5Dfill</td> + * <td>Fills dataspace elements with a fill value in a memory buffer.</td> + * </tr> + * <tr> + * <td>#H5Dset_extent</td> + * <td>Changes the sizes of a dataset’s dimensions.</td> + * </tr> + * </table> + * + * <table> + * <caption>Dataset creation property list functions (H5P)</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_layout</td> + * <td>Sets the type of storage used to store the raw data for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_layout</td> + * <td>Returns the layout of the raw data for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pset_chunk</td> + * <td>Sets the size of the chunks used to store a chunked layout dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_chunk</td> + * <td>Retrieves the size of chunks for the raw data of a chunked layout dataset.</td> + * </tr> + * <tr> + * <td>#H5Pset_deflate</td> + * <td>Sets compression method and compression level.</td> + * </tr> + * <tr> + * <td>#H5Pset_fill_value</td> + * <td>Sets the fill value for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_fill_value</td> + * <td>Retrieves a dataset fill value.</td> + * </tr> + * <tr> + * <td>#H5Pfill_value_defined</td> + * <td>Determines whether the fill value is defined.</td> + * </tr> + * <tr> + * <td>#H5Pset_fill_time</td> + * <td>Sets the time when fill values are written to a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_fill_time</td> + * <td>Retrieves the time when fill value are written to a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pset_alloc_time</td> + * <td>Sets the timing for storage space allocation.</td> + * </tr> + * <tr> + * <td>#H5Pget_alloc_time</td> + * <td>Retrieves the timing for storage space allocation.</td> + * </tr> + * <tr> + * <td>#H5Pset_filter</td> + * <td>Adds a filter to the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pall_filters_avail</td> + * <td>Verifies that all required filters are available.</td> + * </tr> + * <tr> + * <td>#H5Pget_nfilters</td> + * <td>Returns the number of filters in the pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pget_filter</td> + * <td>Returns information about a filter in a pipeline. + * The C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Pget_filter_by_id</td> + * <td>Returns information about the specified filter. + * The C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Pmodify_filter</td> + * <td>Modifies a filter in the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Premove_filter</td> + * <td>Deletes one or more filters in the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pset_fletcher32</td> + * <td>Sets up use of the Fletcher32 checksum filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_nbit</td> + * <td>Sets up use of the n-bit filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_scaleoffset</td> + * <td>Sets up use of the scale-offset filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_shuffle</td> + * <td>Sets up use of the shuffle filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_szip</td> + * <td>Sets up use of the Szip compression filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_external</td> + * <td>Adds an external file to the list of external files.</td> + * </tr> + * <tr> + * <td>#H5Pget_external_count</td> + * <td>Returns the number of external files for a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_external</td> + * <td>Returns information about an external file.</td> + * </tr> + * <tr> + * <td>#H5Pset_char_encoding</td> + * <td>Sets the character encoding used to encode a string. Use to set ASCII or UTF-8 character + * encoding for object names.</td> + * </tr> + * <tr> + * <td>#H5Pget_char_encoding</td> + * <td>Retrieves the character encoding used to create a string.</td> + * </tr> + * </table> + * + * <table> + * <caption>Dataset access property list functions (H5P)</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_buffer</td> + * <td>Sets type conversion and background buffers.</td> + * </tr> + * <tr> + * <td>#H5Pget_buffer</td> + * <td>Reads buffer settings.</td> + * </tr> + * <tr> + * <td>#H5Pset_chunk_cache</td> + * <td>Sets the raw data chunk cache parameters.</td> + * </tr> + * <tr> + * <td>#H5Pget_chunk_cache</td> + * <td>Retrieves the raw data chunk cache parameters.</td> + * </tr> + * <tr> + * <td>#H5Pset_edc_check</td> + * <td>Sets whether to enable error-detection when reading a dataset.</td> + * </tr> + * <tr> + * <td>#H5Pget_edc_check</td> + * <td>Determines whether error-detection is enabled for dataset reads.</td> + * </tr> + * <tr> + * <td>#H5Pset_filter_callback</td> + * <td>Sets user-defined filter callback function.</td> + * </tr> + * <tr> + * <td>#H5Pset_data_transform</td> + * <td>Sets a data transform expression.</td> + * </tr> + * <tr> + * <td>#H5Pget_data_transform</td> + * <td>Retrieves a data transform expression.</td> + * </tr> + * <tr> + * <td>#H5Pset_type_conv_cb</td> + * <td>Sets user-defined datatype conversion callback function.</td> + * </tr> + * <tr> + * <td>#H5Pget_type_conv_cb</td> + * <td>Gets user-defined datatype conversion callback function.</td> + * </tr> + * <tr> + * <td>#H5Pset_hyper_vector_size</td> + * <td>Sets number of I/O vectors to be read/written in hyperslab I/O.</td> + * </tr> + * <tr> + * <td>#H5Pget_hyper_vector_size</td> + * <td>Retrieves number of I/O vectors to be read/written in hyperslab I/O.</td> + * </tr> + * <tr> + * <td>#H5Pset_btree_ratios</td> + * <td>Sets B-tree split ratios for a dataset transfer property list.</td> + * </tr> + * <tr> + * <td>#H5Pget_btree_ratios</td> + * <td>Gets B-tree split ratios for a dataset transfer property list.</td> + * </tr> + * <tr> + * <td>#H5Pset_vlen_mem_manager</td> + * <td>Sets the memory manager for variable-length datatype allocation in #H5Dread and + * #H5Dvlen_reclaim.</td> + * </tr> + * <tr> + * <td>#H5Pget_vlen_mem_manager</td> + * <td>Gets the memory manager for variable-length datatype allocation in #H5Dread and + * #H5Dvlen_reclaim.</td> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio</td> + * <td>Sets data transfer mode.</td> + * </tr> + * <tr> + * <td>#H5Pget_dxpl_mpio</td> + * <td>Returns the data transfer mode.</td> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio_chunk_opt</td> + * <td>Sets a flag specifying linked-chunk I/O or multi-chunk I/O.</td> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio_chunk_opt_num</td> + * <td>Sets a numeric threshold for linked-chunk I/O.</td> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio_chunk_opt_ratio</td> + * <td>Sets a ratio threshold for collective I/O.</td> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio_collective_opt</td> + * <td>Sets a flag governing the use of independent versus collective I/O.</td> + * </tr> + * <tr> + * <td>#H5Pset_multi_type</td> + * <td>Sets the type of data property for the MULTI driver.</td> + * </tr> + * <tr> + * <td>#H5Pget_multi_type</td> + * <td>Retrieves the type of data property for the MULTI driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_small_data_block_size</td> + * <td>Sets the size of a contiguous block reserved for small data.</td> + * </tr> + * <tr> + * <td>#H5Pget_small_data_block_size</td> + * <td>Retrieves the current small data block size setting.</td> + * </tr> + * </table> + * + * \subsection subsec_dataset_program Programming Model for Datasets + * This section explains the programming model for datasets. + * + * \subsubsection subsubsec_dataset_program_general General Model + * + * The programming model for using a dataset has three main phases: + * \li Obtain access to the dataset + * \li Operate on the dataset using the dataset identifier returned at access + * \li Release the dataset + * + * These three phases or steps are described in more detail below the figure. + * + * A dataset may be opened several times and operations performed with several different + * identifiers to the same dataset. All the operations affect the dataset although the calling program + * must synchronize if necessary to serialize accesses. + * + * Note that the dataset remains open until every identifier is closed. The figure below shows the + * basic sequence of operations. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig2.gif "Dataset programming sequence" + * </td> + * </tr> + * </table> + * + * Creation and data access operations may have optional parameters which are set with property + * lists. The general programming model is: + * \li Create property list of appropriate class (dataset create, dataset transfer) + * \li Set properties as needed; each type of property has its own format and datatype + * \li Pass the property list as a parameter of the API call + * + * The steps below describe the programming phases or steps for using a dataset. + * <h4>Step 1. Obtain Access</h4> + * A new dataset is created by a call to #H5Dcreate. If successful, the call returns an identifier for the + * newly created dataset. + * + * Access to an existing dataset is obtained by a call to #H5Dopen. This call returns an identifier for + * the existing dataset. + * + * An object reference may be dereferenced to obtain an identifier to the dataset it points to. + * + * In each of these cases, the successful call returns an identifier to the dataset. The identifier is + * used in subsequent operations until the dataset is closed. + * + * <h4>Step 2. Operate on the Dataset</h4> + * The dataset identifier can be used to write and read data to the dataset, to query and set + * properties, and to perform other operations such as adding attributes, linking in groups, and + * creating references. + * + * The dataset identifier can be used for any number of operations until the dataset is closed. + * + * <h4>Step 3. Close the Dataset</h4> + * When all operations are completed, the dataset identifier should be closed with a call to + * #H5Dclose. This releases the dataset. + * + * After the identifier is closed, it cannot be used for further operations. + * + * \subsubsection subsubsec_dataset_program_create Create Dataset + * + * A dataset is created and initialized with a call to #H5Dcreate. The dataset create operation sets + * permanent properties of the dataset: + * \li Name + * \li Dataspace + * \li Datatype + * \li Storage properties + * + * These properties cannot be changed for the life of the dataset, although the dataspace may be + * expanded up to its maximum dimensions. + * + * <h4>Name</h4> + * A dataset name is a sequence of alphanumeric ASCII characters. The full name would include a + * tracing of the group hierarchy from the root group of the file. An example is + * /rootGroup/groupA/subgroup23/dataset1. The local name or relative name within the lowest- + * level group containing the dataset would include none of the group hierarchy. An example is + * Dataset1. + * + * <h4>Dataspace</h4> + * The dataspace of a dataset defines the number of dimensions and the size of each dimension. The + * dataspace defines the number of dimensions, and the maximum dimension sizes and current size + * of each dimension. The maximum dimension size can be a fixed value or the constant + * #H5S_UNLIMITED, in which case the actual dimension size can be changed with calls to + * #H5Dset_extent, up to the maximum set with the maxdims parameter in the #H5Screate_simple + * call that established the dataset’s original dimensions. The maximum dimension size is set when + * the dataset is created and cannot be changed. + * + * <h4>Datatype</h4> + * Raw data has a datatype which describes the layout of the raw data stored in the file. The + * datatype is set when the dataset is created and can never be changed. When data is transferred to + * and from the dataset, the HDF5 library will assure that the data is transformed to and from the + * stored format. + * + * <h4>Storage Properties</h4> + * Storage properties of the dataset are set when it is created. The required inputs table below shows + * the categories of storage properties. The storage properties cannot be changed after the dataset is + * created. + * + * <h4>Filters</h4> + * When a dataset is created, optional filters are specified. The filters are added to the data transfer + * pipeline when data is read or written. The standard library includes filters to implement + * compression, data shuffling, and error detection code. Additional user-defined filters may also be + * used. + * + * The required filters are stored as part of the dataset, and the list may not be changed after the + * dataset is created. The HDF5 library automatically applies the filters whenever data is + * transferred. + * + * <h4>Summary</h4> + * + * A newly created dataset has no attributes and no data values. The dimensions, datatype, storage + * properties, and selected filters are set. The table below lists the required inputs, and the second + * table below lists the optional inputs. + * + * <table> + * <caption>Required inputs</caption> + * <tr> + * <th>Required Inputs</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Dataspace</td> + * <td>The shape of the array.</td> + * </tr> + * <tr> + * <td>Datatype</td> + * <td>The layout of the stored elements.</td> + * </tr> + * <tr> + * <td>Name</td> + * <td>The name of the dataset in the group.</td> + * </tr> + * </table> + * + * <table> + * <caption>Optional inputs</caption> + * <tr> + * <th>Optional Inputs</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Storage Layout</td> + * <td>How the data is organized in the file including chunking.</td> + * </tr> + * <tr> + * <td>Fill Value</td> + * <td>The behavior and value for uninitialized data.</td> + * </tr> + * <tr> + * <td>External Storage</td> + * <td>Option to store the raw data in an external file.</td> + * </tr> + * <tr> + * <td>Filters</td> + * <td>Select optional filters to be applied. One of the filters that might be applied is compression.</td> + * </tr> + * </table> + * + * <h4>Example</h4> + * To create a new dataset, go through the following general steps: + * \li Set dataset characteristics (optional where default settings are acceptable) + * \li Datatype + * \li Dataspace + * \li Dataset creation property list + * \li Create the dataset + * \li Close the datatype, dataspace, and property list (as necessary) + * \li Close the dataset + * + * Example 1 below shows example code to create an empty dataset. The dataspace is 7 x 8, and the + * datatype is a big-endian integer. The dataset is created with the name “dset1” and is a member of + * the root group, “/”. + * + * <em> Example 1. Create an empty dataset</em> + * \code + * hid_t dataset, datatype, dataspace; + * + * // Create dataspace: Describe the size of the array and create the dataspace for fixed-size dataset. + * dimsf[0] = 7; + * dimsf[1] = 8; + * dataspace = H5Screate_simple(2, dimsf, NULL); + * + * // Define datatype for the data in the file. + * // For this example, store little-endian integer numbers. + * datatype = H5Tcopy(H5T_NATIVE_INT); + * status = H5Tset_order(datatype, H5T_ORDER_LE); + * + * // Create a new dataset within the file using defined + * // dataspace and datatype. No properties are set. + * dataset = H5Dcreate(file, "/dset", datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * H5Dclose(dataset); + * H5Sclose(dataspace); + * H5Tclose(datatype); + * \endcode + * + * Example 2, below, shows example code to create a similar dataset with a fill value of ‘-1’. This + * code has the same steps as in the example above, but uses a non-default property list. A file + * creation property list is created, and then the fill value is set to the desired value. Then the + * property list is passed to the #H5Dcreate call. + * + * <em> Example 2. Create a dataset with fill value set</em> + * \code + * hid_t plist; // property list + * hid_t dataset, datatype, dataspace; + * int fillval = -1; + * + * dimsf[0] = 7; + * dimsf[1] = 8; + * dataspace = H5Screate_simple(2, dimsf, NULL); + * datatype = H5Tcopy(H5T_NATIVE_INT); + * status = H5Tset_order(datatype, H5T_ORDER_LE); + * + * // Example of Dataset Creation property list: set fill value to '-1' + * plist = H5Pcreate(H5P_DATASET_CREATE); + * status = H5Pset_fill_value(plist, datatype, &fillval); + * + * // Same as above, but use the property list + * dataset = H5Dcreate(file, "/dset", datatype, dataspace, H5P_DEFAULT, plist, H5P_DEFAULT); + * H5Dclose(dataset); + * H5Sclose(dataspace); + * H5Tclose(datatype); + * H5Pclose(plist); + * \endcode + * + * After this code is executed, the dataset has been created and written to the file. The data array is + * uninitialized. Depending on the storage strategy and fill value options that have been selected, + * some or all of the space may be allocated in the file, and fill values may be written in the file. + * + * \subsubsection subsubsec_dataset_program_transfer Data Transfer Operations on a Dataset + * Data is transferred between memory and the raw data array of the dataset through #H5Dwrite and + * #H5Dread operations. A data transfer has the following basic steps: + * \li 1. Allocate and initialize memory space as needed + * \li 2. Define the datatype of the memory elements + * \li 3. Define the elements to be transferred (a selection, or all the elements) + * \li 4. Set data transfer properties (including parameters for filters or file drivers) as needed + * \li 5. Call the @ref H5D API + * + * Note that the location of the data in the file, the datatype of the data in the file, the storage + * properties, and the filters do not need to be specified because these are stored as a permanent part + * of the dataset. A selection of elements from the dataspace is specified; the selected elements may + * be the whole dataspace. + * + * The following figure shows a diagram of a write operation which + * transfers a data array from memory to a dataset in the file (usually on disk). A read operation has + * similar parameters with the data flowing the other direction. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig3.gif "A write operation" + * </td> + * </tr> + * </table> + * + * <h4>Memory Space</h4> + * The calling program must allocate sufficient memory to store the data elements to be transferred. + * For a write (from memory to the file), the memory must be initialized with the data to be written + * to the file. For a read, the memory must be large enough to store the elements that will be read. + * The amount of storage needed can be computed from the memory datatype (which defines the + * size of each data element) and the number of elements in the selection. + * + * <h4>Memory Datatype</h4> + * The memory layout of a single data element is specified by the memory datatype. This specifies + * the size, alignment, and byte order of the element as well as the datatype class. Note that the + * memory datatype must be the same datatype class as the file, but may have different byte order + * and other properties. The HDF5 Library automatically transforms data elements between the + * source and destination layouts. For more information, \ref sec_datatype. + * + * For a write, the memory datatype defines the layout of the data to be written; an example is IEEE + * floating-point numbers in native byte order. If the file datatype (defined when the dataset is + * created) is different but compatible, the HDF5 Library will transform each data element when it + * is written. For example, if the file byte order is different than the native byte order, the HDF5 + * library will swap the bytes. + * + * For a read, the memory datatype defines the desired layout of the data to be read. This must be + * compatible with the file datatype, but should generally use native formats such as byte orders. + * The HDF5 library will transform each data element as it is read. + * + * <h4>Selection</h4> + * The data transfer will transfer some or all of the elements of the dataset depending on the + * dataspace selection. The selection has two dataspace objects: one for the source, and one for the + * destination. These objects describe which elements of the dataspace to be transferred. Some + * (partial I/O) or all of the data may be transferred. Partial I/O is defined by defining hyperslabs or + * lists of elements in a dataspace object. + * + * The dataspace selection for the source defines the indices of the elements to be read or written. + * The two selections must define the same number of points, but the order and layout may be + * different. The HDF5 Library automatically selects and distributes the elements according to the + * selections. It might, for example, perform a scatter-gather or sub-set of the data. + * + * <h4>Data Transfer Properties</h4> + * For some data transfers, additional parameters should be set using the transfer property list. The + * table below lists the categories of transfer properties. These properties set parameters for the + * HDF5 Library and may be used to pass parameters for optional filters and file drivers. For + * example, transfer properties are used to select independent or collective operation when using + * MPI-I/O. + * + * <table> + * <caption>Categories of transfer properties</caption> + * <tr> + * <th>Properties</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Library parameters</td> + * <td>Internal caches, buffers, B-Trees, etc.</td> + * </tr> + * <tr> + * <td>Memory management</td> + * <td>Variable-length memory management, data overwrite</td> + * </tr> + * <tr> + * <td>File driver management</td> + * <td>Parameters for file drivers</td> + * </tr> + * <tr> + * <td>Filter management</td> + * <td>Parameters for filters</td> + * </tr> + * </table> + * + * <h4>Data Transfer Operation (Read or Write)</h4> + * The data transfer is done by calling #H5Dread or #H5Dwrite with the parameters described above. + * The HDF5 Library constructs the required pipeline, which will scatter-gather, transform + * datatypes, apply the requested filters, and use the correct file driver. + * + * During the data transfer, the transformations and filters are applied to each element of the data in + * the required order until all the data is transferred. + * + * <h4>Summary</h4> + * To perform a data transfer, it is necessary to allocate and initialize memory, describe the source + * and destination, set required and optional transfer properties, and call the \ref H5D API. + * + * <h4>Examples</h4> + * The basic procedure to write to a dataset is the following: + * \li Open the dataset. + * \li Set the dataset dataspace for the write (optional if dataspace is #H5S_ALL). + * \li Write data. + * \li Close the datatype, dataspace, and property list (as necessary). + * \li Close the dataset. + * + * Example 3 below shows example code to write a 4 x 6 array of integers. In the example, the data + * is initialized in the memory array dset_data. The dataset has already been created in the file, so it + * is opened with H5Dopen. + * + * The data is written with #H5Dwrite. The arguments are the dataset identifier, the memory + * datatype (#H5T_NATIVE_INT), the memory and file selections (#H5S_ALL in this case: the + * whole array), and the default (empty) property list. The last argument is the data to be + * transferred. + * + * <em> Example 3. Write an array of integers</em> + * \code + * hid_t file_id, dataset_id; // identifiers + * herr_t status; + * int i, j, dset_data[4][6]; + * + * // Initialize the dataset. + * for (i = 0; i < 4; i++) + * for (j = 0; j < 6; j++) + * dset_data[i][j] = i * 6 + j + 1; + * + * // Open an existing file. + * file_id = H5Fopen("dset.h5", H5F_ACC_RDWR, H5P_DEFAULT); + * + * // Open an existing dataset. + * dataset_id = H5Dopen(file_id, "/dset", H5P_DEFAULT); + * + * // Write the entire dataset, using 'dset_data': memory type is 'native int' + * // write the entire dataspace to the entire dataspace, no transfer properties + * status = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset_data); + * + * status = H5Dclose(dataset_id); + * \endcode + * + * Example 4 below shows a similar write except for setting a non-default value for the transfer + * buffer. The code is the same as Example 3, but a transfer property list is created, and the desired + * buffer size is set. The #H5Dwrite function has the same arguments, but uses the property list to set + * the buffer. + * + * <em> Example 4. Write an array using a property list</em> + * \code + * hid_t file_id, dataset_id; + * hid_t xferplist; + * herr_t status; + * int i, j, dset_data[4][6]; + * + * file_id = H5Fopen("dset.h5", H5F_ACC_RDWR, H5P_DEFAULT); + * dataset_id = H5Dopen(file_id, "/dset", H5P_DEFAULT); + * + * // Example: set type conversion buffer to 64MB + * xferplist = H5Pcreate(H5P_DATASET_XFER); + * status = H5Pset_buffer( xferplist, 64 * 1024 *1024, NULL, NULL); + * + * // Write the entire dataset, using 'dset_data': memory type is 'native int' + * write the entire dataspace to the entire dataspace, set the buffer size with the property list + * status = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, xferplist, dset_data); + * + * status = H5Dclose(dataset_id); + * \endcode + * + * The basic procedure to read from a dataset is the following: + * \li Define the memory dataspace of the read (optional if dataspace is #H5S_ALL). + * \li Open the dataset. + * \li Get the dataset dataspace (if using #H5S_ALL above). + * + * Else define dataset dataspace of read. + * \li Define the memory datatype (optional). + * \li Define the memory buffer. + * \li Open the dataset. + * \li Read data. + * \li Close the datatype, dataspace, and property list (as necessary). + * \li Close the dataset. + * + * The example below shows code that reads a 4 x 6 array of integers from a dataset called “dset1”. + * First, the dataset is opened. The #H5Dread call has parameters: + * \li The dataset identifier (from #H5Dopen) + * \li The memory datatype (#H5T_NATIVE_INT) + * \li The memory and file dataspace (#H5S_ALL, the whole array) + * \li A default (empty) property list + * \li The memory to be filled + * + * <em> Example 5. Read an array from a dataset</em> + * \code + * hid_t file_id, dataset_id; + * herr_t status; + * int i, j, dset_data[4][6]; + * + * // Open an existing file. + * file_id = H5Fopen("dset.h5", H5F_ACC_RDWR, H5P_DEFAULT); + * + * // Open an existing dataset. + * dataset_id = H5Dopen(file_id, "/dset", H5P_DEFAULT); + * + * // read the entire dataset, into 'dset_data': memory type is 'native int' + * // read the entire dataspace to the entire dataspace, no transfer properties, + * status = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset_data); + * + * status = H5Dclose(dataset_id); + * \endcode + * + * \subsubsection subsubsec_dataset_program_read Retrieve the Properties of a Dataset + * The functions listed below allow the user to retrieve information regarding a dataset including + * the datatype, the dataspace, the dataset creation property list, and the total stored size of the data. + * + * <table> + * <caption>Retrieve dataset information</caption> + * <tr> + * <th>Query Function</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>H5Dget_space</td> + * <td>Retrieve the dataspace of the dataset as stored in the file.</td> + * </tr> + * <tr> + * <td>H5Dget_type</td> + * <td>Retrieve the datatype of the dataset as stored in the file.</td> + * </tr> + * <tr> + * <td>H5Dget_create_plist</td> + * <td>Retrieve the dataset creation properties.</td> + * </tr> + * <tr> + * <td>H5Dget_storage_size</td> + * <td>Retrieve the total bytes for all the data of the dataset.</td> + * </tr> + * <tr> + * <td>H5Dvlen_get_buf_size</td> + * <td>Retrieve the total bytes for all the variable-length data of the dataset.</td> + * </tr> + * </table> + * + * The example below illustrates how to retrieve dataset information. + * + * <em> Example 6. Retrieve dataset</em> + * \code + * hid_t file_id, dataset_id; + * hid_t dspace_id, dtype_id, plist_id; + * herr_t status; + * + * // Open an existing file. + * file_id = H5Fopen("dset.h5", H5F_ACC_RDWR, H5P_DEFAULT); + * + * // Open an existing dataset. + * dataset_id = H5Dopen(file_id, "/dset", H5P_DEFAULT); + * dspace_id = H5Dget_space(dataset_id); + * dtype_id = H5Dget_type(dataset_id); + * plist_id = H5Dget_create_plist(dataset_id); + * + * // use the objects to discover the properties of the dataset + * status = H5Dclose(dataset_id); + * \endcode + * + * \subsection subsec_dataset_transfer Data Transfer + * The HDF5 library implements data transfers through a pipeline which implements data + * transformations (according to the datatype and selections), chunking (as requested), and I/O + * operations using different mechanisms (file drivers). The pipeline is automatically configured by + * the HDF5 library. Metadata is stored in the file so that the correct pipeline can be constructed to + * retrieve the data. In addition, optional filters such as compression may be added to the standard + * pipeline. + * + * The figure below illustrates data layouts for different layers of an application using HDF5. The + * application data is organized as a multidimensional array of elements. The HDF5 format + * specification defines the stored layout of the data and metadata. The storage layout properties + * define the organization of the abstract data. This data is written to and read from some storage + * medium. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig4.gif "Data layouts in an application" + * </td> + * </tr> + * </table> + * + * The last stage of a write (and first stage of a read) is managed by an HDF5 file driver module. + * The virtual file layer of the HDF5 Library implements a standard interface to alternative I/O + * methods, including memory (AKA “core”) files, single serial file I/O, multiple file I/O, and + * parallel I/O. The file driver maps a simple abstract HDF5 file to the specific access methods. + * + * The raw data of an HDF5 dataset is conceived to be a multidimensional array of data elements. + * This array may be stored in the file according to several storage strategies: + * \li Contiguous + * \li Chunked + * \li Compact + * + * The storage strategy does not affect data access methods except that certain operations may be + * more or less efficient depending on the storage strategy and the access patterns. + * + * Overall, the data transfer operations (#H5Dread and #H5Dwrite) work identically for any storage + * method, for any file driver, and for any filters and transformations. The HDF5 library + * automatically manages the data transfer process. In some cases, transfer properties should or + * must be used to pass additional parameters such as MPI/IO directives when using the parallel file + * driver. + * + * \subsubsection subsubsec_dataset_transfer_pipe The Data Pipeline + * When data is written or read to or from an HDF5 file, the HDF5 library passes the data through a + * sequence of processing steps which are known as the HDF5 data pipeline. This data pipeline + * performs operations on the data in memory such as byte swapping, alignment, scatter-gather, and + * hyperslab selections. The HDF5 library automatically determines which operations are needed + * and manages the organization of memory operations such as extracting selected elements from a + * data block. The data pipeline modules operate on data buffers: each module processes a buffer + * and passes the transformed buffer to the next stage. + * + * The table below lists the stages of the data pipeline. The figure below the table shows the order + * of processing during a read or write. + * + * <table> + * <caption>Stages of the data pipeline</caption> + * <tr> + * <th>Layers</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>I/O initiation</td> + * <td>Initiation of HDF5 I/O activities (#H5Dwrite and #H5Dread) in a user’s application program.</td> + * </tr> + * <tr> + * <td>Memory hyperslab operation</td> + * <td>Data is scattered to (for read), or gathered from (for write) the application’s memory buffer + * (bypassed if no datatype conversion is needed).</td> + * </tr> + * <tr> + * <td>Datatype conversion</td> + * <td>Datatype is converted if it is different between memory and storage (bypassed if no datatype + * conversion is needed).</td> + * </tr> + * <tr> + * <td>File hyperslab operation</td> + * <td>Data is gathered from (for read), or scattered to (for write) to file space in memory (bypassed + * if no datatype conversion is needed).</td> + * </tr> + * <tr> + * <td>Filter pipeline</td> + * <td>Data is processed by filters when it passes. Data can be modified and restored here (bypassed + * if no datatype conversion is needed, no filter is enabled, or dataset is not chunked).</td> + * </tr> + * <tr> + * <td>Virtual File Layer</td> + * <td>Facilitate easy plug-in file drivers such as MPIO or POSIX I/O.</td> + * </tr> + * <tr> + * <td>Actual I/O</td> + * <td>Actual file driver used by the library such as MPIO or STDIO.</td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig5.gif "The processing order in the data pipeline" + * </td> + * </tr> + * </table> + * + * The HDF5 library automatically applies the stages as needed. + * + * When the memory dataspace selection is other than the whole dataspace, the memory hyperslab + * stage scatters/gathers the data elements between the application memory (described by the + * selection) and a contiguous memory buffer for the pipeline. On a write, this is a gather operation; + * on a read, this is a scatter operation. + * + * When the memory datatype is different from the file datatype, the datatype conversion stage + * transforms each data element. For example, if data is written from 32-bit big-endian memory, + * and the file datatype is 32-bit little-endian, the datatype conversion stage will swap the bytes of + * every element. Similarly, when data is read from the file to native memory, byte swapping will + * be applied automatically when needed. + * + * The file hyperslab stage is similar to the memory hyperslab stage, but is managing the + * arrangement of the elements according to the dataspace selection. When data is read, data + * elements are gathered from the data blocks from the file to fill the contiguous buffers which are + * then processed by the pipeline. When data is read, the elements from a buffer are scattered to the + * data blocks of the file. + * + * \subsubsection subsubsec_dataset_transfer_filter Data Pipeline Filters + * In addition to the standard pipeline, optional stages, called filters, can be inserted in the pipeline. + * The standard distribution includes optional filters to implement compression and error checking. + * User applications may add custom filters as well. + * + * The HDF5 library distribution includes or employs several optional filters. These are listed in the + * table below. The filters are applied in the pipeline between the virtual file layer and the file + * hyperslab operation. See the figure above. The application can use any number of filters in any + * order. + * + * <table> + * <caption>Data pipeline filters</caption> + * <tr> + * <th>Filter</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>gzip compression</td> + * <td>Data compression using zlib.</td> + * </tr> + * <tr> + * <td>Szip compression</td> + * <td>Data compression using the Szip library. See The HDF Group website for more information + * regarding the Szip filter.</td> + * </tr> + * <tr> + * <td>N-bit compression</td> + * <td>Data compression using an algorithm specialized for n-bit datatypes.</td> + * </tr> + * <tr> + * <td>Scale-offset compression</td> + * <td>Data compression using a “scale and offset” algorithm.</td> + * </tr> + * <tr> + * <td>Shuffling</td> + * <td>To improve compression performance, data is regrouped by its byte position in the data + * unit. In other words, the 1st, 2nd, 3rd, and 4th bytes of integers are stored together + * respectively.</td> + * </tr> + * <tr> + * <td>Fletcher32</td> + * <td>Fletcher32 checksum for error-detection.</td> + * </tr> + * </table> + * + * Filters may be used only for chunked data and are applied to chunks of data between the file + * hyperslab stage and the virtual file layer. At this stage in the pipeline, the data is organized as + * fixed-size blocks of elements, and the filter stage processes each chunk separately. + * + * Filters are selected by dataset creation properties, and some behavior may be controlled by data + * transfer properties. The library determines what filters must be applied and applies them in the + * order in which they were set by the application. That is, if an application calls + * #H5Pset_shuffle and then #H5Pset_deflate when creating a dataset’s creation property list, the + * library will apply the shuffle filter first and then the deflate filter. + * + * For more information, + * \li @see @ref subsubsec_dataset_filters_nbit + * \li @see @ref subsubsec_dataset_filters_scale + * + * \subsubsection subsubsec_dataset_transfer_drive File Drivers + * I/O is performed by the HDF5 virtual file layer. The file driver interface writes and reads blocks + * of data; each driver module implements the interface using different I/O mechanisms. The table + * below lists the file drivers currently supported. Note that the I/O mechanisms are separated from + * the pipeline processing: the pipeline and filter operations are identical no matter what data access + * mechanism is used. + * + * <table> + * <caption>I/O file drivers</caption> + * <tr> + * <th>File Driver</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>#H5FD_CORE</td> + * <td>Store in memory (optional backing store to disk file).</td> + * </tr> + * <tr> + * <td>#H5FD_FAMILY</td> + * <td>Store in a set of files.</td> + * </tr> + * <tr> + * <td>#H5FD_LOG</td> + * <td>Store in logging file.</td> + * </tr> + * <tr> + * <td>#H5FD_MPIO</td> + * <td>Store using MPI/IO.</td> + * </tr> + * <tr> + * <td>#H5FD_MULTI</td> + * <td>Store in multiple files. There are several options to control layout.</td> + * </tr> + * <tr> + * <td>#H5FD_SEC2</td> + * <td>Serial I/O to file using Unix “section 2” functions.</td> + * </tr> + * <tr> + * <td>#H5FD_STDIO</td> + * <td>Serial I/O to file using Unix “stdio” functions.</td> + * </tr> + * </table> + * + * Each file driver writes/reads contiguous blocks of bytes from a logically contiguous address + * space. The file driver is responsible for managing the details of the different physical storage + * methods. + * + * In serial environments, everything above the virtual file layer tends to work identically no matter + * what storage method is used. + * + * Some options may have substantially different performance depending on the file driver that is + * used. In particular, multi-file and parallel I/O may perform considerably differently from serial + * drivers depending on chunking and other settings. + * + * \subsubsection subsubsec_dataset_transfer_props Data Transfer Properties to Manage the Pipeline + * Data transfer properties set optional parameters that control parts of the data pipeline. The + * function listing below shows transfer properties that control the behavior of the library. + * + * <table> + * <caption>Data transfer property list functions</caption> + * <tr> + * <th>C Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_buffer</td> + * <td>Maximum size for the type conversion buffer and the background buffer. May also supply + * pointers to application-allocated buffers.</td> + * </tr> + * <tr> + * <td>#H5Pset_hyper_vector_size</td> + * <td>set the number of "I/O vectors" (offset and length pairs) which are to be + * accumulated in memory before being issued to the lower levels + * of the library for reading or writing the actual data.</td> + * </tr> + * <tr> + * <td>#H5Pset_btree_ratios</td> + * <td>Set the B-tree split ratios for a dataset transfer property list. The split ratios determine + * what percent of children go in the first node when a node splits.</td> + * </tr> + * </table> + * + * Some filters and file drivers require or use additional parameters from the application program. + * These can be passed in the data transfer property list. The table below shows file driver property + * list functions. + * + * <table> + * <caption>File driver property list functions</caption> + * <tr> + * <th>C Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_dxpl_mpio</td> + * <td>Control the MPI I/O transfer mode (independent or collective) during data I/O operations.</td> + * </tr> + * <tr> + * <td>#H5Pset_small_data_block_size</td> + * <td>Reserves blocks of size bytes for the contiguous storage of the raw data portion of small + * datasets. The HDF5 Library then writes the raw data from small datasets to this reserved space + * which reduces unnecessary discontinuities within blocks of metadata and improves + * I/O performance.</td> + * </tr> + * <tr> + * <td>#H5Pset_edc_check</td> + * <td>Disable/enable EDC checking for read. When selected, EDC is always written.</td> + * </tr> + * </table> + * + * The transfer properties are set in a property list which is passed as a parameter of the #H5Dread or + * #H5Dwrite call. The transfer properties are passed to each pipeline stage. Each stage may use or + * ignore any property in the list. In short, there is one property list that contains all the properties. + * + * \subsubsection subsubsec_dataset_transfer_store Storage Strategies + * The raw data is conceptually a multi-dimensional array of elements that is stored as a contiguous + * array of bytes. The data may be physically stored in the file in several ways. The table below lists + * the storage strategies for a dataset. + * + * <table> + * <caption> Dataset storage strategies</caption> + * <tr> + * <th>Storage Strategy</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Contiguous</td> + * <td>The dataset is stored as one continuous array of bytes.</td> + * </tr> + * <tr> + * <td>Chunked </td> + * <td>The dataset is stored as fixed-size chunks.</td> + * </tr> + * <tr> + * <td>Compact</td> + * <td>A small dataset is stored in the metadata header.</td> + * </tr> + * </table> + * + * The different storage strategies do not affect the data transfer operations of the dataset: reads and + * writes work the same for any storage strategy. + * + * These strategies are described in the following sections. + * + * <h4>Contiguous</h4> + * A contiguous dataset is stored in the file as a header and a single continuous array of bytes. See + * the figure below. In the case of a multi-dimensional array, the data is serialized in row major order. By + * default, data is stored contiguously. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig6.gif "Contiguous data storage" + * </td> + * </tr> + * </table> + * + * Contiguous storage is the simplest model. It has several limitations. First, the dataset must be a + * fixed-size: it is not possible to extend the limit of the dataset or to have unlimited dimensions. In + * other words, if the number of dimensions of the array might change over time, then chunking + * storage must be used instead of contiguous. Second, because data is passed through the pipeline + * as fixed-size blocks, compression and other filters cannot be used with contiguous data. + * + * <h4>Chunked</h4> + * The data of a dataset may be stored as fixed-size chunks. A chunk is a hyper- + * rectangle of any shape. When a dataset is chunked, each chunk is read or written as a single I/O + * operation, and individually passed from stage to stage of the data pipeline. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig7.gif "Chunked data storage" + * </td> + * </tr> + * </table> + * + * Chunks may be any size and shape that fits in the dataspace of the dataset. For example, a three + * dimensional dataspace can be chunked as 3-D cubes, 2-D planes, or 1-D lines. The chunks may + * extend beyond the size of the dataspace. For example, a 3 x 3 dataset might by chunked in 2 x 2 + * chunks. Sufficient chunks will be allocated to store the array, and any extra space will not be + * accessible. So, to store the 3 x 3 array, four 2 x 2 chunks would be allocated with 5 unused + * elements stored. + * + * Chunked datasets can be unlimited in any direction and can be compressed or filtered. + * + * Since the data is read or written by chunks, chunking can have a dramatic effect on performance + * by optimizing what is read and written. Note, too, that for specific access patterns such as + * parallel I/O, decomposition into chunks can have a large impact on performance. + * + * Two restrictions have been placed on chunk shape and size: + * <ul><li> The rank of a chunk must be less than or equal to the rank of the dataset</li> + * <li> Chunk size cannot exceed the size of a fixed-size dataset; for example, a dataset consisting of + * a 5 x 4 fixed-size array cannot be defined with 10 x 10 chunks</li></ul> + * + * <h4>Compact</h4> + * For contiguous and chunked storage, the dataset header information and data are stored in two + * (or more) blocks. Therefore, at least two I/O operations are required to access the data: one to + * access the header, and one (or more) to access data. For a small dataset, this is considerable + * overhead. + * + * A small dataset may be stored in a continuous array of bytes in the header block using the + * compact storage option. This dataset can be read entirely in one operation which retrieves the + * header and data. The dataset must fit in the header. This may vary depending on the metadata + * that is stored. In general, a compact dataset should be approximately 30 KB or less total size. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig8.gif "Compact data storage" + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_dataset_transfer_partial Partial I/O Sub‐setting and Hyperslabs + * Data transfers can write or read some of the data elements of the dataset. This is controlled by + * specifying two selections: one for the source and one for the destination. Selections are specified + * by creating a dataspace with selections. + * + * Selections may be a union of hyperslabs or a list of points. A hyperslab is a contiguous hyper- + * rectangle from the dataspace. Selected fields of a compound datatype may be read or written. In + * this case, the selection is controlled by the memory and file datatypes. + * + * Summary of procedure: + * \li 1. Open the dataset + * \li 2. Define the memory datatype + * \li 3. Define the memory dataspace selection and file dataspace selection + * \li 4. Transfer data (#H5Dread or #H5Dwrite) + * + * For more information, + * @see @ref sec_dataspace + * + * \subsection subsec_dataset_allocation Allocation of Space in the File + * When a dataset is created, space is allocated in the file for its header and initial data. The amount +of space allocated when the dataset is created depends on the storage properties. When the +dataset is modified (data is written, attributes added, or other changes), additional storage may be +allocated if necessary. + * + * <table> + * <caption>Initial dataset size</caption> + * <tr> + * <th>Object</th> + * <th>Size</th> + * </tr> + * <tr> + * <td>Header</td> + * <td>Variable, but typically around 256 bytes at the creation of a simple dataset with a simple + * datatype.</td> + * </tr> + * <tr> + * <td>Data</td> + * <td>Size of the data array (number of elements x size of element). Space allocated in + * the file depends on the storage strategy and the allocation strategy.</td> + * </tr> + * </table> + * + * <h4>Header</h4> + * A dataset header consists of one or more header messages containing persistent metadata + * describing various aspects of the dataset. These records are defined in the HDF5 File Format + * Specification. The amount of storage required for the metadata depends on the metadata to be + * stored. The table below summarizes the metadata. + * + * <table> + * <caption>Metadata storage sizes</caption> + * <tr> + * <th>Header Information</th> + * <th>Approximate Storage Size</th> + * </tr> + * <tr> + * <td>Datatype (required)</td> + * <td>Bytes or more. Depends on type.</td> + * </tr> + * <tr> + * <td>Dataspace (required)</td> + * <td>Bytes or more. Depends on number of dimensions and hsize_t.</td> + * </tr> + * <tr> + * <td>Layout (required)</td> + * <td>Points to the stored data. Bytes or more. Depends on hsize_t and number of dimensions.</td> + * </tr> + * <tr> + * <td>Filters</td> + * <td>Depends on the number of filters. The size of the filter message depends on the name and + * data that will be passed.</td> + * </tr> + * </table> + * + * The header blocks also store the name and values of attributes, so the total storage depends on + * the number and size of the attributes. + * + * In addition, the dataset must have at least one link, including a name, which is stored in the file + * and in the group it is linked from. + * + * The different storage strategies determine when and how much space is allocated for the data + * array. See the discussion of fill values below for a detailed explanation of the storage allocation. + * + * <h4>Contiguous Storage</h4> + * For a continuous storage option, the data is stored in a single, contiguous block in the file. The + * data is nominally a fixed-size, (number of elements x size of element). The figure below shows + * an example of a two dimensional array stored as a contiguous dataset. + * + * Depending on the fill value properties, the space may be allocated when the dataset is created or + * when first written (default), and filled with fill values if specified. For parallel I/O, by default the + * space is allocated when the dataset is created. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig9.gif "A two dimensional array stored as a contiguous dataset" + * </td> + * </tr> + * </table> + * + * <h4>Chunked Storage</h4> + * For chunked storage, the data is stored in one or more chunks. Each chunk is a continuous block + * in the file, but chunks are not necessarily stored contiguously. Each chunk has the same size. The + * data array has the same nominal size as a contiguous array (number of elements x size of + * element), but the storage is allocated in chunks, so the total size in the file can be larger than the + * nominal size of the array. See the figure below. + * + * If a fill value is defined, each chunk will be filled with the fill value. Chunks must be allocated + * when data is written, but they may be allocated when the file is created, as the file expands, or + * when data is written. + * + * For serial I/O, by default chunks are allocated incrementally, as data is written to the chunk. For + * a sparse dataset, chunks are allocated only for the parts of the dataset that are written. In this + * case, if the dataset is extended, no storage is allocated. + * + * For parallel I/O, by default chunks are allocated when the dataset is created or extended with fill + * values written to the chunk. + * + * In either case, the default can be changed using fill value properties. For example, using serial + * I/O, the properties can select to allocate chunks when the dataset is created. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig10.gif "A two dimensional array stored in chunks" + * </td> + * </tr> + * </table> + * + * <h4>Changing Dataset Dimensions</h4> + * #H5Dset_extent is used to change the current dimensions of the dataset within the limits of the + * dataspace. Each dimension can be extended up to its maximum or unlimited. Extending the + * dataspace may or may not allocate space in the file and may or may not write fill values, if they + * are defined. See the example code below. + * + * The dimensions of the dataset can also be reduced. If the sizes specified are smaller than the + * dataset’s current dimension sizes, #H5Dset_extent will reduce the dataset’s dimension sizes to the + * specified values. It is the user’s responsibility to ensure that valuable data is not lost; + * #H5Dset_extent does not check. + * + * <em>Using #H5Dset_extent to increase the size of a dataset</em> + * \code + * hid_t file_id, dataset_id; + * herr_t status; + * size_t newdims[2]; + * + * // Open an existing file. + * file_id = H5Fopen("dset.h5", H5F_ACC_RDWR, H5P_DEFAULT); + * + * // Open an existing dataset. + * dataset_id = H5Dopen(file_id, "/dset", H5P_DEFAULT); + * + * // Example: dataset is 2 x 3, each dimension is UNLIMITED + * // extend to 2 x 7 + * newdims[0] = 2; + * newdims[1] = 7; + * status = H5Dset_extent(dataset_id, newdims); + * + * // dataset is now 2 x 7 + * + * status = H5Dclose(dataset_id); + * \endcode + * + * \subsubsection subsubsec_dataset_allocation_store Storage Allocation in the File: Early, Incremental, Late + * The HDF5 Library implements several strategies for when storage is allocated if and when it is + * filled with fill values for elements not yet written by the user. Different strategies are + * recommended for different storage layouts and file drivers. In particular, a parallel program + * needs storage allocated during a collective call (for example, create or extend), while serial + * programs may benefit from delaying the allocation until the data is written. + * + * Two file creation properties control when to allocate space, when to write the fill value, and the + * actual fill value to write. + * + * <h4>When to Allocate Space</h4> + * The table below shows the options for when data is allocated in the file. Early allocation is done + * during the dataset create call. Certain file drivers (especially MPI-I/O and MPI-POSIX) require + * space to be allocated when a dataset is created, so all processors will have the correct view of the + * data. + * + * <table> + * <caption>File storage allocation options</caption> + * <tr> + * <th>Strategy</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Early</td> + * <td>Allocate storage for the dataset immediately when the dataset is created.</td> + * </tr> + * <tr> + * <td>Late</td> + * <td>Defer allocating space for storing the dataset until the dataset is written.</td> + * </tr> + * <tr> + * <td>Incremental</td> + * <td>Defer allocating space for storing each chunk until the chunk is written.</td> + * </tr> + * <tr> + * <td>Default</td> + * <td>Use the strategy (Early, Late, or Incremental) for the storage method and + * access method. This is the recommended strategy.</td> + * </tr> + * </table> + * + * Late allocation is done at the time of the first write to dataset. Space for the whole dataset is + * allocated at the first write. + * + * Incremental allocation (chunks only) is done at the time of the first write to the chunk. Chunks + * that have never been written are not allocated in the file. In a sparsely populated dataset, this + * option allocates chunks only where data is actually written. + * + * The “Default” property selects the option recommended as appropriate for the storage method + * and access method. The defaults are shown in the table below. Note that Early allocation is + * recommended for all Parallel I/O, while other options are recommended as the default for serial + * I/O cases. + * + * <table> + * <caption>Default storage options</caption> + * <tr> + * <th>Storage Type</th> + * <th>Serial I/O</th> + * <th>Parallel I/O</th> + * </tr> + * <tr> + * <td>Contiguous</td> + * <td>Late</td> + * <td>Early</td> + * </tr> + * <tr> + * <td>Chunked</td> + * <td>Incremental</td> + * <td>Early</td> + * </tr> + * <tr> + * <td>Compact</td> + * <td>Early</td> + * <td>Early</td> + * </tr> + * </table> + * + * <h4>When to Write the Fill Value</h4> + * The second property is when to write the fill value. The possible values are “Never” and + * “Allocation”. The table below shows these options. + * + * <table> + * <caption>When to write fill values</caption> + * <tr> + * <th>When</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Never</td> + * <td>Fill value will never be written.</td> + * </tr> + * <tr> + * <td>Allocation</td> + * <td>Fill value is written when space is allocated. (Default for chunked and contiguous + * data storage.)</td> + * </tr> + * </table> + * + * <h4>What Fill Value to Write</h4> + * The third property is the fill value to write. The table below shows the values. By default, the + * data is filled with zeros. The application may choose no fill value (Undefined). In this case, + * uninitialized data may have random values. The application may define a fill value of an + * appropriate type. For more information, @see @ref subsec_datatype_fill. + * + * <table> + * <caption>Fill values to write</caption> + * <tr> + * <th>What to Write</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>Default</td> + * <td>By default, the library fills allocated space with zeros.</td> + * </tr> + * <tr> + * <td>Undefined</td> + * <td>Allocated space is filled with random values.</td> + * </tr> + * <tr> + * <td>User-defined</td> + * <td>The application specifies the fill value.</td> + * </tr> + * </table> + * + * Together these three properties control the library’s behavior. The table below summarizes the + * possibilities during the dataset create-write-close cycle. + * + * <table> + * <caption>Storage allocation and fill summary</caption> + * <tr> + * <th>When to allocate space</th> + * <th>When to write fill value</th> + * <th>What fill value to write</th> + * <th>Library create-write-close behavior</th> + * </tr> + * <tr> + * <td>Early</td> + * <td>Never</td> + * <td>-</td> + * <td>Library allocates space when dataset is created, but never writes a fill value to dataset. A read + * of unwritten data returns undefined values.</td> + * </tr> + * <tr> + * <td>Late</td> + * <td>Never</td> + * <td>-</td> + * <td>Library allocates space when dataset is written to, but never writes a fill value to the dataset. A + * read of unwritten data returns undefined values.</td> + * </tr> + * <tr> + * <td>Incremental</td> + * <td>Never</td> + * <td>-</td> + * <td>Library allocates space when a dataset or chunk (whichever is the smallest unit of space) + * is written to, but it never writes a fill value to a dataset or a chunk. A read of unwritten data + * returns undefined values.</td> + * </tr> + * <tr> + * <td>-</td> + * <td>Allocation</td> + * <td>Undefined</td> + * <td>Error on creating the dataset. The dataset is not created.</td> + * </tr> + * <tr> + * <td>Early</td> + * <td>Allocation</td> + * <td>Default or User-defined</td> + * <td>Allocate space for the dataset when the dataset is created. Write the fill value (default or + * user-defined) to the entire dataset when the dataset is created.</td> + * </tr> + * <tr> + * <td>Late</td> + * <td>Allocation</td> + * <td>Default or User-define</td> + * <td>Allocate space for the dataset when the application first writes data values to the dataset. + * Write the fill value to the entire dataset before writing application data values.</td> + * </tr> + * <tr> + * <td>Incremental</td> + * <td>Allocation</td> + * <td>Default or User-define</td> + * <td>Allocate space for the dataset when the application first writes data values to the dataset or + * chunk (whichever is the smallest unit of space). Write the fill value to the entire dataset + * or chunk before writing application data values.</td> + * </tr> + * </table> + * + * During the #H5Dread function call, the library behavior depends on whether space has been + * allocated, whether the fill value has been written to storage, how the fill value is defined, and + * when to write the fill value. The table below summarizes the different behaviors. + * + * <table> + * <caption>H5Dread summary</caption> + * <tr> + * <th>Is space allocated in the file?</th> + * <th>What is the fill value?</th> + * <th>When to write the fill value?</th> + * <th>Library read behavior</th> + * </tr> + * <tr> + * <td>No</td> + * <td>Undefined</td> + * <td>anytime</td> + * <td>Error. Cannot create this dataset.</td> + * </tr> + * <tr> + * <td>No</td> + * <td>Default or User-define</td> + * <td>anytime</td> + * <td>Fill the memory buffer with the fill value.</td> + * </tr> + * <tr> + * <td>Yes</td> + * <td>Undefined</td> + * <td>anytime</td> + * <td>Return data from storage (dataset). Trash is possible if the application has not written data + * to the portion of the dataset being read.</td> + * </tr> + * <tr> + * <td>Yes</td> + * <td>Default or User-define</td> + * <td>Never</td> + * <td>Return data from storage (dataset). Trash is possible if the application has not written data + * to the portion of the dataset being read.</td> + * </tr> + * <tr> + * <td>Yes</td> + * <td>Default or User-define</td> + * <td>Allocation</td> + * <td>Return data from storage (dataset).</td> + * </tr> + * </table> + * + * There are two cases to consider depending on whether the space in the file has been allocated + * before the read or not. When space has not yet been allocated and if a fill value is defined, the + * memory buffer will be filled with the fill values and returned. In other words, no data has been + * read from the disk. If space has been allocated, the values are returned from the stored data. The + * unwritten elements will be filled according to the fill value. + * + * \subsubsection subsubsec_dataset_allocation_delete Deleting a Dataset from a File and Reclaiming Space + * HDF5 does not at this time provide an easy mechanism to remove a dataset from a file or to + * reclaim the storage space occupied by a deleted object. + * + * Removing a dataset and reclaiming the space it used can be done with the #H5Ldelete function + * and the h5repack utility program. With the H5Ldelete function, links to a dataset can be removed + * from the file structure. After all the links have been removed, the dataset becomes inaccessible to + * any application and is effectively removed from the file. The way to recover the space occupied + * by an unlinked dataset is to write all of the objects of the file into a new file. Any unlinked object + * is inaccessible to the application and will not be included in the new file. Writing objects to a + * new file can be done with a custom program or with the h5repack utility program. + * + * For more information, @see @ref sec_group + * + * \subsubsection subsubsec_dataset_allocation_release Releasing Memory Resources + * The system resources required for HDF5 objects such as datasets, datatypes, and dataspaces + * should be released once access to the object is no longer needed. This is accomplished via the + * appropriate close function. This is not unique to datasets but a general requirement when + * working with the HDF5 Library; failure to close objects will result in resource leaks. + * + * In the case where a dataset is created or data has been transferred, there are several objects that + * must be closed. These objects include datasets, datatypes, dataspaces, and property lists. + * + * The application program must free any memory variables and buffers it allocates. When + * accessing data from the file, the amount of memory required can be determined by calculating + * the size of the memory datatype and the number of elements in the memory selection. + * + * Variable-length data are organized in two or more areas of memory. For more information, + * \see \ref h4_vlen_datatype "Variable-length Datatypes". + * + * When writing data, the application creates an array of + * vl_info_t which contains pointers to the elements. The elements might be, for example, strings. + * In the file, the variable-length data is stored in two parts: a heap with the variable-length values + * of the data elements and an array of vl_info_t elements. When the data is read, the amount of + * memory required for the heap can be determined with the #H5Dvlen_get_buf_size call. + * + * The data transfer property may be used to set a custom memory manager for allocating variable- + * length data for a #H5Dread. This is set with the #H5Pset_vlen_mem_manager call. + * To free the memory for variable-length data, it is necessary to visit each element, free the + * variable-length data, and reset the element. The application must free the memory it has + * allocated. For memory allocated by the HDF5 Library during a read, the #H5Dvlen_reclaim + * function can be used to perform this operation. + * + * \subsubsection subsubsec_dataset_allocation_ext External Storage Properties + * The external storage format allows data to be stored across a set of non-HDF5 files. A set of + * segments (offsets and sizes) in one or more files is defined as an external file list, or EFL, and + * the contiguous logical addresses of the data storage are mapped onto these segments. Currently, + * only the #H5D_CONTIGUOUS storage format allows external storage. External storage is + * enabled by a dataset creation property. The table below shows the API. + * + * <table> + * <caption>External storage API</caption> + * <tr> + * <th>Function</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>#H5Pset_external</td> + * <td>This function adds a new segment to the end of the external file list of the specified dataset + * creation property list. The segment begins a byte offset of file name and continues for size + * bytes. The space represented by this segment is adjacent to the space already represented by + * the external file list. The last segment in a file list may have the size #H5F_UNLIMITED, in + * which case the external file may be of unlimited size and no more files can be added to the + * external files list.</td> + * </tr> + * <tr> + * <td>#H5Pget_external_count</td> + * <td>Calling this function returns the number of segments in an external file list. If the dataset + * creation property list has no external data, then zero is returned.</td> + * </tr> + * <tr> + * <td>#H5Pget_external</td> + * <td>This is the counterpart for the #H5Pset_external function. Given a dataset creation + * property list and a zero-based index into that list, the file name, byte offset, and segment + * size are returned through non-null arguments. At most name_size characters are copied into + * the name argument which is not null terminated if the file name is longer than the + * supplied name buffer (this is similar to strncpy()).</td> + * </tr> + * </table> + * + * The figure below shows an example of how a contiguous, one-dimensional dataset is partitioned + * into three parts and each of those parts is stored in a segment of an external file. The top + * rectangle represents the logical address space of the dataset while the bottom rectangle represents + * an external file. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig11.gif "External file storage" + * </td> + * </tr> + * </table> + * + * The example below shows code that defines the external storage for the example. Note that the + * segments are defined in order of the logical addresses they represent, not their order within the + * external file. It would also have been possible to put the segments in separate files. Care should + * be taken when setting up segments in a single file since the library does not automatically check + * for segments that overlap. + * + * <em>External storage</em> + * \code + * plist = H5Pcreate (H5P_DATASET_CREATE); + * H5Pset_external (plist, "velocity.data", 3000, 1000); + * H5Pset_external (plist, "velocity.data", 0, 2500); + * H5Pset_external (plist, "velocity.data", 4500, 1500); + * \endcode + * + * The figure below shows an example of how a contiguous, two-dimensional dataset is partitioned + * into three parts and each of those parts is stored in a separate external file. The top rectangle + * represents the logical address space of the dataset while the bottom rectangles represent external + * files. + * + * <table> + * <tr> + * <td> + * \image html Dsets_fig12.gif "Partitioning a 2-D dataset for external storage" + * </td> + * </tr> + * </table> + * + * The example below shows code for the partitioning described above. In this example, the library + * maps the multi-dimensional array onto a linear address space as defined by the HDF5 format + * specification, and then maps that address space into the segments defined in the external file list. + * + * <em>Partitioning a 2-D dataset for external storage</em> + * \code + * plist = H5Pcreate (H5P_DATASET_CREATE); + * H5Pset_external (plist, "scan1.data", 0, 24); + * H5Pset_external (plist, "scan2.data", 0, 24); + * H5Pset_external (plist, "scan3.data", 0, 16); + * \endcode + * + * The segments of an external file can exist beyond the end of the (external) file. The library reads + * that part of a segment as zeros. When writing to a segment that exists beyond the end of a file, + * the external file is automatically extended. Using this feature, one can create a segment (or set of + * segments) which is larger than the current size of the dataset. This allows the dataset to be + * extended at a future time (provided the dataspace also allows the extension). + * + * All referenced external data files must exist before performing raw data I/O on the dataset. This + * is normally not a problem since those files are being managed directly by the application or + * indirectly through some other library. However, if the file is transferred from its original context, + * care must be taken to assure that all the external files are accessible in the new location. + * + * \subsection subsec_dataset_filters Using HDF5 Filters + * This section describes in detail how to use the n-bit, scale-offset filters and szip filters. + * + * \subsubsection subsubsec_dataset_filters_nbit Using the N‐bit Filter + * N-bit data has n significant bits, where n may not correspond to a precise number of bytes. On + * the other hand, computing systems and applications universally, or nearly so, run most efficiently + * when manipulating data as whole bytes or multiple bytes. + * + * Consider the case of 12-bit integer data. In memory, that data will be handled in at least 2 bytes, + * or 16 bits, and on some platforms in 4 or even 8 bytes. The size of such a dataset can be + * significantly reduced when written to disk if the unused bits are stripped out. + * + * The n-bit filter is provided for this purpose, packing n-bit data on output by stripping off all + * unused bits and unpacking on input, restoring the extra bits required by the computational + * processor. + * + * <h4>N-bit Datatype</h4> + * An n-bit datatype is a datatype of n significant bits. Unless it is packed, an n-bit datatype is + * presented as an n-bit bitfield within a larger-sized value. For example, a 12-bit datatype might be + * presented as a 12-bit field in a 16-bit, or 2-byte, value. + * + * Currently, the datatype classes of n-bit datatype or n-bit field of a compound datatype or an array + * datatype are limited to integer or floating-point. + * + * The HDF5 user can create an n-bit datatype through a series of function calls. For example, the + * following calls create a 16-bit datatype that is stored in a 32-bit value with a 4-bit offset: + * \code + * hid_t nbit_datatype = H5Tcopy(H5T_STD_I32LE); + * H5Tset_precision(nbit_datatype, 16); + * H5Tset_offset(nbit_datatype, 4); + * \endcode + * + * In memory, one value of the above example n-bit datatype would be stored on a little-endian + * machine as follows: + * <table> + * <tr> + * <th>byte 3</th> + * <th>byte 2</th> + * <th>byte 1</th> + * <th>byte 0</th> + * </tr> + * <tr> + * <td>????????</td> + * <td>????SPPP</td> + * <td>PPPPPPPP</td> + * <td>PPPP????</td> + * </tr> + * <tr> + * <td colspan="4"> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in signed integer datatype precision.</em> + * </td> + * </tr> + * </table> + * + * <h4>N-bit Filter</h4> + * When data of an n-bit datatype is stored on disk using the n-bit filter, the filter packs the data by + * stripping off the padding bits; only the significant bits are retained and stored. The values on disk + * will appear as follows: + * <table> + * <tr> + * <th>1st value</th> + * <th>2nd value</th> + * <th>nth value</th> + * </tr> + * <tr> + * <td>SPPPPPPP PPPPPPPP</td> + * <td>SPPPPPPP PPPPPPPP</td> + * <td>...</td> + * </tr> + * <tr> + * <td colspan="3"> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in signed integer datatype precision.</em> + * </td> + * </tr> + * </table> + * + * <h4>How Does the N-bit Filter Work?</h4> + * The n-bit filter always compresses and decompresses according to dataset properties supplied by + * the HDF5 library in the datatype, dataspace, or dataset creation property list. + * + * The dataset datatype refers to how data is stored in an HDF5 file while the memory datatype + * refers to how data is stored in memory. The HDF5 library will do datatype conversion when + * writing data in memory to the dataset or reading data from the dataset to memory if the memory + * datatype differs from the dataset datatype. Datatype conversion is performed by HDF5 library + * before n-bit compression and after n-bit decompression. + * + * The following sub-sections examine the common cases: + * \li N-bit integer conversions + * \li N-bit floating-point conversions + * + * <h4>N-bit Integer Conversions</h4> + * Integer data with a dataset of integer datatype of less than full precision and a memory datatype + * of #H5T_NATIVE_INT, provides the simplest application of the n-bit filter. + * + * The precision of #H5T_NATIVE_INT is 8 multiplied by sizeof(int). This value, the size of an + * int in bytes, differs from platform to platform; we assume a value of 4 for the following + * illustration. We further assume the memory byte order to be little-endian. + * + * In memory, therefore, the precision of #H5T_NATIVE_INT is 32 and the offset is 0. One value of + * #H5T_NATIVE_INT is laid out in memory as follows: + * <table> + * <tr> + * <td> + * \image html Dsets_NbitInteger1.gif "H5T_NATIVE_INT in memory"<br /> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in signed integer datatype precision.</em> + * </td> + * </tr> + * </table> + * + * Suppose the dataset datatype has a precision of 16 and an offset of 4. After HDF5 converts + * values from the memory datatype to the dataset datatype, it passes something like the following + * to the n-bit filter for compression: + * <table> + * <tr> + * <td> + * \image html Dsets_NbitInteger2.gif "Passed to the n-bit filter"<br /> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in signed integer datatype precision.</em> + * </td> + * </tr> + * </table> + * + * Notice that only the specified 16 bits (15 significant bits and the sign bit) are retained in the + * conversion. All other significant bits of the memory datatype are discarded because the dataset + * datatype calls for only 16 bits of precision. After n-bit compression, none of these discarded bits, + * known as padding bits will be stored on disk. + * + * <h4>N-bit Floating-point Conversions</h4> + * Things get more complicated in the case of a floating-point dataset datatype class. This sub- + * section provides an example that illustrates the conversion from a memory datatype of + * #H5T_NATIVE_FLOAT to a dataset datatype of class floating-point. + * + * As before, let the #H5T_NATIVE_FLOAT be 4 bytes long, and let the memory byte order be + * little-endian. Per the IEEE standard, one value of #H5T_NATIVE_FLOAT is laid out in memory + * as follows: + * <table> + * <tr> + * <td> + * \image html Dsets_NbitFloating1.gif "H5T_NATIVE_FLOAT in memory"<br /> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in floating-point datatype precision.</em> + * </td> + * </tr> + * </table> + * + * Suppose the dataset datatype has a precision of 20, offset of 7, mantissa size of 13, mantissa + * position of 7, exponent size of 6, exponent position of 20, and sign position of 26. For more + * information, @see @ref subsubsec_datatype_program_define. + * + * After HDF5 converts values from the memory datatype to the dataset datatype, it passes + * something like the following to the n-bit filter for compression: + * <table> + * <tr> + * <td> + * \image html Dsets_NbitFloating2.gif "Passed to the n-bit filter"<br /> + * <em>Note: Key: S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit. Sign bit is + * included in floating-point datatype precision.</em> + * </td> + * </tr> + * </table> + * + * The sign bit and truncated mantissa bits are not changed during datatype conversion by the + * HDF5 library. On the other hand, the conversion of the 8-bit exponent to a 6-bit exponent is a + * little tricky: + * + * The bias for the new exponent in the n-bit datatype is: + * <code> + * 2<sup>(n-1)</sup>-1 + * </code> + * + * The following formula is used for this exponent conversion:<br /> + * <code> + * exp8 - (2<sup>(8-1)</sup> -1) = exp6 - (2<sup>(6-1)</sup>-1) = actual exponent value + * </code><br /> + * where exp8 is the stored decimal value as represented by the 8-bit exponent, and exp6 is the + * stored decimal value as represented by the 6-bit exponent. + * + * In this example, caution must be taken to ensure that, after conversion, the actual exponent value + * is within the range that can be represented by a 6-bit exponent. For example, an 8-bit exponent + * can represent values from -127 to 128 while a 6-bit exponent can represent values only from -31 + * to 32. + * + * <h4>N-bit Filter Behavior</h4> + * The n-bit filter was designed to treat the incoming data byte by byte at the lowest level. The + * purpose was to make the n-bit filter as generic as possible so that no pointer cast related to the + * datatype is needed. + * + * Bitwise operations are employed for packing and unpacking at the byte level. + * + * Recursive function calls are used to treat compound and array datatypes. + * + * <h4>N-bit Compression</h4> + * The main idea of n-bit compression is to use a loop to compress each data element in a chunk. + * Depending on the datatype of each element, the n-bit filter will call one of four functions. Each + * of these functions performs one of the following tasks: + * \li Compress a data element of a no-op datatype + * \li Compress a data element of an atomic datatype + * \li Compress a data element of a compound datatype + * \li Compress a data element of an array datatype + * + * No-op datatypes: The n-bit filter does not actually compress no-op datatypes. Rather, it copies + * the data buffer of the no-op datatype from the non-compressed buffer to the proper location in + * the compressed buffer; the compressed buffer has no holes. The term “compress” is used here + * simply to distinguish this function from the function that performs the reverse operation during + * decompression. + * + * Atomic datatypes: The n-bit filter will find the bytes where significant bits are located and try to + * compress these bytes, one byte at a time, using a loop. At this level, the filter needs the following + * information: + * <ul><li>The byte offset of the beginning of the current data element with respect to the + * beginning of the input data buffer</li> + * <li>Datatype size, precision, offset, and byte order</li></ul> + * + * The n-bit filter compresses from the most significant byte containing significant bits to the least + * significant byte. For big-endian data, therefore, the loop index progresses from smaller to larger + * while for little-endian, the loop index progresses from larger to smaller. + * + * In the extreme case of when the n-bit datatype has full precision, this function copies the content + * of the entire non-compressed datatype to the compressed output buffer. + * + * Compound datatypes: The n-bit filter will compress each data member of the compound + * datatype. If the member datatype is of an integer or floating-point datatype, the n-bit filter will + * call the function described above. If the member datatype is of a no-op datatype, the filter will + * call the function described above. If the member datatype is of a compound datatype, the filter + * will make a recursive call to itself. If the member datatype is of an array datatype, the filter will + * call the function described below. + * + * Array datatypes: The n-bit filter will use a loop to compress each array element in the array. If + * the base datatype of array element is of an integer or floating-point datatype, the n-bit filter will + * call the function described above. If the base datatype is of a no-op datatype, the filter will call + * the function described above. If the base datatype is of a compound datatype, the filter will call + * the function described above. If the member datatype is of an array datatype, the filter will make + * a recursive call of itself. + * + * <h4>N-bit Decompression</h4> + * The n-bit decompression algorithm is very similar to n-bit compression. The only difference is + * that at the byte level, compression packs out all padding bits and stores only significant bits into + * a continuous buffer (unsigned char) while decompression unpacks significant bits and inserts + * padding bits (zeros) at the proper positions to recover the data bytes as they existed before + * compression. + * + * <h4>Storing N-bit Parameters to Array cd_value[]</h4> + * All of the information, or parameters, required by the n-bit filter are gathered and stored in the + * array cd_values[] by the private function H5Z__set_local_nbit and are passed to another private + * function, H5Z__filter_nbit, by the HDF5 Library. + * These parameters are as follows: + * \li Parameters related to the datatype + * \li The number of elements within the chunk + * \li A flag indicating whether compression is needed + * + * The first and second parameters can be obtained using the HDF5 dataspace and datatype + * interface calls. + * + * A compound datatype can have members of array or compound datatype. An array datatype’s + * base datatype can be a complex compound datatype. Recursive calls are required to set + * parameters for these complex situations. + * + * Before setting the parameters, the number of parameters should be calculated to dynamically + * allocate the array cd_values[], which will be passed to the HDF5 Library. This also requires + * recursive calls. + * + * For an atomic datatype (integer or floating-point), parameters that will be stored include the + * datatype’s size, endianness, precision, and offset. + * + * For a no-op datatype, only the size is required. + * + * For a compound datatype, parameters that will be stored include the datatype’s total size and + * number of members. For each member, its member offset needs to be stored. Other parameters + * for members will depend on the respective datatype class. + * + * For an array datatype, the total size parameter should be stored. Other parameters for the array’s + * base type depend on the base type’s datatype class. + * + * Further, to correctly retrieve the parameter for use of n-bit compression or decompression later, + * parameters for distinguishing between datatype classes should be stored. + * + * <h4>Implementation</h4> + * Three filter callback functions were written for the n-bit filter: + * \li H5Z__can_apply_nbit + * \li H5Z__set_local_nbit + * \li H5Z__filter_nbit + * + * These functions are called internally by the HDF5 library. A number of utility functions were + * written for the function H5Z__set_local_nbit. Compression and decompression functions were + * written and are called by function H5Z__filter_nbit. All these functions are included in the file + * H5Znbit.c. + * + * The public function #H5Pset_nbit is called by the application to set up the use of the n-bit filter. + * This function is included in the file H5Pdcpl.c. The application does not need to supply any + * parameters. + * + * <h4>How N-bit Parameters are Stored</h4> + * A scheme of storing parameters required by the n-bit filter in the array cd_values[] was + * developed utilizing recursive function calls. + * + * Four private utility functions were written for storing the parameters associated with atomic + * (integer or floating-point), no-op, array, and compound datatypes: + * \li H5Z__set_parms_atomic + * \li H5Z__set_parms_array + * \li H5Z__set_parms_nooptype + * \li H5Z__set_parms_compound + * + * The scheme is briefly described below. + * + * First, assign a numeric code for datatype class atomic (integer or float), no-op, array, and + * compound datatype. The code is stored before other datatype related parameters are stored. + * + * The first three parameters of cd_values[] are reserved for: + * \li 1. The number of valid entries in the array cd_values[] + * \li 2. A flag indicating whether compression is needed + * \li 3. The number of elements in the chunk + * + * Throughout the balance of this explanation, i represents the index of cd_values[]. + * In the function H5Z__set_local_nbit: + * <ul><li>1. i = 2</li> + * <li>2. Get the number of elements in the chunk and store in cd_value[i]; increment i</li> + * <li>3. Get the class of the datatype: + * <ul><li>For an integer or floating-point datatype, call H5Z__set_parms_atomic</li> + * <li>For an array datatype, call H5Z__set_parms_array</li> + * <li>For a compound datatype, call H5Z__set_parms_compound</li> + * <li>For none of the above, call H5Z__set_parms_noopdatatype</li></ul></li> + * <li>4. Store i in cd_value[0] and flag in cd_values[1]</li></ul> + * + * In the function H5Z__set_parms_atomic: + * \li 1. Store the assigned numeric code for the atomic datatype in cd_value[i]; increment i + * \li 2. Get the size of the atomic datatype and store in cd_value[i]; increment i + * \li 3. Get the order of the atomic datatype and store in cd_value[i]; increment i + * \li 4. Get the precision of the atomic datatype and store in cd_value[i]; increment i + * \li 5. Get the offset of the atomic datatype and store in cd_value[i]; increment i + * \li 6. Determine the need to do compression at this point + * + * In the function H5Z__set_parms_nooptype: + * \li 1. Store the assigned numeric code for the no-op datatype in cd_value[i]; increment i + * \li 2. Get the size of the no-op datatype and store in cd_value[i]; increment i + * + * In the function H5Z__set_parms_array: + * <ul><li>1. Store the assigned numeric code for the array datatype in cd_value[i]; increment i</li> + * <li>2. Get the size of the array datatype and store in cd_value[i]; increment i</li> + * <li>3. Get the class of the array’s base datatype. + * <ul><li>For an integer or floating-point datatype, call H5Z__set_parms_atomic</li> + * <li>For an array datatype, call H5Z__set_parms_array</li> + * <li>For a compound datatype, call H5Z__set_parms_compound</li> + * <li>If none of the above, call H5Z__set_parms_noopdatatype</li></ul></li></ul> + * + * In the function H5Z__set_parms_compound: + * <ul><li>1. Store the assigned numeric code for the compound datatype in cd_value[i]; increment i</li> + * <li>2. Get the size of the compound datatype and store in cd_value[i]; increment i</li> + * <li>3. Get the number of members and store in cd_values[i]; increment i</li> + * <li>4. For each member + * <ul><li>Get the member offset and store in cd_values[i]; increment i</li> + * <li>Get the class of the member datatype</li> + * <li>For an integer or floating-point datatype, call H5Z__set_parms_atomic</li> + * <li>For an array datatype, call H5Z__set_parms_array</li> + * <li>For a compound datatype, call H5Z__set_parms_compound</li> + * <li>If none of the above, call H5Z__set_parms_noopdatatype</li></ul></li></ul> + * + * <h4>N-bit Compression and Decompression Functions</h4> + * The n-bit compression and decompression functions above are called by the private HDF5 + * function H5Z__filter_nbit. The compress and decompress functions retrieve the n-bit parameters + * from cd_values[] as it was passed by H5Z__filter_nbit. Parameters are retrieved in exactly the + * same order in which they are stored and lower-level compression and decompression functions + * for different datatype classes are called. + * + * N-bit compression is not implemented in place. Due to the difficulty of calculating actual output + * buffer size after compression, the same space as that of the input buffer is allocated for the output + * buffer as passed to the compression function. However, the size of the output buffer passed by + * reference to the compression function will be changed (smaller) after the compression is + * complete. + * + * <h4>Usage Examples</h4> + * + * The following code example illustrates the use of the n-bit filter for writing and reading n-bit + * integer data. + * + * <em>N-bit compression for integer data</em> + * \code + * #include "hdf5.h" + * #include "stdlib.h" + * #include "math.h" + * + * #define H5FILE_NAME "nbit_test_int.h5" + * #define DATASET_NAME "nbit_int" + * #define NX 200 + * #define NY 300 + * #define CH_NX 10 + * #define CH_NY 15 + * + * int main(void) + * { + * hid_t file, dataspace, dataset, datatype, mem_datatype, dset_create_props; + * hsize_t dims[2], chunk_size[2]; + * int orig_data[NX][NY]; + * int new_data[NX][NY]; + * int i, j; + * size_t precision, offset; + * + * // Define dataset datatype (integer), and set precision, offset + * datatype = H5Tcopy(H5T_NATIVE_INT); + * precision = 17; // precision includes sign bit + * if(H5Tset_precision(datatype,precision) < 0) { + * printf("Error: fail to set precision\n"); + * return -1; + * } + * offset = 4; + * if(H5Tset_offset(datatype,offset) < 0) { + * printf("Error: fail to set offset\n"); + * return -1; + * } + * + * // Copy to memory datatype + * mem_datatype = H5Tcopy(datatype); + * + * // Set order of dataset datatype + * if(H5Tset_order(datatype, H5T_ORDER_BE) < 0) { + * printf("Error: fail to set endianness\n"); + * return -1; + * } + * + * // Initialize data buffer with random data within correct + * // range corresponding to the memory datatype's precision + * // and offset. + * for (i = 0; i < NX; i++) + * for (j = 0; j < NY; j++) + * orig_data[i][j] = rand() % (int)pow(2, precision-1) << offset; + * + * // Describe the size of the array. + * dims[0] = NX; + * dims[1] = NY; + * if((dataspace = H5Screate_simple (2, dims, NULL)) < 0) { + * printf("Error: fail to create dataspace\n"); + * return -1; + * } + * + * // Create a new file using read/write access, default file + * // creation properties, and default file access properties. + * if((file = H5Fcreate (H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create file\n"); + * return -1; + * } + * + * // Set the dataset creation property list to specify that + * // the raw data is to be partitioned into 10 x 15 element + * // chunks and that each chunk is to be compressed. + * chunk_size[0] = CH_NX; + * chunk_size[1] = CH_NY; + * if((dset_create_props = H5Pcreate (H5P_DATASET_CREATE)) < 0) { + * printf("Error: fail to create dataset property\n"); + * return -1; + * } + * if(H5Pset_chunk (dset_create_props, 2, chunk_size) < 0) { + * printf("Error: fail to set chunk\n"); + * return -1; + * } + * + * // Set parameters for n-bit compression; check the description + * // of the H5Pset_nbit function in the HDF5 Reference Manual + * // for more information. + * if(H5Pset_nbit (dset_create_props) < 0) { + * printf("Error: fail to set nbit filter\n"); + * return -1; + * } + * + * // Create a new dataset within the file. The datatype + * // and dataspace describe the data on disk, which may + * // be different from the format used in the application's + * // memory. + * if((dataset = H5Dcreate(file, DATASET_NAME, datatype, dataspace, + * H5P_DEFAULT, dset_create_props, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create dataset\n"); + * return -1; + * } + * + * // Write the array to the file. The datatype and dataspace + * // describe the format of the data in the 'orig_data' buffer. + * // The raw data is translated to the format required on disk, + * // as defined above. We use default raw data transfer + * // properties. + * if(H5Dwrite (dataset, mem_datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig_data) < 0) { + * printf("Error: fail to write to dataset\n"); + * return -1; + * } + * H5Dclose (dataset); + * + * if((dataset = H5Dopen(file, DATASET_NAME, H5P_DEFAULT)) < 0) { + * printf("Error: fail to open dataset\n"); + * return -1; + * } + * + * // Read the array. This is similar to writing data, + * // except the data flows in the opposite direction. + * // Note: Decompression is automatic. + * if(H5Dread (dataset, mem_datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, new_data) < 0) { + * printf("Error: fail to read from dataset\n"); + * return -1; + * } + * + * H5Tclose (datatype); + * H5Tclose (mem_datatype); + * H5Dclose (dataset); + * H5Sclose (dataspace); + * H5Pclose (dset_create_props); + * H5Fclose (file); + * + * return 0; + * } + * \endcode + * + * The following code example illustrates the use of the n-bit filter for writing and reading n-bit + * floating-point data. + * + * <em>N-bit compression for floating-point data</em> + * \code + * #include "hdf5.h" + * + * #define H5FILE_NAME "nbit_test_float.h5" + * #define DATASET_NAME "nbit_float" + * #define NX 2 + * #define NY 5 + * #define CH_NX 2 + * #define CH_NY 5 + * + * int main(void) + * { + * hid_t file, dataspace, dataset, datatype, dset_create_props; + * hsize_t dims[2], chunk_size[2]; + * + * // orig_data[] are initialized to be within the range that + * // can be represented by dataset datatype (no precision + * // loss during datatype conversion) + * // + * float orig_data[NX][NY] = {{188384.00, 19.103516,-1.0831790e9, -84.242188, 5.2045898}, + * {-49140.000, 2350.2500, -3.2110596e-1, 6.4998865e-5, -0.0000000}}; + * float new_data[NX][NY]; + * size_t precision, offset; + * + * // Define single-precision floating-point type for dataset + * //--------------------------------------------------------------- + * // size=4 byte, precision=20 bits, offset=7 bits, + * // mantissa size=13 bits, mantissa position=7, + * // exponent size=6 bits, exponent position=20, + * // exponent bias=31. + * // It can be illustrated in little-endian order as: + * // (S - sign bit, E - exponent bit, M - mantissa bit, ? - padding bit) + * // + * // 3 2 1 0 + * // ?????SEE EEEEMMMM MMMMMMMM M??????? + * // + * // To create a new floating-point type, the following + * // properties must be set in the order of + * // set fields -> set offset -> set precision -> set size. + * // All these properties must be set before the type can + * // function. Other properties can be set anytime. Derived + * // type size cannot be expanded bigger than original size + * // but can be decreased. There should be no holes + * // among the significant bits. Exponent bias usually + * // is set 2^(n-1)-1, where n is the exponent size. + * //--------------------------------------------------------------- + * datatype = H5Tcopy(H5T_IEEE_F32BE); + * if(H5Tset_fields(datatype, 26, 20, 6, 7, 13) < 0) { + * printf("Error: fail to set fields\n"); + * return -1; + * } + * offset = 7; + * if(H5Tset_offset(datatype,offset) < 0) { + * printf("Error: fail to set offset\n"); + * return -1; + * } + * precision = 20; + * if(H5Tset_precision(datatype,precision) < 0) { + * printf("Error: fail to set precision\n"); + * return -1; + * } + * if(H5Tset_size(datatype, 4) < 0) { + * printf("Error: fail to set size\n"); + * return -1; + * } + * if(H5Tset_ebias(datatype, 31) < 0) { + * printf("Error: fail to set exponent bias\n"); + * return -1; + * } + * + * // Describe the size of the array. + * dims[0] = NX; + * dims[1] = NY; + * if((dataspace = H5Screate_simple (2, dims, NULL)) < 0) { + * printf("Error: fail to create dataspace\n"); + * return -1; + * } + * + * // Create a new file using read/write access, default file + * // creation properties, and default file access properties. + * if((file = H5Fcreate (H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create file\n"); + * return -1; + * } + * + * // Set the dataset creation property list to specify that + * // the raw data is to be partitioned into 2 x 5 element + * // chunks and that each chunk is to be compressed. + * chunk_size[0] = CH_NX; + * chunk_size[1] = CH_NY; + * if((dset_create_props = H5Pcreate (H5P_DATASET_CREATE)) < 0) { + * printf("Error: fail to create dataset property\n"); + * return -1; + * } + * if(H5Pset_chunk (dset_create_props, 2, chunk_size) < 0) { + * printf("Error: fail to set chunk\n"); + * return -1; + * } + * + * // Set parameters for n-bit compression; check the description + * // of the H5Pset_nbit function in the HDF5 Reference Manual + * // for more information. + * if(H5Pset_nbit (dset_create_props) < 0) { + * printf("Error: fail to set nbit filter\n"); + * return -1; + * } + * + * // Create a new dataset within the file. The datatype + * // and dataspace describe the data on disk, which may + * // be different from the format used in the application's memory. + * if((dataset = H5Dcreate(file, DATASET_NAME, datatype, dataspace, H5P_DEFAULT, + * dset_create_plists, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create dataset\n"); + * return -1; + * } + * + * // Write the array to the file. The datatype and dataspace + * // describe the format of the data in the 'orig_data' buffer. + * // The raw data is translated to the format required on disk, + * // as defined above. We use default raw data transfer properties. + * if(H5Dwrite (dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig_data) < 0) { + * printf("Error: fail to write to dataset\n"); + * return -1; + * } + * H5Dclose (dataset); + * if((dataset = H5Dopen(file, DATASET_NAME, H5P_DEFAULT))<0) { + * printf("Error: fail to open dataset\n"); + * return -1; + * } + * + * // Read the array. This is similar to writing data, + * // except the data flows in the opposite direction. + * // Note: Decompression is automatic. + * if(H5Dread (dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, new_data) < 0) { + * printf("Error: fail to read from dataset\n"); + * return -1; + * } + * H5Tclose (datatype); + * H5Dclose (dataset); + * H5Sclose (dataspace); + * H5Pclose (dset_create_props); + * H5Fclose (file); + * + * return 0 + * } + * \endcode + * + * <h4>Limitations</h4> + * Because the array cd_values[] has to fit into an object header message of 64K, the n-bit filter has + * an upper limit on the number of n-bit parameters that can be stored in it. To be conservative, a + * maximum of 4K is allowed for the number of parameters. + * + * The n-bit filter currently only compresses n-bit datatypes or fields derived from integer or + * floating-point datatypes. The n-bit filter assumes padding bits of zero. This may not be true since + * the HDF5 user can set padding bit to be zero, one, or leave the background alone. However, it is + * expected the n-bit filter will be modified to adjust to such situations. + * + * The n-bit filter does not have a way to handle the situation where the fill value of a dataset is + * defined and the fill value is not of an n-bit datatype although the dataset datatype is. + * + * \subsubsection subsubsec_dataset_filters_scale Using the Scale‐offset Filter + * Generally speaking, scale-offset compression performs a scale and/or offset operation on each + * data value and truncates the resulting value to a minimum number of bits (minimum-bits) before + * storing it. + * + * The current scale-offset filter supports integer and floating-point datatypes only. For the floating- + * point datatype, float and double are supported, but long double is not supported. + * + * Integer data compression uses a straight-forward algorithm. Floating-point data compression + * adopts the GRiB data packing mechanism which offers two alternate methods: a fixed minimum- + * bits method, and a variable minimum-bits method. Currently, only the variable minimum-bits + * method is implemented. + * + * Like other I/O filters supported by the HDF5 library, applications using the scale-offset filter + * must store data with chunked storage. + * + * Integer type: The minimum-bits of integer data can be determined by the filter. For example, if + * the maximum value of data to be compressed is 7065 and the minimum value is 2970. Then the + * “span” of dataset values is equal to (max-min+1), which is 4676. If no fill value is defined for the + * dataset, the minimum-bits is: ceiling(log2(span)) = 12. With fill value set, the minimum-bits is: + * ceiling(log2(span+1)) = 13. + * + * HDF5 users can also set the minimum-bits. However, if the user gives a minimum-bits that is + * less than that calculated by the filter, the compression will be lossy. + * + * Floating-point type: The basic idea of the scale-offset filter for the floating-point type is to + * transform the data by some kind of scaling to integer data, and then to follow the procedure of + * the scale-offset filter for the integer type to do the data compression. Due to the data + * transformation from floating-point to integer, the scale-offset filter is lossy in nature. + * + * Two methods of scaling the floating-point data are used: the so-called D-scaling and E-scaling. + * D-scaling is more straightforward and easy to understand. For HDF5 1.8 release, only the + * D-scaling method had been implemented. + * + * <h4>Design</h4> + * Before the filter does any real work, it needs to gather some information from the HDF5 Library + * through API calls. The parameters the filter needs are: + * \li The minimum-bits of the data value + * \li The number of data elements in the chunk + * \li The datatype class, size, sign (only for integer type), byte order, and fill value if defined + * + * Size and sign are needed to determine what kind of pointer cast to use when retrieving values + * from the data buffer. + * + * The pipeline of the filter can be divided into four parts: (1)pre-compression; (2)compression; + * (3)decompression; (4)post-decompression. + * + * Depending on whether a fill value is defined or not, the filter will handle pre-compression and + * post-decompression differently. + * + * The scale-offset filter only needs the memory byte order, size of datatype, and minimum-bits for + * compression and decompression. + * + * Since decompression has no access to the original data, the minimum-bits and the minimum + * value need to be stored with the compressed data for decompression and post-decompression. + * + * <h4>Integer Type</h4> + * Pre-compression: During pre-compression minimum-bits is calculated if it is not set by the user. + * For more information on how minimum-bits are calculated, @see @ref subsubsec_dataset_filters_nbit. + * + * If the fill value is defined, finding the maximum and minimum values should ignore the data + * element whose value is equal to the fill value. + * + * If no fill value is defined, the value of each data element is subtracted by the minimum value + * during this stage. + * + * If the fill value is defined, the fill value is assigned to the maximum value. In this way minimum- + * bits can represent a data element whose value is equal to the fill value and subtracts the + * minimum value from a data element whose value is not equal to the fill value. + * + * The fill value (if defined), the number of elements in a chunk, the class of the datatype, the size + * of the datatype, the memory order of the datatype, and other similar elements will be stored in + * the HDF5 object header for the post-decompression usage. + * + * After pre-compression, all values are non-negative and are within the range that can be stored by + * minimum-bits. + * + * Compression: All modified data values after pre-compression are packed together into the + * compressed data buffer. The number of bits for each data value decreases from the number of + * bits of integer (32 for most platforms) to minimum-bits. The value of minimum-bits and the + * minimum value are added to the data buffer and the whole buffer is sent back to the library. In + * this way, the number of bits for each modified value is no more than the size of minimum-bits. + * + * Decompression: In this stage, the number of bits for each data value is resumed from minimum- + * bits to the number of bits of integer. + * + * Post-decompression: For the post-decompression stage, the filter does the opposite of what it + * does during pre-compression except that it does not calculate the minimum-bits or the minimum + * value. These values were saved during compression and can be retrieved through the resumed + * data buffer. If no fill value is defined, the filter adds the minimum value back to each data + * element. + * + * If the fill value is defined, the filter assigns the fill value to the data element whose value is equal + * to the maximum value that minimum-bits can represent and adds the minimum value back to + * each data element whose value is not equal to the maximum value that minimum-bits can + * represent. + * + * @anchor h4_float_datatype <h4>Floating-point Type</h4> + * The filter will do data transformation from floating-point type to integer type and then handle the + * data by using the procedure for handling the integer data inside the filter. Insignificant bits of + * floating-point data will be cut off during data transformation, so this filter is a lossy compression + * method. + * + * There are two scaling methods: D-scaling and E-scaling. The HDF5 1.8 release only supports D- + * scaling. D-scaling is short for decimal scaling. E-scaling should be similar conceptually. In order + * to transform data from floating-point to integer, a scale factor is introduced. The minimum value + * will be calculated. Each data element value will subtract the minimum value. The modified data + * will be multiplied by 10 (Decimal) to the power of scale_factor, and only the integer part will be + * kept and manipulated through the routines for the integer type of the filter during pre- + * compression and compression. Integer data will be divided by 10 to the power of scale_factor to + * transform back to floating-point data during decompression and post-decompression. Each data + * element value will then add the minimum value, and the floating-point data are resumed. + * However, the resumed data will lose some insignificant bits compared with the original value. + * + * For example, the following floating-point data are manipulated by the filter, and the D-scaling + * factor is 2. + * <em>{104.561, 99.459, 100.545, 105.644}</em> + * + * The minimum value is 99.459, each data element subtracts 99.459, the modified data is + * <em>{5.102, 0, 1.086, 6.185}</em> + * + * Since the D-scaling factor is 2, all floating-point data will be multiplied by 10^2 with this result: + * <em>{510.2, 0, 108.6, 618.5}</em> + * + * The digit after decimal point will be rounded off, and then the set looks like: + * <em>{510, 0, 109, 619}</em> + * + * After decompression, each value will be divided by 10^2 and will be added to the offset 99.459. + * The floating-point data becomes + * <em>{104.559, 99.459, 100.549, 105.649}</em> + * + * The relative error for each value should be no more than 5* (10^(D-scaling factor +1)). + * D-scaling sometimes is also referred as a variable minimum-bits method since for different datasets + * the minimum-bits to represent the same decimal precision will vary. The data value is modified + * to 2 to power of scale_factor for E-scaling. E-scaling is also called fixed-bits method since for + * different datasets the minimum-bits will always be fixed to the scale factor of E-scaling. + * Currently, HDF5 ONLY supports the D-scaling (variable minimum-bits) method. + * + * <h4>Implementation</h4> + * The scale-offset filter implementation was written and included in the file H5Zscaleoffset.c. + * Function #H5Pset_scaleoffset was written and included in the file “H5Pdcpl.c”. The HDF5 user + * can supply minimum-bits by calling function #H5Pset_scaleoffset. + * + * The scale-offset filter was implemented based on the design outlined in this section. However, + * the following factors need to be considered: + * <ol><li> + * The filter needs the appropriate cast pointer whenever it needs to retrieve data values. + * </li> + * <li> + * The HDF5 Library passes to the filter the to-be-compressed data in the format of the dataset + * datatype, and the filter passes back the decompressed data in the same format. If a fill value is + * defined, it is also in dataset datatype format. For example, if the byte order of the dataset data- + * type is different from that of the memory datatype of the platform, compression or decompression performs + * an endianness conversion of data buffer. Moreover, it should be aware that + * memory byte order can be different during compression and decompression. + * </li> + * <li> + * The difference of endianness and datatype between file and memory should be considered + * when saving and retrieval of minimum-bits, minimum value, and fill value. + * <li> + * If the user sets the minimum-bits to full precision of the datatype, no operation is needed at + * the filter side. If the full precision is a result of calculation by the filter, then the minimum-bits + * needs to be saved for decompression but no compression or decompression is needed (only a + * copy of the input buffer is needed).</li> + * <li> + * If by calculation of the filter, the minimum-bits is equal to zero, special handling is needed. + * Since it means all values are the same, no compression or decompression is needed. But the + * minimum-bits and minimum value still need to be saved during compression.</li> + * <li> + * For floating-point data, the minimum value of the dataset should be calculated at first. Each + * data element value will then subtract the minimum value to obtain the “offset” data. The offset + * data will then follow the steps outlined above in the discussion of floating-point types to do data + * transformation to integer and rounding. For more information, @see @ref h4_float_datatype. + * </li></ol> + * + * <h4>Usage Examples</h4> + * The following code example illustrates the use of the scale-offset filter for writing and reading + * integer data. + * + * <em>Scale-offset compression integer data</em> + * \code + * #include "hdf5.h" + * #include "stdlib.h" + * + * #define H5FILE_NAME "scaleoffset_test_int.h5" + * #define DATASET_NAME "scaleoffset_int" + * #define NX 200 + * #define NY 300 + * #define CH_NX 10 + * #define CH_NY 15 + * int main(void) + * { + * hid_t file, dataspace, dataset, datatype, dset_create_props; + * hsize_t dims[2], chunk_size[2]; + * int orig_data[NX][NY]; + * int new_data[NX][NY]; + * int i, j, fill_val; + * + * // Define dataset datatype + * datatype = H5Tcopy(H5T_NATIVE_INT); + * + * // Initialize data buffer + * for (i=0; i < NX; i++) + * for (j=0; j < NY; j++) + * orig_data[i][j] = rand() % 10000; + * + * // Describe the size of the array. + * dims[0] = NX; + * dims[1] = NY; + * if((dataspace = H5Screate_simple (2, dims, NULL)) < 0) { + * printf("Error: fail to create dataspace\n"); + * return -1; + * } + * + * // Create a new file using read/write access, default file + * // creation properties, and default file access properties. + * if((file = H5Fcreate (H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create file\n"); + * return -1; + * } + * + * // Set the dataset creation property list to specify that + * // the raw data is to be partitioned into 10 x 15 element + * // chunks and that each chunk is to be compressed. + * chunk_size[0] = CH_NX; + * chunk_size[1] = CH_NY; + * if((dset_create_props = H5Pcreate (H5P_DATASET_CREATE)) < 0) { + * printf("Error: fail to create dataset property\n"); + * return -1; + * } + * if(H5Pset_chunk (dset_create_props, 2, chunk_size) < 0) { + * printf("Error: fail to set chunk\n"); + * return -1; + * } + * + * // Set the fill value of dataset + * fill_val = 10000; + * if (H5Pset_fill_value(dset_create_props, H5T_NATIVE_INT, &fill_val)<0) { + * printf("Error: can not set fill value for dataset\n"); + * return -1; + * } + * + * // Set parameters for scale-offset compression. Check the + * // description of the H5Pset_scaleoffset function in the + * // HDF5 Reference Manual for more information. + * if(H5Pset_scaleoffset (dset_create_props, H5Z_SO_INT, H5Z_SO_INT_MINIMUMBITS_DEFAULT) < 0) { + * printf("Error: fail to set scaleoffset filter\n"); + * return -1; + * } + * + * // Create a new dataset within the file. The datatype + * // and dataspace describe the data on disk, which may + * // or may not be different from the format used in the + * // application's memory. The link creation and + * // dataset access property list parameters are passed + * // with default values. + * if((dataset = H5Dcreate (file, DATASET_NAME, datatype, dataspace, H5P_DEFAULT, + * dset_create_props, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create dataset\n"); + * return -1; + * } + * + * // Write the array to the file. The datatype and dataspace + * // describe the format of the data in the 'orig_data' buffer. + * // We use default raw data transfer properties. + * if(H5Dwrite (dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig_data) < 0) { + * printf("Error: fail to write to dataset\n"); + * return -1; + * } + * + * H5Dclose (dataset); + * + * if((dataset = H5Dopen(file, DATASET_NAME, H5P_DEFAULT)) < 0) { + * printf("Error: fail to open dataset\n"); + * return -1; + * } + * + * // Read the array. This is similar to writing data, + * // except the data flows in the opposite direction. + * // Note: Decompression is automatic. + * if(H5Dread (dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, new_data) < 0) { + * printf("Error: fail to read from dataset\n"); + * return -1; + * } + * + * H5Tclose (datatype); + * H5Dclose (dataset); + * H5Sclose (dataspace); + * H5Pclose (dset_create_props); + * H5Fclose (file); + * + * return 0; + * } + * \endcode + * + * The following code example illustrates the use of the scale-offset filter (set for variable + * minimum-bits method) for writing and reading floating-point data. + * + * <em>Scale-offset compression floating-point data</em> + * \code + * #include "hdf5.h" + * #include "stdlib.h" + * + * #define H5FILE_NAME "scaleoffset_test_float_Dscale.h5" + * #define DATASET_NAME "scaleoffset_float_Dscale" + * #define NX 200 + * #define NY 300 + * #define CH_NX 10 + * #define CH_NY 15 + * + * int main(void) + * { + * hid_t file, dataspace, dataset, datatype, dset_create_props; + * hsize_t dims[2], chunk_size[2]; + * float orig_data[NX][NY]; + * float new_data[NX][NY]; + * float fill_val; + * int i, j; + * + * // Define dataset datatype + * datatype = H5Tcopy(H5T_NATIVE_FLOAT); + * + * // Initialize data buffer + * for (i=0; i < NX; i++) + * for (j=0; j < NY; j++) + * orig_data[i][j] = (rand() % 10000) / 1000.0; + * + * // Describe the size of the array. + * dims[0] = NX; + * dims[1] = NY; + * if((dataspace = H5Screate_simple (2, dims, NULL)) < 0) { + * printf("Error: fail to create dataspace\n"); + * return -1; + * } + * + * // Create a new file using read/write access, default file + * // creation properties, and default file access properties. + * if((file = H5Fcreate (H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create file\n"); + * return -1; + * } + * + * // Set the dataset creation property list to specify that + * // the raw data is to be partitioned into 10 x 15 element + * // chunks and that each chunk is to be compressed. + * chunk_size[0] = CH_NX; + * chunk_size[1] = CH_NY; + * if((dset_create_props = H5Pcreate (H5P_DATASET_CREATE)) < 0) { + * printf("Error: fail to create dataset property\n"); + * return -1; + * } + * if(H5Pset_chunk (dset_create_props, 2, chunk_size) < 0) { + * printf("Error: fail to set chunk\n"); + * return -1; + * } + * + * // Set the fill value of dataset + * fill_val = 10000.0; + * if (H5Pset_fill_value(dset_create_props, H5T_NATIVE_FLOAT, &fill_val) < 0) { + * printf("Error: can not set fill value for dataset\n"); + * return -1; + * } + * + * // Set parameters for scale-offset compression; use variable + * // minimum-bits method, set decimal scale factor to 3. Check + * // the description of the H5Pset_scaleoffset function in the + * // HDF5 Reference Manual for more information. + * if(H5Pset_scaleoffset (dset_create_props, H5Z_SO_FLOAT_DSCALE, 3) < 0) { + * printf("Error: fail to set scaleoffset filter\n"); + * return -1; + * } + * + * // Create a new dataset within the file. The datatype + * // and dataspace describe the data on disk, which may + * // or may not be different from the format used in the + * // application's memory. + * if((dataset = H5Dcreate (file, DATASET_NAME, datatype, dataspace, H5P_DEFAULT, + * dset_create_props, H5P_DEFAULT)) < 0) { + * printf("Error: fail to create dataset\n"); + * return -1; + * } + * + * // Write the array to the file. The datatype and dataspace + * // describe the format of the data in the 'orig_data' buffer. + * // We use default raw data transfer properties. + * if(H5Dwrite (dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, orig_data) < 0) { + * printf("Error: fail to write to dataset\n"); + * return -1; + * } + * + * H5Dclose (dataset); + * + * if((dataset = H5Dopen(file, DATASET_NAME, H5P_DEFAULT)) < 0) { + * printf("Error: fail to open dataset\n"); + * return -1; + * } + * + * // Read the array. This is similar to writing data, + * // except the data flows in the opposite direction. + * // Note: Decompression is automatic. + * if(H5Dread (dataset, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, new_data) < 0) { + * printf("Error: fail to read from dataset\n"); + * return -1; + * } + * + * H5Tclose (datatype); + * H5Dclose (dataset); + * H5Sclose (dataspace); + * H5Pclose (dset_create_props); + * H5Fclose (file); + * + * return 0; + * } + * \endcode + * + * <h4>Limitations</h4> + * For floating-point data handling, there are some algorithmic limitations to the GRiB data packing + * mechanism: + * <ol><li> + * Both the E-scaling and D-scaling methods are lossy compression + * </li> + * <li> + * For the D-scaling method, since data values have been rounded to integer values (positive) + * before truncating to the minimum-bits, their range is limited by the maximum value that can be + * represented by the corresponding unsigned integer type (the same size as that of the floating- + * point type) + * </li></ol> + * + * <h4>Suggestions</h4> + * The following are some suggestions for using the filter for floating-point data: + * <ol><li> + * It is better to convert the units of data so that the units are within certain common range (for + * example, 1200m to 1.2km) + * </li> + * <li> + * If data values to be compressed are very near to zero, it is strongly recommended that the + * user sets the fill value away from zero (for example, a large positive number); if the user does + * nothing, the HDF5 library will set the fill value to zero, and this may cause undesirable + * compression results + * </li> + * <li> + * Users are not encouraged to use a very large decimal scale factor (for example, 100) for the + * D-scaling method; this can cause the filter not to ignore the fill value when finding maximum + * and minimum values, and they will get a much larger minimum-bits (poor compression) + * </li></ol> + * + * \subsubsection subsubsec_dataset_filters_szip Using the Szip Filter + * See The HDF Group website for further information regarding the Szip filter. + * + * Previous Chapter \ref sec_group - Next Chapter \ref sec_datatype + * + */ + +/** + * \defgroup H5D Datasets (H5D) * * Use the functions in this module to manage HDF5 datasets, including the * transfer of data between memory and disk and the description of dataset diff --git a/src/H5Emodule.h b/src/H5Emodule.h index 58a3517..f2e6d44 100644 --- a/src/H5Emodule.h +++ b/src/H5Emodule.h @@ -29,30 +29,558 @@ #define H5_MY_PKG_ERR H5E_ERROR #define H5_MY_PKG_INIT YES -/**\defgroup H5E H5E - * - * Use the functions in this module to manage HDF5 error stacks and error - * messages. - * - * <table> - * <tr><th>Create</th><th>Read</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5E_examples.c create - * </td> - * <td> - * \snippet{lineno} H5E_examples.c read - * </td> - * <tr><th>Update</th><th>Delete</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5E_examples.c update - * </td> - * <td> - * \snippet{lineno} H5E_examples.c delete - * </td> - * </tr> - * </table> +/** \page H5E_UG HDF5 Error Handling + * + * \section sec_error HDF5 Error Handling + * + * The HDF5 library provides an error reporting mechanism for both the library itself and for user + * application programs. It can trace errors through function stack and error information like file + * name, function name, line number, and error description. + * + * \subsection subsec_error_intro Introduction + * The HDF5 Library provides an error reporting mechanism for both the library itself and for user application + * programs. It can trace errors through function stack and error information like file name, function name, + * line number, and error description. + * + * \ref subsec_error_ops discusses the basic error concepts such as error stack, error record, and error + * message and describes the related API functions. These concepts and functions are sufficient for + * application programs to trace errors inside the HDF5 Library. + * + * \ref subsec_error_adv talks about the advanced concepts of error + * class and error stack handle and talks about the related functions. With these concepts and functions, an + * application library or program using the HDF5 Library can have its own error report blended with HDF5’s + * error report. + * + * Starting with Release 1.8, we have a new set of Error Handling API functions. For the purpose of backward + * compatibility with version 1.6 and before, we still keep the old API functions, \ref H5Epush1, + * \ref H5Eprint1, \ref H5Ewalk1, \ref H5Eclear1, \ref H5Eget_auto1, \ref H5Eset_auto1. These functions do + * not have the error stack as a parameter. The library allows them to operate on the default error stack. + * (The H5E compatibility macros will choose the correct function based on the parameters) + * + * The old API is similar to functionality discussed in \ref subsec_error_ops. The functionality discussed in + * \ref subsec_error_adv,the ability of allowing applications to add their own error records, is the new + * design for the Error Handling API. + * + * \subsection subsec_error_H5E Error Handling Function Summaries + * @see H5E reference manual + * + * \subsection subsec_error_program Programming Model for Error Handling + * This section is under construction. + * + * \subsection subsec_error_ops Basic Error Handling Operations + * Let us first try to understand the error stack. An error stack is a collection of error records. Error + * records can be pushed onto or popped off the error stack. By default, when an error occurs deep within + * the HDF5 Library, an error record is pushed onto an error stack and that function returns a failure + * indication. + * Its caller detects the failure, pushes another record onto the stack, and returns a failure indication. + * This continues until the API function called by the application returns a failure indication. The next + * API function being called will reset the error stack. All HDF5 Library error records belong to the same + * error class. For more information, see \ref subsec_error_adv. + * + * \subsubsection subsubsec_error_ops_stack Error Stack and Error Message + * In normal circumstances, an error causes the stack to be printed on the standard error stream + * automatically. + * This automatic error stack is the library’s default stack. For all the functions in this section, whenever + * an error stack ID is needed as a parameter, \ref H5E_DEFAULT can be used to indicate the library’s default + * stack. The first error record of the error stack, number #000, is produced by the API function itself and + * is usually sufficient to indicate to the application what went wrong. + * <table> + * <caption align=top>Example: An Error Message</caption> + * <tr> + * <td> + * <p>If an application calls \ref H5Tclose on a + * predefined datatype then the following message is + * printed on the standard error stream. This is a + * simple error that has only one component, the API + * function; other errors may have many components. + * <p><code><pre> + * HDF5-DIAG: Error detected in HDF5 (1.10.9) thread 0. + * #000: H5T.c line ### in H5Tclose(): predefined datatype + * major: Function argument + * minor: Bad value + * </pre></code> + * </td> + * </tr> + * </table> + * In the example above, we can see that an error record has a major message and a minor message. A major + * message generally indicates where the error happens. The location can be a dataset or a dataspace, for + * example. A minor message explains further details of the error. An example is “unable to open file”. + * Another specific detail about the error can be found at the end of the first line of each error record. + * This error description is usually added by the library designer to tell what exactly goes wrong. In the + * example above, the “predefined datatype” is an error description. + * + * \subsubsection subsubsec_error_ops_print Print and Clear an Error Stack + * Besides the automatic error report, the error stack can also be printed and cleared by the functions + * \ref H5Eprint2 and \ref H5Eclear2. If an application wishes to make explicit + * calls to \ref H5Eprint2 to print the error stack, the automatic printing should be turned off + * to prevent error messages from being displayed twice (see \ref H5Eset_auto2). + * + * <em>To print an error stack:</em> + * \code + * herr_t H5Eprint2(hid_t error_stack, FILE * stream) + * \endcode + * This function prints the error stack specified by error_stack on the specified stream, stream. If the + * error stack is empty, a one‐line message will be printed. The following is an example of such a message. + * This message would be generated if the error was in the HDF5 Library. + * \code + * HDF5-DIAG: Error detected in HDF5 Library version: 1.10.9 thread 0. + * \endcode + * + * <em>To clear an error stack:</em> + * \code + * herr_t H5Eclear2(hid_t error_stack) + * \endcode + * The \ref H5Eclear2 function shown above clears the error stack specified by error_stack. + * \ref H5E_DEFAULT can be passed in to clear the current error stack. The current stack is also cleared + * whenever an API function is called; there are certain exceptions to this rule such as \ref H5Eprint2. + * + * \subsubsection subsubsec_error_ops_mute Mute Error Stack + * Sometimes an application calls a function for the sake of its return value, fully expecting the function + * to fail; sometimes the application wants to call \ref H5Eprint2 explicitly. In these situations, + * it would be misleading if an error message were still automatically printed. Using the + * \ref H5Eset_auto2 function can control the automatic printing of error messages. + * + * <em>To enable or disable automatic printing of errors:</em> + * \code + * herr_t H5Eset_auto2(hid_t error_stack, H5E_auto_t func, void *client_data) + * \endcode + * The \ref H5Eset_auto2 function can be used to turn on or off the automatic printing of errors + * for the error stack specified by error_stack. When turned on (non‐null func pointer), any API function + * which returns an error indication will first call func, passing it client_data as an argument. When the + * library is first initialized the auto printing function is set to \ref H5Eprint2 and client_data + * is the standard error stream pointer, stderr. + * + * <em>To see the current settings:</em> + * \code + * herr_t H5Eget_auto(hid_t error_stack, H5E_auto_t * func, void **client_data) + * \endcode + * The function above returns the current settings for the automatic error stack traversal function, func, and + * its data, client_data. If either or both of the arguments are null, then the value is not returned. + * + * <table> + * <caption align=top>Example: Turn off error messages while probing a function</caption> + * <tr> + * <td> + * <p>An application can temporarily turn off error messages while “probing” a function. See the + * example below. + * <p><code><pre> + * *** Save old error handler *** + * H5E_auto2_t oldfunc; + * void *old_client_data; + * H5Eget_auto2(error_stack, &old_func, &old_client_data); + * *** Turn off error handling *** + * H5Eset_auto2(error_stack, NULL, NULL); + * *** Probe. Likely to fail, but that’s okay *** + * status = H5Fopen (......); + * *** Restore previous error handler *** + * H5Eset_auto2(error_stack, old_func, old_client_data); + * </pre></code> + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Example: Disable automatic printing and explicitly print error messages</caption> + * <tr> + * <td> + * <p>Or automatic printing can be disabled altogether and error messages can be explicitly printed. + * <p><code><pre> + * *** Turn off error handling permanently *** + * H5Eset_auto2(error_stack, NULL, NULL); + * *** If failure, print error message *** + * if (H5Fopen (....)<0) { + * H5Eprint2(H5E_DEFAULT, stderr); + * exit (1); + * } + * </pre></code> + * </td> + * </tr> + * </table> + * + * + * \subsubsection subsubsec_error_ops_custom_print Customized Printing of an Error Stack + * Applications are allowed to define an automatic error traversal function other than the default + * \ref H5Eprint(). For instance, one can define a function that prints a simple, one‐line error message to + * the standard error stream and then exits. The first example below defines a such a function. The second + * example below installs the function as the error handler. + * + * <table> + * <caption align=top>Example: Defining a function to print a simple error message</caption> + * <tr> + * <td> + * <p><code><pre> + * herr_t + * my_hdf5_error_handler(void *unused) + * { + * fprintf (stderr, “An HDF5 error was detected. Bye.\\n”); + * exit (1); + * } + * + * </pre></code> + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Example: The user‐defined error handler</caption> + * <tr> + * <td> + * <p><code><pre> + * H5Eset_auto2(H5E_DEFAULT, my_hdf5_error_handler, NULL); + * </pre></code> + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_error_ops_walk Walk through the Error Stack + * The \ref H5Eprint2 function is actually just a wrapper around the more complex \ref H5Ewalk function + * which traverses an error stack and calls a user‐defined function for each member of the stack. The example + * below shows how \ref H5Ewalk is used. + * \code + * herr_t H5Ewalk(hid_t err_stack, H5E_direction_t direction, + * H5E_walk_t func, void *client_data) + * \endcode + * The error stack err_stack is traversed and func is called for each member of the stack. Its arguments + * are an integer sequence number beginning at zero (regardless of direction) and the client_data + * pointer. If direction is \ref H5E_WALK_UPWARD, then traversal begins at the inner‐most function that + * detected the error and concludes with the API function. Use \ref H5E_WALK_DOWNWARD for the opposite + * order. + * + * \subsubsection subsubsec_error_ops_travers Traverse an Error Stack with a Callback Function + * An error stack traversal callback function takes three arguments: n is a sequence number beginning at + * zero for each traversal, eptr is a pointer to an error stack member, and client_data is the same pointer + * used in the example above passed to \ref H5Ewalk. See the example below. + * \code + * typedef herr_t (*H5E_walk_t)(unsigned n, H5E_error2_t *eptr, void *client_data) + * \endcode + * The H5E_error2_t structure is shown below. + * \code + * typedef struct { + * hid_t cls_id; + * hid_t maj_num; + * hid_t min_num; + * unsigned line; + * const char *func_name; + * const char *file_name; + * const char *desc; + * } H5E_error2_t; + * \endcode + * The maj_num and min_num are major and minor error IDs, func_name is the name of the function where + * the error was detected, file_name and line locate the error within the HDF5 Library source code, and + * desc points to a description of the error. + * + * <table> + * <caption align=top>Example: A user‐defined callback function</caption> + * <tr> + * <td> + * <p>The following example shows a user‐defined callback function. + * <p><code><pre> + * \#define MSG_SIZE 64 + * herr_t + * custom_print_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data) + * { + * FILE *stream = (FILE *)client_data; + * char maj[MSG_SIZE]; + * char min[MSG_SIZE]; + * char cls[MSG_SIZE]; + * const int indent = 4; + * + * *** Get descriptions for the major and minor error numbers *** + * if(H5Eget_class_name(err_desc->cls_id, cls, MSG_SIZE) < 0) + * TEST_ERROR; + * if(H5Eget_msg(err_desc->maj_num, NULL, maj, MSG_SIZE) < 0) + * TEST_ERROR; + * if(H5Eget_msg(err_desc->min_num, NULL, min, MSG_SIZE) < 0) + * TEST_ERROR; + * fprintf (stream, “%*serror #%03d: %s in %s(): + * line %u\\n”, + * indent, “”, n, err_desc->file_name, + * err_desc->func_name, err_desc->line); + * fprintf (stream, “%*sclass: %s\\n”, indent*2, “”, cls); + * fprintf (stream, “%*smajor: %s\\n”, indent*2, “”, maj); + * fprintf (stream, “%*sminor: %s\\n”, indent*2, “”, min); + * return 0; + * error: + * return -1; + * } + * </pre></code> + * </td> + * </tr> + * </table> + * + * <h4>Programming Note for C++ Developers Using C Functions</h4> + * If a C routine that takes a function pointer as an argument is called from within C++ code, the C routine + * should be returned from normally. + * + * Examples of this kind of routine include callbacks such as \ref H5Pset_elink_cb and + * \ref H5Pset_type_conv_cb and + * functions such as \ref H5Tconvert and \ref H5Ewalk2. + * + * Exiting the routine in its normal fashion allows the HDF5 C Library to clean up its work properly. In other + * words, if the C++ application jumps out of the routine back to the C++ “catch” statement, the library is + * not given the opportunity to close any temporary data structures that were set up when the routine was + * called. The C++ application should save some state as the routine is started so that any problem that + * occurs might be diagnosed. + * + * \subsection subsec_error_adv Advanced Error Handling Operations + * The section above, see \ref subsec_error_ops, discusses the basic error + * handling operations of the library. In that section, all the error records on the error stack are from the + * library itself. In this section, we are going to introduce the operations that allow an application program + * to push its own error records onto the error stack once it declares an error class of its own through the + * HDF5 Error API. + * + * <table> + * <caption align=top>Example: An Error Report</caption> + * <tr> + * <td> + * <p>An error report shows both the library’s error record and the application’s error records. + * See the example below. + * <p><code><pre> + * Error Test-DIAG: Error detected in Error Program (1.0) + * thread 8192: + * #000: ../../hdf5/test/error_test.c line ### in main(): + * Error test failed + * major: Error in test + * minor: Error in subroutine + * #001: ../../hdf5/test/error_test.c line ### in + * test_error(): H5Dwrite failed as supposed to + * major: Error in IO + * minor: Error in H5Dwrite + * HDF5-DIAG: Error detected in HDF5 (1.10.9) thread #####: + * #002: ../../hdf5/src/H5Dio.c line ### in H5Dwrite(): + * not a dataset + * major: Invalid arguments to routine + * minor: Inappropriate type + * </pre></code> + * </td> + * </tr> + * </table> + * In the line above error record #002 in the example above, the starting phrase is HDF5. This is the error + * class name of the HDF5 Library. All of the library’s error messages (major and minor) are in this default + * error class. The Error Test in the beginning of the line above error record #000 is the name of the + * application’s error class. The first two error records, #000 and #001, are from application’s error class. + * By definition, an error class is a group of major and minor error messages for a library (the HDF5 Library + * or an application library built on top of the HDF5 Library) or an application program. The error class can + * be registered for a library or program through the HDF5 Error API. Major and minor messages can be defined + * in an error class. An application will have object handles for the error class and for major and minor + * messages for further operation. See the example below. + * + * <table> + * <caption align=top>Example: The user‐defined error handler</caption> + * <tr> + * <td> + * <p><code><pre> + * \#define MSG_SIZE 64 + * herr_t + * custom_print_cb(unsigned n, const H5E_error2_t *err_desc, + * void* client_data) + * { + * FILE *stream = (FILE *)client_data; + * char maj[MSG_SIZE]; + * char min[MSG_SIZE]; + * char cls[MSG_SIZE]; + * const int indent = 4; + * + * *** Get descriptions for the major and minor error numbers *** + * if(H5Eget_class_name(err_desc->cls_id, cls, MSG_SIZE) < 0) + * TEST_ERROR; + * if(H5Eget_msg(err_desc->maj_num, NULL, maj, MSG_SIZE) < 0) + * TEST_ERROR; + * if(H5Eget_msg(err_desc->min_num, NULL, min, MSG_SIZE) < 0) + * TEST_ERROR; + * fprintf (stream, “%*serror #%03d: %s in %s(): + * line %u\\n”, + * indent, “”, n, err_desc->file_name, + * err_desc->func_name, err_desc->line); + * fprintf (stream, “%*sclass: %s\\n”, indent*2, “”, cls); + * fprintf (stream, “%*smajor: %s\\n”, indent*2, “”, maj); + * fprintf (stream, “%*sminor: %s\\n”, indent*2, “”, min); + * return 0; + * error: + * return -1; + * } + * </pre></code> + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_error_adv_more More Error API Functions + * The Error API has functions that can be used to register or unregister an error class, to create or close + * error messages, and to query an error class or error message. These functions are illustrated below. + * + * <em>To register an error class:</em> + * \code + * hid_t H5Eregister_class(const char* cls_name, const char* lib_name, const char* version) + * \endcode + * This function registers an error class with the HDF5 Library so that the application library or program + * can report errors together with the HDF5 Library. + * + * <em>To add an error message to an error class:</em> + * \code + * hid_t H5Ecreate_msg(hid_t class, H5E_type_t msg_type, const char* mesg) + * \endcode + * This function adds an error message to an error class defined by an application library or program. The + * error message can be either major or minor which is indicated by parameter msg_type. + * + * <em>To get the name of an error class:</em> + * \code + * ssize_t H5Eget_class_name(hid_t class_id, char* name, size_t size) + * \endcode + * This function retrieves the name of the error class specified by the class ID. + * + * <em>To retrieve an error message:</em> + * \code + * ssize_t H5Eget_msg(hid_t mesg_id, H5E_type_t* mesg_type, char* mesg, size_t size) + * \endcode + * This function retrieves the error message including its length and type. + * + * <em>To close an error message:</em> + * \code + * herr_t H5Eclose_msg(hid_t mesg_id) + * \endcode + * This function closes an error message. + * + * <em>To remove an error class:</em> + * \code + * herr_t H5Eunregister_class(hid_t class_id) + * \endcode + * This function removes an error class from the Error API. + * + * <table> + * <caption align=top>Example: Create an error class and error messages</caption> + * <tr> + * <td> + * <p>The example below shows how an application creates an error class and error messages. + * <p><code><pre> + * *** Create an error class *** + * class_id = H5Eregister_class(ERR_CLS_NAME, PROG_NAME, PROG_VERS); + * *** Retrieve class name *** + * H5Eget_class_name(class_id, cls_name, cls_size); + * *** Create a major error message in the class *** + * maj_id = H5Ecreate_msg(class_id, H5E_MAJOR, “... ...”); + * *** Create a minor error message in the class *** + * min_id = H5Ecreate_msg(class_id, H5E_MINOR, “... ...”); + * </pre></code> + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Example: Closing error messages and unregistering the error class</caption> + * <tr> + * <td> + * <p>The example below shows how an application closes error messages and unregisters the error + * class. + * <p><code><pre> + * H5Eclose_msg(maj_id); + * H5Eclose_msg(min_id); + * H5Eunregister_class(class_id); + * </pre></code> + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_error_adv_app Pushing an Application Error Message onto Error Stack + * An application can push error records onto or pop error records off of the error stack just as the library + * does internally. An error stack can be registered, and an object handle can be returned to the application + * so that the application can manipulate a registered error stack. + * + * <em>To register the current stack:</em> + * \code + * hid_t H5Eget_current_stack(void) + * \endcode + * This function registers the current error stack, returns an object handle, and clears the current error + * stack. + * An empty error stack will also be assigned an ID. + * + * <em>To replace the current error stack with another:</em> + * \code + * herr_t H5Eset_current_stack(hid_t error_stack) + * \endcode + * This function replaces the current error stack with another error stack specified by error_stack and + * clears the current error stack. The object handle error_stack is closed after this function call. + * + * <em>To push a new error record to the error stack:</em> + * \code + * herr_t H5Epush(hid_t error_stack, const char* file, const char* func, + * unsigned line, hid_t cls_id, hid_t major_id, hid_t minor_id, + * const char* desc, ... ) + * \endcode + * This function pushes a new error record onto the error stack for the current thread. + * + * <em>To delete some error messages:</em> + * \code + * herr_t H5Epop(hid_t error_stack, size_t count) + * \endcode + * This function deletes some error messages from the error stack. + * + * <em>To retrieve the number of error records:</em> + * \code + * int H5Eget_num(hid_t error_stack) + * \endcode + * This function retrieves the number of error records from an error stack. + * + * <em>To clear the error stack:</em> + * \code + * herr_t H5Eclear_stack(hid_t error_stack) + * \endcode + * This function clears the error stack. + * + * <em>To close the object handle for an error stack:</em> + * \code + * herr_t H5Eclose_stack(hid_t error_stack) + * \endcode + * This function closes the object handle for an error stack and releases its resources. + * + * <table> + * <caption align=top>Example: Pushing an error message to an error stack</caption> + * <tr> + * <td> + * <p>The example below shows how an application pushes an error record onto the default error stack. + * <p><code><pre> + * *** Make call to HDF5 I/O routine *** + * if((dset_id=H5Dopen(file_id, dset_name, access_plist)) < 0) + * { + * *** Push client error onto error stack *** + * H5Epush(H5E_DEFAULT,__FILE__,FUNC,__LINE__,cls_id, + * CLIENT_ERR_MAJ_IO,CLIENT_ERR_MINOR_OPEN, “H5Dopen failed”); + * } + * *** Indicate error occurred in function *** + * return 0; + * </pre></code> + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Example: Registering the error stack</caption> + * <tr> + * <td> + * <p>The example below shows how an application registers the current error stack and + * creates an object handle to avoid another HDF5 function from clearing the error stack. + * <p><code><pre> + * if (H5Dwrite(dset_id, mem_type_id, mem_space_id, file_space_id, dset_xfer_plist_id, buf) < 0) + * { + * *** Push client error onto error stack *** + * H5Epush2(H5E_DEFAULT,__FILE__,FUNC,__LINE__,cls_id, + * CLIENT_ERR_MAJ_IO,CLIENT_ERR_MINOR_HDF5, + * “H5Dwrite failed”); + * *** Preserve the error stack by assigning an object handle to it *** + * error_stack = H5Eget_current_stack(); + * *** Close dataset *** + * H5Dclose(dset_id); + * *** Replace the current error stack with the preserved one *** + * H5Eset_current_stack(error_stack); + * } + * return 0; + * </pre></code> + * </td> + * </tr> + * </table> + * + * Previous Chapter \ref sec_attribute - Next Chapter \ref sec_plist + * + * \defgroup H5E Error Handling (H5E) * * \internal The \c FUNC_ENTER macro clears the error stack whenever an * interface function is entered. When an error is detected, an entry @@ -77,6 +605,8 @@ * error stack. The error stack is statically allocated to reduce the * complexity of handling errors within the \ref H5E package. * + * @see sec_error + * */ #endif /* H5Emodule_H */ diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 0254c37..6e47d28 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -899,8 +899,8 @@ H5_DLL herr_t H5Ewalk1(H5E_direction_t direction, H5E_walk1_t func, void *client * * \deprecated 1.8.0 Function deprecated in this release. * - * \details Given a major error number, H5Eget_major() returns a constant - * character string that describes the error. + * \details H5Eget_major() returns a constant + * character string that describes the error, given a major error number. * * \attention This function returns a dynamically allocated string (\c char * array). An application calling this function must free the memory @@ -920,8 +920,8 @@ H5_DLL char *H5Eget_major(H5E_major_t maj); * * \deprecated 1.8.0 Function deprecated and return type changed in this release. * - * \details Given a minor error number, H5Eget_minor() returns a constant - * character string that describes the error. + * \details H5Eget_minor() returns a constant + * character string that describes the error, given a minor error number. * * \attention In the Release 1.8.x series, H5Eget_minor() returns a string of * dynamic allocated \c char array. An application calling this diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h index a70f34b..ba508eb 100644 --- a/src/H5FDmpio.h +++ b/src/H5FDmpio.h @@ -104,10 +104,10 @@ H5_DLL herr_t H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info); * \param[out] info MPI-2 info object * \returns \herr_t * - * \details If the file access property list is set to the #H5FD_MPIO driver, - * H5Pget_fapl_mpio() returns duplicates of the stored MPI communicator + * \details H5Pget_fapl_mpio() returns duplicates of the stored MPI communicator * and Info object through the \p comm and \p info pointers, if those - * values are non-null. + * values are non-null. The file access property list must be set to the + * #H5FD_MPIO driver. * * Since the MPI communicator and Info object are duplicates of the * stored information, future modifications to the access property list diff --git a/src/H5FDsec2.h b/src/H5FDsec2.h index 541ac71..d0811ed 100644 --- a/src/H5FDsec2.h +++ b/src/H5FDsec2.h @@ -26,7 +26,21 @@ extern "C" { #endif -H5_DLL hid_t H5FD_sec2_init(void); +H5_DLL hid_t H5FD_sec2_init(void); +/** + * \ingroup FAPL + * + * \brief Sets the sec2 driver + * + * \fapl_id + * \returns \herr_t + * + * \details H5Pset_fapl_sec2() modifies the file access property list to use + * the sec2 driver, H5FDsec2. + * + * \since 1.4.0 + * + */ H5_DLL herr_t H5Pset_fapl_sec2(hid_t fapl_id); #ifdef __cplusplus diff --git a/src/H5FDstdio.h b/src/H5FDstdio.h index 9db92ed..6d1cdf3 100644 --- a/src/H5FDstdio.h +++ b/src/H5FDstdio.h @@ -38,7 +38,7 @@ H5_DLL hid_t H5FD_stdio_init(void); * \returns \herr_t * * \details H5Pset_fapl_stdio() modifies the file access property list to use - * the standard I/O driver, H5FDstdio(). + * the standard I/O driver, H5FDstdio. * * \since 1.4.0 * diff --git a/src/H5Fmodule.h b/src/H5Fmodule.h index 81c1ede..523d6bf 100644 --- a/src/H5Fmodule.h +++ b/src/H5Fmodule.h @@ -29,7 +29,1448 @@ #define H5_MY_PKG_ERR H5E_FILE #define H5_MY_PKG_INIT YES -/**\defgroup H5F H5F +/** \page H5F_UG The HDF5 File + * + * \section sec_file The HDF5 File + * \subsection subsec_file_intro Introduction + * The purpose of this chapter is to describe how to work with HDF5 data files. + * + * If HDF5 data is to be written to or read from a file, the file must first be explicitly created or + * opened with the appropriate file driver and access privileges. Once all work with the file is + * complete, the file must be explicitly closed. + * + * This chapter discusses the following: + * \li File access modes + * \li Creating, opening, and closing files + * \li The use of file creation property lists + * \li The use of file access property lists + * \li The use of low-level file drivers + * + * This chapter assumes an understanding of the material presented in the data model chapter. For + * more information, @see @ref sec_data_model. + * + * \subsection subsec_file_access_modes File Access Modes + * There are two issues regarding file access: + * <ul><li>What should happen when a new file is created but a file of the same name already + * exists? Should the create action fail, or should the existing file be overwritten?</li> + * <li>Is a file to be opened with read-only or read-write access?</li></ul> + * + * Four access modes address these concerns. Two of these modes can be used with #H5Fcreate, and + * two modes can be used with #H5Fopen. + * \li #H5Fcreate accepts #H5F_ACC_EXCL or #H5F_ACC_TRUNC + * \li #H5Fopen accepts #H5F_ACC_RDONLY or #H5F_ACC_RDWR + * + * The access modes are described in the table below. + * + * <table> + * <caption>Access flags and modes</caption> + * <tr> + * <th>Access Flag</th> + * <th>Resulting Access Mode</th> + * </tr> + * <tr> + * <td>#H5F_ACC_EXCL</td> + * <td>If the file already exists, #H5Fcreate fails. If the file does not exist, + * it is created and opened with read-write access. (Default)</td> + * </tr> + * <tr> + * <td>#H5F_ACC_TRUNC</td> + * <td>If the file already exists, the file is opened with read-write access, + * and new data will overwrite any existing data. If the file does not exist, + * it is created and opened with read-write access.</td> + * </tr> + * <tr> + * <td>#H5F_ACC_RDONLY</td> + * <td>An existing file is opened with read-only access. If the file does not + * exist, #H5Fopen fails. (Default)</td> + * </tr> + * <tr> + * <td>#H5F_ACC_RDWR</td> + * <td>An existing file is opened with read-write access. If the file does not + * exist, #H5Fopen fails.</td> + * </tr> + * </table> + * + * By default, #H5Fopen opens a file for read-only access; passing #H5F_ACC_RDWR allows + * read-write access to the file. + * + * By default, #H5Fcreate fails if the file already exists; only passing #H5F_ACC_TRUNC allows + * the truncating of an existing file. + * + * \subsection subsec_file_creation_access File Creation and File Access Properties + * File creation and file access property lists control the more complex aspects of creating and + * accessing files. + * + * File creation property lists control the characteristics of a file such as the size of the userblock, + * a user-definable data block; the size of data address parameters; properties of the B-trees that are + * used to manage the data in the file; and certain HDF5 Library versioning information. + * + * For more information, @see @ref subsubsec_file_property_lists_props. + * + * This section has a more detailed discussion of file creation properties. If you have no special + * requirements for these file characteristics, you can simply specify #H5P_DEFAULT for the default + * file creation property list when a file creation property list is called for. + * + * File access property lists control properties and means of accessing a file such as data alignment + * characteristics, metadata block and cache sizes, data sieve buffer size, garbage collection + * settings, and parallel I/O. Data alignment, metadata block and cache sizes, and data sieve buffer + * size are factors in improving I/O performance. + * + * For more information, @see @ref subsubsec_file_property_lists_access. + * + * This section has a more detailed discussion of file access properties. If you have no special + * requirements for these file access characteristics, you can simply specify #H5P_DEFAULT for the + * default file access property list when a file access property list is called for. + * + * <table> + * <caption>Figure 10 - More sample file structures</caption> + * <tr> + * <td> + * \image html UML_FileAndProps.gif "UML model for an HDF5 file and its property lists" + * </td> + * </tr> + * </table> + * + * \subsection subsec_file_drivers Low-level File Drivers + * The concept of an HDF5 file is actually rather abstract: the address space for what is normally + * thought of as an HDF5 file might correspond to any of the following at the storage level: + * \li Single file on a standard file system + * \li Multiple files on a standard file system + * \li Multiple files on a parallel file system + * \li Block of memory within an application’s memory space + * \li More abstract situations such as virtual files + * + * This HDF5 address space is generally referred to as an HDF5 file regardless of its organization at + * the storage level. + * + * HDF5 accesses a file (the address space) through various types of low-level file drivers. The + * default HDF5 file storage layout is as an unbuffered permanent file which is a single, contiguous + * file on local disk. Alternative layouts are designed to suit the needs of a variety of systems, + * environments, and applications. + * + * \subsection subsec_file_program_model Programming Model for Files + * Programming models for creating, opening, and closing HDF5 files are described in the + * sub-sections below. + * + * \subsubsection subsubsec_file_program_model_create Creating a New File + * The programming model for creating a new HDF5 file can be summarized as follows: + * \li Define the file creation property list + * \li Define the file access property list + * \li Create the file + * + * First, consider the simple case where we use the default values for the property lists. See the + * example below. + * + * <em>Creating an HDF5 file using property list defaults</em> + * \code + * file_id = H5Fcreate ("SampleFile.h5", H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT) + * \endcode + * + * Note: The example above specifies that #H5Fcreate should fail if SampleFile.h5 already exists. + * + * A more complex case is shown in the example below. In this example, we define file creation + * and access property lists (though we do not assign any properties), specify that #H5Fcreate + * should fail if SampleFile.h5 already exists, and create a new file named SampleFile.h5. The example + * does not specify a driver, so the default driver, #H5FD_SEC2, will be used. + * + * <em>Creating an HDF5 file using property lists</em> + * \code + * fcplist_id = H5Pcreate (H5P_FILE_CREATE) + * <...set desired file creation properties...> + * faplist_id = H5Pcreate (H5P_FILE_ACCESS) + * <...set desired file access properties...> + * file_id = H5Fcreate ("SampleFile.h5", H5F_ACC_EXCL, fcplist_id, faplist_id) + * \endcode + * Notes: + * 1. A root group is automatically created in a file when the file is first created. + * + * 2. File property lists, once defined, can be reused when another file is created within the same + * application. + * + * \subsubsection subsubsec_file_program_model_open Opening an Existing File + * The programming model for opening an existing HDF5 file can be summarized as follows: + * <ul><li>Define or modify the file access property list including a low-level file driver (optional)</li> + * <li>Open the file</li></ul> + * + * The code in the example below shows how to open an existing file with read-only access. + * + * <em>Opening an HDF5 file</em> + * \code + * faplist_id = H5Pcreate (H5P_FILE_ACCESS) + * status = H5Pset_fapl_stdio (faplist_id) + * file_id = H5Fopen ("SampleFile.h5", H5F_ACC_RDONLY, faplist_id) + * \endcode + * + * \subsubsection subsubsec_file_program_model_close Closing a File + * The programming model for closing an HDF5 file is very simple: + * \li Close file + * + * We close SampleFile.h5 with the code in the example below. + * + * <em>Closing an HDF5 file</em> + * \code + * status = H5Fclose (file_id) + * \endcode + * Note that #H5Fclose flushes all unwritten data to storage and that file_id is the identifier returned + * for SampleFile.h5 by #H5Fopen. + * + * More comprehensive discussions regarding all of these steps are provided below. + * + * \subsection subsec_file_h5dump Using h5dump to View a File + * h5dump is a command-line utility that is included in the HDF5 distribution. This program + * provides a straight-forward means of inspecting the contents of an HDF5 file. You can use + * h5dump to verify that a program is generating the intended HDF5 file. h5dump displays ASCII + * output formatted according to the HDF5 DDL grammar. + * + * The following h5dump command will display the contents of SampleFile.h5: + * \code + * h5dump SampleFile.h5 + * \endcode + * + * If no datasets or groups have been created in and no data has been written to the file, the output + * will look something like the following: + * \code + * HDF5 "SampleFile.h5" { + * GROUP "/" { + * } + * } + * \endcode + * + * Note that the root group, indicated above by /, was automatically created when the file was created. + * + * h5dump is described on the + * <a href="https://portal.hdfgroup.org/display/HDF5/h5dump">Tools</a> + * page under + * <a href="https://portal.hdfgroup.org/display/HDF5/Libraries+and+Tools+Reference"> + * Libraries and Tools Reference</a>. + * The HDF5 DDL grammar is described in the document \ref DDLBNF110. + * + * \subsection subsec_file_summary File Function Summaries + * General library (\ref H5 functions and macros), (\ref H5F functions), file related + * (\ref H5P functions), and file driver (\ref H5P functions) are listed below. + * + * <table> + * <caption>General library functions and macros</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5check_version</td> + * <td>Verifies that HDF5 library versions are consistent.</td> + * </tr> + * <tr> + * <td>#H5close</td> + * <td>Flushes all data to disk, closes all open identifiers, and cleans up memory.</td> + * </tr> + * <tr> + * <td>#H5dont_atexit</td> + * <td>Instructs the library not to install the atexit cleanup routine.</td> + * </tr> + * <tr> + * <td>#H5garbage_collect</td> + * <td>Garbage collects on all free-lists of all types.</td> + * </tr> + * <tr> + * <td>#H5get_libversion</td> + * <td>Returns the HDF library release number.</td> + * </tr> + * <tr> + * <td>#H5open</td> + * <td>Initializes the HDF5 library.</td> + * </tr> + * <tr> + * <td>#H5set_free_list_limits</td> + * <td>Sets free-list size limits.</td> + * </tr> + * <tr> + * <td>#H5_VERSION_GE</td> + * <td>Determines whether the version of the library being used is greater than or equal + * to the specified version.</td> + * </tr> + * <tr> + * <td>#H5_VERSION_LE</td> + * <td>Determines whether the version of the library being used is less than or equal + * to the specified version.</td> + * </tr> + * </table> + * + * <table> + * <caption>File functions </caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Fclear_elink_file_cache</td> + * <td>Clears the external link open file cache for a file.</td> + * </tr> + * <tr> + * <td>#H5Fclose</td> + * <td>Closes HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Fcreate</td> + * <td>Creates new HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Fflush</td> + * <td>Flushes data to HDF5 file on storage medium.</td> + * </tr> + * <tr> + * <td>#H5Fget_access_plist</td> + * <td>Returns a file access property list identifier.</td> + * </tr> + * <tr> + * <td>#H5Fget_create_plist</td> + * <td>Returns a file creation property list identifier.</td> + * </tr> + * <tr> + * <td>#H5Fget_file_image</td> + * <td>Retrieves a copy of the image of an existing, open file.</td> + * </tr> + * <tr> + * <td>#H5Fget_filesize</td> + * <td>Returns the size of an HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Fget_freespace</td> + * <td>Returns the amount of free space in a file.</td> + * </tr> + * <tr> + * <td>#H5Fget_info</td> + * <td>Returns global information for a file.</td> + * </tr> + * <tr> + * <td>#H5Fget_intent</td> + * <td>Determines the read/write or read-only status of a file.</td> + * </tr> + * <tr> + * <td>#H5Fget_mdc_config</td> + * <td>Obtain current metadata cache configuration for target file.</td> + * </tr> + * <tr> + * <td>#H5Fget_mdc_hit_rate</td> + * <td>Obtain target file’s metadata cache hit rate.</td> + * </tr> + * <tr> + * <td>#H5Fget_mdc_size</td> + * <td>Obtain current metadata cache size data for specified file.</td> + * </tr> + * <tr> + * <td>#H5Fget_mpi_atomicity</td> + * <td>Retrieves the atomicity mode in use.</td> + * </tr> + * <tr> + * <td>#H5Fget_name</td> + * <td>Retrieves the name of the file to which the object belongs.</td> + * </tr> + * <tr> + * <td>#H5Fget_obj_count</td> + * <td>Returns the number of open object identifiers for an open file.</td> + * </tr> + * <tr> + * <td>#H5Fget_obj_ids</td> + * <td>Returns a list of open object identifiers.</td> + * </tr> + * <tr> + * <td>#H5Fget_vfd_handle</td> + * <td>Returns pointer to the file handle from the virtual file driver.</td> + * </tr> + * <tr> + * <td>#H5Fis_hdf5</td> + * <td>Determines whether a file is in the HDF5 format.</td> + * </tr> + * <tr> + * <td>#H5Fmount</td> + * <td>Mounts a file.</td> + * </tr> + * <tr> + * <td>#H5Fopen</td> + * <td>Opens an existing HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Freopen</td> + * <td>Returns a new identifier for a previously-opened HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Freset_mdc_hit_rate_stats</td> + * <td>Reset hit rate statistics counters for the target file.</td> + * </tr> + * <tr> + * <td>#H5Fset_mdc_config</td> + * <td>Use to configure metadata cache of target file.</td> + * </tr> + * <tr> + * <td>#H5Fset_mpi_atomicity</td> + * <td>Use to set the MPI atomicity mode.</td> + * </tr> + * <tr> + * <td>#H5Funmount</td> + * <td>Unmounts a file.</td> + * </tr> + * </table> + * + * <table> + * <caption>File creation property list functions </caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_userblock/#H5Pget_userblock</td> + * <td>Sets/retrieves size of userblock.</td> + * </tr> + * <tr> + * <td>#H5Pset_sizes/#H5Pget_sizes</td> + * <td>Sets/retrieves byte size of offsets and lengths used to address objects in HDF5 file.</td> + * </tr> + * <tr> + * <td>#H5Pset_sym_k/#H5Pget_sym_k</td> + * <td>Sets/retrieves size of parameters used to control symbol table nodes.</td> + * </tr> + * <tr> + * <td>#H5Pset_istore_k/#H5Pget_istore_k</td> + * <td>Sets/retrieves size of parameter used to control B-trees for indexing chunked datasets.</td> + * </tr> + * <tr> + * <td>#H5Pset_file_image</td> + * <td>Sets an initial file image in a memory buffer.</td> + * </tr> + * <tr> + * <td>#H5Pget_file_image</td> + * <td>Retrieves a copy of the file image designated as the initial content and structure of a file.</td> + * </tr> + * <tr> + * <td>#H5Pset_shared_mesg_nindexes/#H5Pget_shared_mesg_nindexes</td> + * <td>Sets or retrieves number of shared object header message indexes in file + * creation property list.</td> + * </tr> + * <tr> + * <td>#H5Pset_shared_mesg_index</td> + * <td>Configures the specified shared object header message index.</td> + * </tr> + * <tr> + * <td>#H5Pget_shared_mesg_index</td> + * <td>Retrieves the configuration settings for a shared message index.</td> + * </tr> + * <tr> + * <td>#H5Pset_shared_mesg_phase_change/#H5Pget_shared_mesg_phase_change</td> + * <td>Sets or retrieves shared object header message storage phase change thresholds.</td> + * </tr> + * <tr> + * <td>#H5Pget_version</td> + * <td></td> + * </tr> + * </table> + * + * <table> + * <caption>File access property list functions </caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_alignment/#H5Pget_alignment</td> + * <td>Sets/retrieves alignment properties.</td> + * </tr> + * <tr> + * <td>#H5Pset_cache/#H5Pget_cache</td> + * <td>Sets/retrieves metadata cache and raw data chunk cache parameters.</td> + * </tr> + * <tr> + * <td>#H5Pset_elink_file_cache_size/#H5Pget_elink_file_cache_size</td> + * <td>Sets/retrieves the size of the external link open file cache from the specified + * file access property list.</td> + * </tr> + * <tr> + * <td>#H5Pset_gc_references/#H5Pget_gc_references</td> + * <td>Sets/retrieves garbage collecting references flag.</td> + * </tr> + * <tr> + * <td>#H5Pset_family_offset</td> + * <td>Sets offset property for low-level access to a file in a family of files.</td> + * </tr> + * <tr> + * <td>#H5Pget_family_offset</td> + * <td>Retrieves a data offset from the file access property list.</td> + * </tr> + * <tr> + * <td>#H5Pset_meta_block_size/#H5Pget_meta_block_size</td> + * <td>Sets the minimum metadata blocksize or retrieves the current metadata block size setting.</td> + * </tr> + * <tr> + * <td>#H5Pset_mdc_config</td> + * <td>Set the initial metadata cache configuration in the indicated File Access Property List + * to the supplied value.</td> + * </tr> + * <tr> + * <td>#H5Pget_mdc_config</td> + * <td>Get the current initial metadata cache config-uration from the indicated File Access + * Property List.</td> + * </tr> + * <tr> + * <td>#H5Pset_sieve_buf_size/#H5Pget_sieve_buf_size</td> + * <td>Sets/retrieves maximum size of data sieve buffer.</td> + * </tr> + * <tr> + * <td>#H5Pset_libver_bounds</td> + * <td>Sets bounds on library versions, and indirectly format versions, to be used + * when creating objects.</td> + * </tr> + * <tr> + * <td>#H5Pget_libver_bounds</td> + * <td>Retrieves library version bounds settings that indirectly control the format + * versions used when creating objects.</td> + * </tr> + * <tr> + * <td>#H5Pset_small_data_block_size</td> + * <td>Sets the size of a contiguous block reserved for small data.</td> + * </tr> + * <tr> + * <td>#H5Pget_small_data_block_size</td> + * <td>Retrieves the current small data block size setting.</td> + * </tr> + * </table> + * + * <table> + * <caption>File driver functions </caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_driver</td> + * <td>Sets a file driver.</td> + * </tr> + * <tr> + * <td>#H5Pget_driver</td> + * <td>Returns the identifier for the driver used to create a file.</td> + * </tr> + * <tr> + * <td>#H5Pget_driver_info</td> + * <td>Returns a pointer to file driver information.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_core/#H5Pget_fapl_core</td> + * <td>Sets the driver for buffered memory files (in RAM) or retrieves information regarding + * the driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_direct/#H5Pget_fapl_direct</td> + * <td>Sets up use of the direct I/O driver or retrieves the direct I/O driver settings.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_family/#H5Pget_fapl_family</td> + * <td>Sets driver for file families, designed for systems that do not support files + * larger than 2 gigabytes, or retrieves information regarding driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_log</td> + * <td>Sets logging driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_mpio/#H5Pget_fapl_mpio</td> + * <td>Sets driver for files on parallel file systems (MPI I/O) or retrieves information + * regarding the driver.</td> + * </tr> + * <tr> + * <td>H5Pset_fapl_mpiposix/H5Pget_fapl_mpiposix</td> + * <td>No longer available.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_multi/#H5Pget_fapl_multi</td> + * <td>Sets driver for multiple files, separating categories of metadata and raw data, + * or retrieves information regarding driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_sec2</td> + * <td>Sets driver for unbuffered permanent files or retrieves information regarding driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_split</td> + * <td>Sets driver for split files, a limited case of multiple files with one metadata file + * and one raw data file.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_stdio</td> + * <td>Sets driver for buffered permanent files.</td> + * </tr> + * <tr> + * <td>#H5Pset_fapl_windows</td> + * <td>Sets the Windows I/O driver.</td> + * </tr> + * <tr> + * <td>#H5Pset_multi_type</td> + * <td>Specifies type of data to be accessed via the MULTI driver enabling more direct access.</td> + * </tr> + * <tr> + * <td>#H5Pget_multi_type</td> + * <td>Retrieves type of data property for MULTI driver.</td> + * </tr> + * </table> + * + * \subsection subsec_file_create Creating or Opening an HDF5 File + * This section describes in more detail how to create and how to open files. + * + * New HDF5 files are created and opened with #H5Fcreate; existing files are opened with + * #H5Fopen. Both functions return an object identifier which must eventually be released by calling + * #H5Fclose. + * + * To create a new file, call #H5Fcreate: + * \code + * hid_t H5Fcreate (const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) + * \endcode + * + * #H5Fcreate creates a new file named name in the current directory. The file is opened with read + * and write access; if the #H5F_ACC_TRUNC flag is set, any pre-existing file of the same name in + * the same directory is truncated. If #H5F_ACC_TRUNC is not set or #H5F_ACC_EXCL is set and + * if a file of the same name exists, #H5Fcreate will fail. + * + * The new file is created with the properties specified in the property lists fcpl_id and fapl_id. + * fcpl is short for file creation property list. fapl is short for file access property list. Specifying + * #H5P_DEFAULT for either the creation or access property list will use the library’s default + * creation or access properties. + * + * If #H5Fcreate successfully creates the file, it returns a file identifier for the new file. This + * identifier will be used by the application any time an object identifier, an OID, for the file is + * required. Once the application has finished working with a file, the identifier should be released + * and the file closed with #H5Fclose. + * + * To open an existing file, call #H5Fopen: + * \code + * hid_t H5Fopen (const char *name, unsigned flags, hid_t fapl_id) + * \endcode + * + * #H5Fopen opens an existing file with read-write access if #H5F_ACC_RDWR is set and read-only + * access if #H5F_ACC_RDONLY is set. + * + * fapl_id is the file access property list identifier. Alternatively, #H5P_DEFAULT indicates that the + * application relies on the default I/O access parameters. Creating and changing access property + * lists is documented further below. + * + * A file can be opened more than once via multiple #H5Fopen calls. Each such call returns a unique + * file identifier and the file can be accessed through any of these file identifiers as long as they + * remain valid. Each of these file identifiers must be released by calling #H5Fclose when it is no + * longer needed. + * + * For more information, @see @ref subsubsec_file_property_lists_access. + * For more information, @see @ref subsec_file_property_lists. + * + * \subsection subsec_file_closes Closing an HDF5 File + * #H5Fclose both closes a file and releases the file identifier returned by #H5Fopen or #H5Fcreate. + * #H5Fclose must be called when an application is done working with a file; while the HDF5 + * Library makes every effort to maintain file integrity, failure to call #H5Fclose may result in the + * file being abandoned in an incomplete or corrupted state. + * + * To close a file, call #H5Fclose: + * \code + * herr_t H5Fclose (hid_t file_id) + * \endcode + * This function releases resources associated with an open file. After closing a file, the file + * identifier, file_id, cannot be used again as it will be undefined. + * + * #H5Fclose fulfills three purposes: to ensure that the file is left in an uncorrupted state, to ensure + * that all data has been written to the file, and to release resources. Use #H5Fflush if you wish to + * ensure that all data has been written to the file but it is premature to close it. + * + * Note regarding serial mode behavior: When #H5Fclose is called in serial mode, it closes the file + * and terminates new access to it, but it does not terminate access to objects that remain + * individually open within the file. That is, if #H5Fclose is called for a file but one or more objects + * within the file remain open, those objects will remain accessible until they are individually + * closed. To illustrate, assume that a file, fileA, contains a dataset, data_setA, and that both are + * open when #H5Fclose is called for fileA. data_setA will remain open and accessible, including + * writable, until it is explicitly closed. The file will be automatically and finally closed once all + * objects within it have been closed. + * + * Note regarding parallel mode behavior: Once #H5Fclose has been called in parallel mode, access + * is no longer available to any object within the file. + * + * \subsection subsec_file_property_lists File Property Lists + * Additional information regarding file structure and access are passed to #H5Fcreate and + * #H5Fopen through property list objects. Property lists provide a portable and extensible method of + * modifying file properties via simple API functions. There are two kinds of file-related property + * lists: + * \li File creation property lists + * \li File access property lists + * + * In the following sub-sections, we discuss only one file creation property, userblock size, in detail + * as a model for the user. Other file creation and file access properties are mentioned and defined + * briefly, but the model is not expanded for each; complete syntax, parameter, and usage + * information for every property list function is provided in the \ref H5P + * section of the HDF5 Reference Manual. + * + * For more information, @see @ref sec_plist. + * + * \subsubsection subsubsec_file_property_lists_create Creating a Property List + * If you do not wish to rely on the default file creation and access properties, you must first create + * a property list with #H5Pcreate. + * \code + * hid_t H5Pcreate (hid_t cls_id) + * \endcode + * cls_id is the type of property list being created. In this case, the appropriate values are + * #H5P_FILE_CREATE for a file creation property list and #H5P_FILE_ACCESS for a file access + * property list. + * + * Thus, the following calls create a file creation property list and a file access property list with + * identifiers fcpl_id and fapl_id, respectively: + * \code + * fcpl_id = H5Pcreate (H5P_FILE_CREATE) + * fapl_id = H5Pcreate (H5P_FILE_ACCESS) + * \endcode + * + * Once the property lists have been created, the properties themselves can be modified via the + * functions described in the following sub-sections. + * + * \subsubsection subsubsec_file_property_lists_props File Creation Properties + * File creation property lists control the file metadata, which is maintained in the superblock of the + * file. These properties are used only when a file is first created. + * + * <h4>Userblock Size</h4> + * \code + * herr_t H5Pset_userblock (hid_t plist, hsize_t size) + * herr_t H5Pget_userblock (hid_t plist, hsize_t *size) + * \endcode + * + * The userblock is a fixed-length block of data located at the beginning of the file and is ignored + * by the HDF5 library. This block is specifically set aside for any data or information that + * developers determine to be useful to their applications but that will not be used by the HDF5 + * library. The size of the userblock is defined in bytes and may be set to any power of two with a + * minimum size of 512 bytes. In other words, userblocks might be 512, 1024, or 2048 bytes in + * size. + * + * This property is set with #H5Pset_userblock and queried via #H5Pget_userblock. For example, if + * an application needed a 4K userblock, then the following function call could be used: + * \code + * status = H5Pset_userblock(fcpl_id, 4096) + * \endcode + * + * The property list could later be queried with: + * \code + * status = H5Pget_userblock(fcpl_id, size) + * \endcode + * and the value 4096 would be returned in the parameter size. + * + * Other properties, described below, are set and queried in exactly the same manner. Syntax and + * usage are detailed in the @ref H5P section of the HDF5 Reference Manual. + * + * <h4>Offset and Length Sizes</h4> + * This property specifies the number of bytes used to store the offset and length of objects in the + * HDF5 file. Values of 2, 4, and 8 bytes are currently supported to accommodate 16-bit, 32-bit, + * and 64-bit file address spaces. + * + * These properties are set and queried via #H5Pset_sizes and #H5Pget_sizes. + * + * <h4>Symbol Table Parameters</h4> + * The size of symbol table B-trees can be controlled by setting the 1/2-rank and 1/2-node size + * parameters of the B-tree. + * + * These properties are set and queried via #H5Pset_sym_k and #H5Pget_sym_k + * + * <h4>Indexed Storage Parameters</h4> + * The size of indexed storage B-trees can be controlled by setting the 1/2-rank and 1/2-node size + * parameters of the B-tree. + * + * These properties are set and queried via #H5Pset_istore_k and #H5Pget_istore_k. + * + * <h4>Version Information</h4> + * Various objects in an HDF5 file may over time appear in different versions. The HDF5 Library + * keeps track of the version of each object in the file. + * + * Version information is retrieved via #H5Pget_version. + * + * \subsubsection subsubsec_file_property_lists_access File Access Properties + * This section discusses file access properties that are not related to the low-level file drivers. File + * drivers are discussed separately later in this chapter. + * For more information, @see @ref subsec_file_alternate_drivers. + * + * File access property lists control various aspects of file I/O and structure. + * + * <h4>Data Alignment</h4> + * Sometimes file access is faster if certain data elements are aligned in a specific manner. This can + * be controlled by setting alignment properties via the #H5Pset_alignment function. There are two + * values involved: + * \li A threshold value + * \li An alignment interval + * + * Any allocation request at least as large as the threshold will be aligned on an address that is a + * multiple of the alignment interval. + * + * <h4>Metadata Block Allocation Size</h4> + * Metadata typically exists as very small chunks of data; storing metadata elements in a file + * without blocking them can result in hundreds or thousands of very small data elements in the + * file. This can result in a highly fragmented file and seriously impede I/O. By blocking metadata + * elements, these small elements can be grouped in larger sets, thus alleviating both problems. + * + * #H5Pset_meta_block_size sets the minimum size in bytes of metadata block allocations. + * #H5Pget_meta_block_size retrieves the current minimum metadata block allocation size. + * + * <h4>Metadata Cache</h4> + * Metadata and raw data I/O speed are often governed by the size and frequency of disk reads and + * writes. In many cases, the speed can be substantially improved by the use of an appropriate + * cache. + * + * #H5Pset_cache sets the minimum cache size for both metadata and raw data and a preemption + * value for raw data chunks. #H5Pget_cache retrieves the current values. + * + * <h4>Data Sieve Buffer Size</h4> + * Data sieve buffering is used by certain file drivers to speed data I/O and is most commonly when + * working with dataset hyperslabs. For example, using a buffer large enough to hold several pieces + * of a dataset as it is read in for hyperslab selections will boost performance noticeably. + * + * #H5Pset_sieve_buf_size sets the maximum size in bytes of the data sieve buffer. + * #H5Pget_sieve_buf_size retrieves the current maximum size of the data sieve buffer. + * + * <h4>Garbage Collection References</h4> + * Dataset region references and other reference types use space in an HDF5 file’s global heap. If + * garbage collection is on (1) and the user passes in an uninitialized value in a reference structure, + * the heap might become corrupted. When garbage collection is off (0), however, and the user reuses + * a reference, the previous heap block will be orphaned and not returned to the free heap + * space. When garbage collection is on, the user must initialize the reference structures to 0 or risk + * heap corruption. + * + * #H5Pset_gc_references sets the garbage collecting references flag. + * + * \subsection subsec_file_alternate_drivers Alternate File Storage Layouts and Low-level File Drivers + * The concept of an HDF5 file is actually rather abstract: the address space for what is normally + * thought of as an HDF5 file might correspond to any of the following: + * \li Single file on standard file system + * \li Multiple files on standard file system + * \li Multiple files on parallel file system + * \li Block of memory within application’s memory space + * \li More abstract situations such as virtual files + * + * This HDF5 address space is generally referred to as an HDF5 file regardless of its organization at + * the storage level. + * + * HDF5 employs an extremely flexible mechanism called the virtual file layer, or VFL, for file + * I/O. A full understanding of the VFL is only necessary if you plan to write your own drivers + * @see \ref VFL in the HDF5 Technical Notes. + * + * For our + * purposes here, it is sufficient to know that the low-level drivers used for file I/O reside in the + * VFL, as illustrated in the following figure. Note that H5FD_STREAM is not available with 1.8.x + * and later versions of the library. + * + * <table> + * <tr> + * <td> + * \image html VFL_Drivers.gif "I/O path from application to VFL and low-level drivers to storage" + * </td> + * </tr> + * </table> + * + * As mentioned above, HDF5 applications access HDF5 files through various low-level file + * drivers. The default driver for that layout is the POSIX driver (also known as the SEC2 driver), + * #H5FD_SEC2. Alternative layouts and drivers are designed to suit the needs of a variety of + * systems, environments, and applications. The drivers are listed in the table below. + * + * <table> + * <caption id="table_file_drivers">Supported file drivers</caption> + * <tr> + * <th>Driver Name</th> + * <th>Driver Identifier</th> + * <th>Description</th> + * <th>Related API</th> + * </tr> + * <tr> + * <td>POSIX</td> + * <td>#H5FD_SEC2</td> + * <td>This driver uses POSIX file-system functions like read and write to perform I/O to a single, + * permanent file on local disk with no system buffering. This driver is POSIX-compliant and is + * the default file driver for all systems.</td> + * <td>#H5Pset_fapl_sec2</td> + * </tr> + * <tr> + * <td>Direct</td> + * <td>#H5FD_DIRECT</td> + * <td>This is the #H5FD_SEC2 driver except data is written to or read from the file + * synchronously without being cached by the system.</td> + * <td>#H5Pset_fapl_direct</td> + * </tr> + * <tr> + * <td>Log</td> + * <td>#H5FD_LOG</td> + * <td>This is the #H5FD_SEC2 driver with logging capabilities.</td> + * <td>#H5Pset_fapl_log</td> + * </tr> + * <tr> + * <td>Windows</td> + * <td>#H5FD_WINDOWS</td> + * <td>This driver was modified in HDF5-1.8.8 to be a wrapper of the POSIX driver, + * #H5FD_SEC2. This change should not affect user applications.</td> + * <td>#H5Pset_fapl_windows</td> + * </tr> + * <tr> + * <td>STDIO</td> + * <td>#H5FD_STDIO</td> + * <td>This driver uses functions from the standard C stdio.h to perform I/O + * to a single, permanent file on local disk with additional system buffering.</td> + * <td>#H5Pset_fapl_stdio</td> + * </tr> + * <tr> + * <td>Memory</td> + * <td>#H5FD_CORE</td> + * <td>With this driver, an application can work with a file in memory for faster reads and + * writes. File contents are kept in memory until the file is closed. At closing, the memory + * version of the file can be written back to disk or abandoned.</td> + * <td>#H5Pset_fapl_core</td> + * </tr> + * <tr> + * <td>Family</td> + * <td>#H5FD_FAMILY</td> + * <td>With this driver, the HDF5 file’s address space is partitioned into pieces and sent to + * separate storage files using an underlying driver of the user’s choice. This driver is for + * systems that do not support files larger than 2 gigabytes.</td> + * <td>#H5Pset_fapl_family</td> + * </tr> + * <tr> + * <td>Multi</td> + * <td>#H5FD_MULTI</td> + * <td>With this driver, data can be stored in multiple files according to the type of the data. + * I/O might work better if data is stored in separate files based on the type of data. The Split + * driver is a special case of this driver.</td> + * <td>#H5Pset_fapl_multi</td> + * </tr> + * <tr> + * <td>Split</td> + * <td>H5FD_SPLIT</td> + * <td>This file driver splits a file into two parts. One part stores metadata, and the other part + * stores raw data. This splitting a file into two parts is a limited case of the Multi driver.</td> + * <td>#H5Pset_fapl_split</td> + * </tr> + * <tr> + * <td>Parallel</td> + * <td>#H5FD_MPIO</td> + * <td>This is the standard HDF5 file driver for parallel file systems. This driver uses the MPI + * standard for both communication and file I/O.</td> + * <td>#H5Pset_fapl_mpio</td> + * </tr> + * <tr> + * <td>Parallel POSIX</td> + * <td>H5FD_MPIPOSIX</td> + * <td>This driver is no longer available</td> + * <td></td> + * </tr> + * <tr> + * <td>Stream</td> + * <td>H5FD_STREAM</td> + * <td>This driver is no longer available.</td> + * <td></td> + * </tr> + * </table> + * + * For more information, see the HDF5 Reference Manual entries for the function calls shown in + * the column on the right in the table above. + * + * Note that the low-level file drivers manage alternative file storage layouts. Dataset storage + * layouts (chunking, compression, and external dataset storage) are managed independently of file + * storage layouts. + * + * If an application requires a special-purpose low-level driver, the VFL provides a public API for + * creating one. For more information on how to create a driver, + * @see @ref VFL in the HDF5 Technical Notes. + * + * \subsubsection subsubsec_file_alternate_drivers_id Identifying the Previously‐used File Driver + * When creating a new HDF5 file, no history exists, so the file driver must be specified if it is to be + * other than the default. + * + * When opening existing files, however, the application may need to determine which low-level + * driver was used to create the file. The function #H5Pget_driver is used for this purpose. See the + * example below. + * + * <em>Identifying a driver</em> + * \code + * hid_t H5Pget_driver (hid_t fapl_id) + * \endcode + * + * #H5Pget_driver returns a constant identifying the low-level driver for the access property list + * fapl_id. For example, if the file was created with the POSIX (aka SEC2) driver, + * #H5Pget_driver returns #H5FD_SEC2. + * + * If the application opens an HDF5 file without both determining the driver used to create the file + * and setting up the use of that driver, the HDF5 Library will examine the superblock and the + * driver definition block to identify the driver. + * See the <a href="https://docs.hdfgroup.org/hdf5/develop/_s_p_e_c.html">HDF5 File Format Specification</a> + * for detailed descriptions of the superblock and the driver definition block. + * + * \subsubsection subsubsec_file_alternate_drivers_sec2 The POSIX (aka SEC2) Driver + * The POSIX driver, #H5FD_SEC2, uses functions from section 2 of the POSIX manual to access + * unbuffered files stored on a local file system. This driver is also known as the SEC2 driver. The + * HDF5 Library buffers metadata regardless of the low-level driver, but using this driver prevents + * data from being buffered again by the lowest layers of the library. + * + * The function #H5Pset_fapl_sec2 sets the file access properties to use the POSIX driver. See the + * example below. + * + * <em>Using the POSIX, aka SEC2, driver</em> + * \code + * herr_t H5Pset_fapl_sec2 (hid_t fapl_id) + * \endcode + * + * Any previously-defined driver properties are erased from the property list. + * + * Additional parameters may be added to this function in the future. Since there are no additional + * variable settings associated with the POSIX driver, there is no H5Pget_fapl_sec2 function. + * + * \subsubsection subsubsec_file_alternate_drivers_direct The Direct Driver + * The Direct driver, #H5FD_DIRECT, functions like the POSIX driver except that data is written to + * or read from the file synchronously without being cached by the system. + * + * The functions #H5Pset_fapl_direct and #H5Pget_fapl_direct are used to manage file access properties. + * See the example below. + * + * <em>Using the Direct driver</em> + * \code + * herr_t H5Pset_fapl_direct(hid_t fapl_id, size_t alignment, size_t block_size, size_t cbuf_size) + * herr_t H5Pget_fapl_direct(hid_t fapl_id, size_t *alignment, size_t *block_size, size_t *cbuf_size) + * \endcode + * + * #H5Pset_fapl_direct sets the file access properties to use the Direct driver; any previously defined + * driver properties are erased from the property list. #H5Pget_fapl_direct retrieves the file access + * properties used with the Direct driver. fapl_id is the file access property list identifier. + * alignment is the memory alignment boundary. block_size is the file system block size. + * cbuf_size is the copy buffer size. + * + * Additional parameters may be added to this function in the future. + * + * \subsubsection subsubsec_file_alternate_drivers_log The Log Driver + * The Log driver, #H5FD_LOG, is designed for situations where it is necessary to log file access + * activity. + * + * The function #H5Pset_fapl_log is used to manage logging properties. See the example below. + * + * <em>Logging file access</em> + * \code + * herr_t H5Pset_fapl_log (hid_t fapl_id, const char *logfile, unsigned int flags, size_t buf_size) + * \endcode + * + * #H5Pset_fapl_log sets the file access property list to use the Log driver. File access characteristics + * are identical to access via the POSIX driver. Any previously defined driver properties are erased + * from the property list. + * + * Log records are written to the file logfile. + * + * The logging levels set with the verbosity parameter are shown in the table below. + * + * <table> + * <caption>Logging levels</caption> + * <tr> + * <th>Level</th> + * <th>Comments</th> + * </tr> + * <tr> + * <td>0</td> + * <td>Performs no logging.</td> + * </tr> + * <tr> + * <td>1</td> + * <td>Records where writes and reads occur in the file.</td> + * </tr> + * <tr> + * <td>2</td> + * <td>Records where writes and reads occur in the file and what kind of data is written + * at each location. This includes raw data or any of several types of metadata + * (object headers, superblock, B-tree data, local headers, or global headers).</td> + * </tr> + * </table> + * + * There is no H5Pget_fapl_log function. + * + * Additional parameters may be added to this function in the future. + * + * \subsubsection subsubsec_file_alternate_drivers_win The Windows Driver + * The Windows driver, #H5FD_WINDOWS, was modified in HDF5-1.8.8 to be a wrapper of the + * POSIX driver, #H5FD_SEC2. In other words, if the Windows drivers is used, any file I/O will + * instead use the functionality of the POSIX driver. This change should be transparent to all user + * applications. The Windows driver used to be the default driver for Windows systems. The + * POSIX driver is now the default. + * + * The function #H5Pset_fapl_windows sets the file access properties to use the Windows driver. + * See the example below. + * + * <em>Using the Windows driver</em> + * \code + * herr_t H5Pset_fapl_windows (hid_t fapl_id) + * \endcode + * + * Any previously-defined driver properties are erased from the property list. + * + * Additional parameters may be added to this function in the future. Since there are no additional + * variable settings associated with the POSIX driver, there is no H5Pget_fapl_windows function. + * + * \subsubsection subsubsec_file_alternate_drivers_stdio The STDIO Driver + * The STDIO driver, #H5FD_STDIO, accesses permanent files in a local file system like the + * POSIX driver does. The STDIO driver also has an additional layer of buffering beneath the + * HDF5 Library. + * + * The function #H5Pset_fapl_stdio sets the file access properties to use the STDIO driver. See the + * example below. + * + * <em>Using the STDIO driver</em> + * \code + * herr_t H5Pset_fapl_stdio (hid_t fapl_id) + * \endcode + * + * Any previously defined driver properties are erased from the property list. + * + * Additional parameters may be added to this function in the future. Since there are no additional + * variable settings associated with the STDIO driver, there is no H5Pget_fapl_stdio function. + * + * \subsubsection subsubsec_file_alternate_drivers_mem The Memory (aka Core) Driver + * There are several situations in which it is reasonable, sometimes even required, to maintain a file + * entirely in system memory. You might want to do so if, for example, either of the following + * conditions apply: + * <ul><li>Performance requirements are so stringent that disk latency is a limiting factor</li> + * <li>You are working with small, temporary files that will not be retained and, thus, + * need not be written to storage media</li></ul> + * + * The Memory driver, #H5FD_CORE, provides a mechanism for creating and managing such in memory files. + * The functions #H5Pset_fapl_core and #H5Pget_fapl_core manage file access + * properties. See the example below. + * + * <em>Managing file access for in-memory files</em> + * \code + * herr_t H5Pset_fapl_core (hid_t access_properties, size_t block_size, hbool_t backing_store) + * herr_t H5Pget_fapl_core (hid_t access_properties, size_t *block_size), hbool_t *backing_store) + * \endcode + * + * #H5Pset_fapl_core sets the file access property list to use the Memory driver; any previously + * defined driver properties are erased from the property list. + * + * Memory for the file will always be allocated in units of the specified block_size. + * + * The backing_store Boolean flag is set when the in-memory file is created. + * backing_store indicates whether to write the file contents to disk when the file is closed. If + * backing_store is set to 1 (TRUE), the file contents are flushed to a file with the same name as the + * in-memory file when the file is closed or access to the file is terminated in memory. If + * backing_store is set to 0 (FALSE), the file is not saved. + * + * The application is allowed to open an existing file with the #H5FD_CORE driver. While using + * #H5Fopen to open an existing file, if backing_store is set to 1 and the flag for #H5Fopen is set to + * #H5F_ACC_RDWR, changes to the file contents will be saved to the file when the file is closed. + * If backing_store is set to 0 and the flag for #H5Fopen is set to #H5F_ACC_RDWR, changes to the + * file contents will be lost when the file is closed. If the flag for #H5Fopen is set to + * #H5F_ACC_RDONLY, no change to the file will be allowed either in memory or on file. + * + * If the file access property list is set to use the Memory driver, #H5Pget_fapl_core will return + * block_size and backing_store with the relevant file access property settings. + * + * Note the following important points regarding in-memory files: + * <ul><li>Local temporary files are created and accessed directly from memory without ever + * being written to disk</li> + * <li>Total file size must not exceed the available virtual memory</li> + * <li>Only one HDF5 file identifier can be opened for the file, the identifier returned by + * #H5Fcreate or #H5Fopen</li> + * <li>The changes to the file will be discarded when access is terminated unless + * backing_store is set to 1</li></ul> + * + * Additional parameters may be added to these functions in the future. + * + * @see <a href="https://portal.hdfgroup.org/display/HDF5/HDF5+File+Image+Operations"> + * HDF5 File Image Operations</a> + * section for information on more advanced usage of the Memory file driver, and + * @see <a href="http://www.hdfgroup.org/HDF5/doc/Advanced/ModifiedRegionWrites/ModifiedRegionWrites.pdf"> + * Modified Region Writes</a> + * section for information on how to set write operations so that only modified regions are written + * to storage. + * + * \subsubsection subsubsec_file_alternate_drivers_family The Family Driver + * HDF5 files can become quite large, and this can create problems on systems that do not support + * files larger than 2 gigabytes. The HDF5 file family mechanism is designed to solve the problems + * this creates by splitting the HDF5 file address space across several smaller files. This structure + * does not affect how metadata and raw data are stored: they are mixed in the address space just as + * they would be in a single, contiguous file. + * + * HDF5 applications access a family of files via the Family driver, #H5FD_FAMILY. The + * functions #H5Pset_fapl_family and #H5Pget_fapl_family are used to manage file family + * properties. See the example below. + * + * <em>Managing file family properties</em> + * \code + * herr_t H5Pset_fapl_family (hid_t fapl_id, + * hsize_t memb_size, hid_t member_properties) + * herr_t H5Pget_fapl_family (hid_t fapl_id, + * hsize_t *memb_size, hid_t *member_properties) + * \endcode + * + * Each member of the family is the same logical size though the size and disk storage reported by + * file system listing tools may be substantially smaller. Examples of file system listing tools are + * \code + * ls -l + * \endcode + * on a Unix system or the detailed folder listing on an Apple or Microsoft Windows + * system. The name passed to #H5Fcreate or #H5Fopen should include a printf(3c)-style integer + * format specifier which will be replaced with the family member number. The first family + * member is numbered zero (0). + * + * #H5Pset_fapl_family sets the access properties to use the Family driver; any previously defined + * driver properties are erased from the property list. member_properties will serve as the file + * access property list for each member of the file family. memb_size specifies the logical size, in + * bytes, of each family member. memb_size is used only when creating a new file or truncating an + * existing file; otherwise the member size is determined by the size of the first member of the + * family being opened. Note: If the size of the off_t type is four bytes, the maximum family + * member size is usually 2^31-1 because the byte at offset 2,147,483,647 is generally inaccessible. + * + * #H5Pget_fapl_family is used to retrieve file family properties. If the file access property list is set + * to use the Family driver, member_properties will be returned with a pointer to a copy of the + * appropriate member access property list. If memb_size is non-null, it will contain the logical + * size, in bytes, of family members. + * + * Additional parameters may be added to these functions in the future. + * + * <h4>Unix Tools and an HDF5 Utility</h4> + * It occasionally becomes necessary to repartition a file family. A command-line utility for this + * purpose, h5repart, is distributed with the HDF5 library. + * + * \code + * h5repart [-v] [-b block_size[suffix]] [-m member_size[suffix]] source destination + * \endcode + * + * h5repart repartitions an HDF5 file by copying the source file or file family to the destination file + * or file family, preserving holes in the underlying UNIX files. Families are used for the source + * and/or destination if the name includes a printf-style integer format such as %d. The -v switch + * prints input and output file names on the standard error stream for progress monitoring, -b sets + * the I/O block size (the default is 1KB), and -m sets the output member size if the destination is a + * family name (the default is 1GB). block_size and member_size may be suffixed with the letters + * g, m, or k for GB, MB, or KB respectively. + * + * The h5repart utility is described on the Tools page of the HDF5 Reference Manual. + * + * An existing HDF5 file can be split into a family of files by running the file through split(1) on a + * UNIX system and numbering the output files. However, the HDF5 Library is lazy about + * extending the size of family members, so a valid file cannot generally be created by + * concatenation of the family members. + * + * Splitting the file and rejoining the segments by concatenation (split(1) and cat(1) on UNIX + * systems) does not generate files with holes; holes are preserved only through the use of h5repart. + * + * \subsubsection subsubsec_file_alternate_drivers_multi The Multi Driver + * In some circumstances, it is useful to separate metadata from raw data and some types of + * metadata from other types of metadata. Situations that would benefit from use of the Multi driver + * include the following: + * <ul><li>In networked situations where the small metadata files can be kept on local disks but + * larger raw data files must be stored on remote media</li> + * <li>In cases where the raw data is extremely large</li> + * <li>In situations requiring frequent access to metadata held in RAM while the raw data + * can be efficiently held on disk</li></ul> + * + * In either case, access to the metadata is substantially easier with the smaller, and possibly more + * localized, metadata files. This often results in improved application performance. + * + * The Multi driver, #H5FD_MULTI, provides a mechanism for segregating raw data and different + * types of metadata into multiple files. The functions #H5Pset_fapl_multi and + * #H5Pget_fapl_multi are used to manage access properties for these multiple files. See the example + * below. + * + * <em>Managing access properties for multiple files</em> + * \code + * herr_t H5Pset_fapl_multi (hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_fapl, + * const char * const *memb_name, const haddr_t *memb_addr, + * hbool_t relax) + * herr_t H5Pget_fapl_multi (hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_fapl, + * const char **memb_name, const haddr_t *memb_addr, hbool_t *relax) + * \endcode + * + * #H5Pset_fapl_multi sets the file access properties to use the Multi driver; any previously defined + * driver properties are erased from the property list. With the Multi driver invoked, the application + * will provide a base name to #H5Fopen or #H5Fcreate. The files will be named by that base name as + * modified by the rule indicated in memb_name. File access will be governed by the file access + * property list memb_properties. + * + * See #H5Pset_fapl_multi and #H5Pget_fapl_multi in the HDF5 Reference Manual for descriptions + * of these functions and their usage. + * + * Additional parameters may be added to these functions in the future. + * + * \subsubsection subsubsec_file_alternate_drivers_split The Split Driver + * The Split driver, H5FD_SPLIT, is a limited case of the Multi driver where only two files are + * created. One file holds metadata, and the other file holds raw data. + * The function #H5Pset_fapl_split is used to manage Split file access properties. See the example + * below. + * + * <em>Managing access properties for split files</em> + * \code + * herr_t H5Pset_fapl_split (hid_t access_properties, const char *meta_extension, + * hid_t meta_properties,const char *raw_extension, hid_t raw_properties) + * \endcode + * + * #H5Pset_fapl_split sets the file access properties to use the Split driver; any previously defined + * driver properties are erased from the property list. + * + * With the Split driver invoked, the application will provide a base file name such as file_name to + * #H5Fcreate or #H5Fopen. The metadata and raw data files in storage will then be named + * file_name.meta_extension and file_name.raw_extension, respectively. For example, if + * meta_extension is defined as .meta and raw_extension is defined as .raw, the final filenames will + * be file_name.meta and file_name.raw. + * + * Each file can have its own file access property list. This allows the creative use of other lowlevel + * file drivers. For instance, the metadata file can be held in RAM and accessed via the + * Memory driver while the raw data file is stored on disk and accessed via the POSIX driver. + * Metadata file access will be governed by the file access property list in meta_properties. Raw + * data file access will be governed by the file access property list in raw_properties. + * + * Additional parameters may be added to these functions in the future. Since there are no + * additional variable settings associated with the Split driver, there is no H5Pget_fapl_split + * function. + * + * \subsubsection subsubsec_file_alternate_drivers_par The Parallel Driver + * Parallel environments require a parallel low-level driver. HDF5’s default driver for parallel + * systems is called the Parallel driver, #H5FD_MPIO. This driver uses the MPI standard for both + * communication and file I/O. + * + * The functions #H5Pset_fapl_mpio and #H5Pget_fapl_mpio are used to manage file access + * properties for the #H5FD_MPIO driver. See the example below. + * + * <em>Managing parallel file access properties</em> + * \code + * herr_t H5Pset_fapl_mpio (hid_t fapl_id, MPI_Comm comm, MPI_info info) + * herr_t H5Pget_fapl_mpio (hid_t fapl_id, MPI_Comm *comm, MPI_info *info) + * \endcode + * + * The file access properties managed by #H5Pset_fapl_mpio and retrieved by + * #H5Pget_fapl_mpio are the MPI communicator, comm, and the MPI info object, info. comm and + * info are used for file open. info is an information object much like an HDF5 property list. Both + * are defined in MPI_FILE_OPEN of MPI-2. + * + * The communicator and the info object are saved in the file access property list fapl_id. + * fapl_id can then be passed to MPI_FILE_OPEN to create and/or open the file. + * + * #H5Pset_fapl_mpio and #H5Pget_fapl_mpio are available only in the parallel HDF5 Library and + * are not collective functions. The Parallel driver is available only in the parallel HDF5 Library. + * + * Additional parameters may be added to these functions in the future. + * + * \subsection subsec_file_examples Code Examples for Opening and Closing Files + * \subsubsection subsubsec_file_examples_trunc Example Using the H5F_ACC_TRUNC Flag + * The following example uses the #H5F_ACC_TRUNC flag when it creates a new file. The default + * file creation and file access properties are also used. Using #H5F_ACC_TRUNC means the + * function will look for an existing file with the name specified by the function. In this case, that + * name is FILE. If the function does not find an existing file, it will create one. If it does find an + * existing file, it will empty the file in preparation for a new set of data. The identifier for the + * "new" file will be passed back to the application program. + * For more information, @see @ref subsec_file_access_modes. + * + * <em>Creating a file with default creation and access properties</em> + * \code + * hid_t file; // identifier + * + * // Create a new file using H5F_ACC_TRUNC access, default + * // file creation properties, and default file access + * // properties. + * file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + * + * // Close the file. + * status = H5Fclose(file); + * \endcode + * + * \subsubsection subsubsec_file_examples_props Example with the File Creation Property List + * The example below shows how to create a file with 64-bit object offsets and lengths. + * + * <em>Creating a file with 64-bit offsets</em> + * \code + * hid_t create_plist; + * hid_t file_id; + * + * create_plist = H5Pcreate(H5P_FILE_CREATE); + * H5Pset_sizes(create_plist, 8, 8); + * file_id = H5Fcreate(“test.h5”, H5F_ACC_TRUNC, create_plist, H5P_DEFAULT); + * . + * . + * . + * + * H5Fclose(file_id); + * \endcode + * + * \subsubsection subsubsec_file_examples_access Example with the File Access Property List + * This example shows how to open an existing file for independent datasets access by MPI parallel + * I/O: + * + * <em>Opening an existing file for parallel I/O</em> + * \code + * hid_t access_plist; + * hid_t file_id; + * + * access_plist = H5Pcreate(H5P_FILE_ACCESS); + * H5Pset_fapl_mpi(access_plist, MPI_COMM_WORLD, MPI_INFO_NULL); + * + * // H5Fopen must be called collectively + * file_id = H5Fopen(“test.h5”, H5F_ACC_RDWR, access_plist); + * . + * . + * . + * + * // H5Fclose must be called collectively + * H5Fclose(file_id); + * \endcode + * + * \subsection subsec_file_multiple Working with Multiple HDF5 Files + * Multiple HDF5 files can be associated so that the files can be worked with as though all the + * information is in a single HDF5 file. A temporary association can be set up by means of the + * #H5Fmount function. A permanent association can be set up by means of the external link + * function #H5Lcreate_external. + * + * The purpose of this section is to describe what happens when the #H5Fmount function is used to + * mount one file on another. + * + * When a file is mounted on another, the mounted file is mounted at a group, and the root group of + * the mounted file takes the place of that group until the mounted file is unmounted or until the + * files are closed. + * + * The figure below shows two files before one is mounted on the other. File1 has two groups and + * three datasets. The group that is the target of the A link has links, Z and Y, to two of the datasets. + * The group that is the target of the B link has a link, W, to the other dataset. File2 has three + * groups and three datasets. The groups in File2 are the targets of the AA, BB, and CC links. The + * datasets in File2 are the targets of the ZZ, YY, and WW links. + * + * <table> + * <tr> + * <td> + * \image html Files_fig3.gif "Two separate files" + * </td> + * </tr> + * </table> + * + * The figure below shows the two files after File2 has been mounted File1 at the group that is the + * target of the B link. + * + * <table> + * <tr> + * <td> + * \image html Files_fig4.gif "File2 mounted on File1" + * </td> + * </tr> + * </table> + * + * Note: In the figure above, the dataset that is the target of the W link is not shown. That dataset is + * masked by the mounted file. + * + * If a file is mounted on a group that has members, those members are hidden until the mounted + * file is unmounted. There are two ways around this if you need to work with a group member. + * One is to mount the file on an empty group. Another is to open the group member before you + * mount the file. Opening the group member will return an identifier that you can use to locate the + * group member. + * + * The example below shows how #H5Fmount might be used to mount File2 onto File1. + * + * <em>Using H5Fmount</em> + * \code + * status = H5Fmount(loc_id, "/B", child_id, plist_id) + * \endcode + * + * Note: In the code example above, loc_id is the file identifier for File1, /B is the link path to the + * group where File2 is mounted, child_id is the file identifier for File2, and plist_id is a property + * list identifier. + * For more information, @see @ref sec_group. + * + * See the entries for #H5Fmount, #H5Funmount, and #H5Lcreate_external in the HDF5 Reference Manual. + * + * Previous Chapter \ref sec_program - Next Chapter \ref sec_group + * + */ + +/** + * \defgroup H5F Files (H5F) * * Use the functions in this module to manage HDF5 files. * diff --git a/src/H5Gmodule.h b/src/H5Gmodule.h index a0e121d..a112a40 100644 --- a/src/H5Gmodule.h +++ b/src/H5Gmodule.h @@ -29,7 +29,929 @@ #define H5_MY_PKG_ERR H5E_SYM #define H5_MY_PKG_INIT YES -/** \defgroup H5G H5G +/** \page H5G_UG HDF5 Groups + * + * \section sec_group HDF5 Groups + * \subsection subsec_group_intro Introduction + * As suggested by the name Hierarchical Data Format, an HDF5 file is hierarchically structured. + * The HDF5 group and link objects implement this hierarchy. + * + * In the simple and most common case, the file structure is a tree structure; in the general case, the + * file structure may be a directed graph with a designated entry point. The tree structure is very + * similar to the file system structures employed on UNIX systems, directories and files, and on + * Apple and Microsoft Windows systems, folders and files. HDF5 groups are analogous + * to the directories and folders; HDF5 datasets are analogous to the files. + * + * The one very important difference between the HDF5 file structure and the above-mentioned file + * system analogs is that HDF5 groups are linked as a directed graph, allowing circular references; + * the file systems are strictly hierarchical, allowing no circular references. The figures below + * illustrate the range of possibilities. + * + * In the first figure below, the group structure is strictly hierarchical, identical to the file system + * analogs. + * + * In the next two figures below, the structure takes advantage of the directed graph’s allowance of + * circular references. In the second figure, GroupA is not only a member of the root group, /, but a + * member of GroupC. Since Group C is a member of Group B and Group B is a member of Group + * A, Dataset1 can be accessed by means of the circular reference /Group A/Group B/Group + * C/Group A/Dataset1. The third figure below illustrates an extreme case in which GroupB is a + * member of itself, enabling a reference to a member dataset such as /Group A/Group B/Group + * B/Group B/Dataset2. + * + * <table> + * <tr> + * <td> + * \image html Groups_fig1.gif "A file with a strictly hierarchical group structure" + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Groups_fig2.gif "A file with a circular reference" + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Groups_fig3.gif "A file with one group as a member of itself" + * </td> + * </tr> + * </table> + * + * As becomes apparent upon reflection, directed graph structures can become quite complex; + * caution is advised! + * + * The balance of this chapter discusses the following topics: + * \li The HDF5 group object (or a group) and its structure in more detail + * \li HDF5 link objects (or links) + * \li The programming model for working with groups and links + * \li HDF5 functions provided for working with groups, group members, and links + * \li Retrieving information about objects in a group + * \li Discovery of the structure of an HDF5 file and the contained objects + * \li Examples of file structures + * + * \subsection subsec_group_descr Description of the Group Object + * \subsubsection subsubsec_group_descr_object The Group Object + * Abstractly, an HDF5 group contains zero or more objects and every object must be a member of + * at least one group. The root group, the sole exception, may not belong to any group. + * + * <table> + * <tr> + * <td> + * \image html Groups_fig4.gif "Abstract model of the HDF5 group object" + * </td> + * </tr> + * </table> + * + * Group membership is actually implemented via link objects. See the figure above. A link object + * is owned by a group and points to a named object. Each link has a name, and each link points to + * exactly one object. Each named object has at least one and possibly many links to it. + * + * There are three classes of named objects: group, dataset, and committed datatype (formerly + * called named datatype). See the figure below. Each of these objects is the member of at least one + * group, which means there is at least one link to it. + * + * <table> + * <tr> + * <td> + * \image html Groups_fig5.gif "Classes of named objects" + * </td> + * </tr> + * </table> + * + * The primary operations on a group are to add and remove members and to discover member + * objects. These abstract operations, as listed in the figure below, are implemented in the \ref H5G + * APIs. For more information, @see @ref subsec_group_function. + * + * To add and delete members of a group, links from the group to existing objects in the file are + * created and deleted with the link and unlink operations. When a new named object is created, the + * HDF5 Library executes the link operation in the background immediately after creating the + * object (in other words, a new object is added as a member of the group in which it is created + * without further user intervention). + * + * Given the name of an object, the get_object_info method retrieves a description of the object, + * including the number of references to it. The iterate method iterates through the members of the + * group, returning the name and type of each object. + * + * <table> + * <tr> + * <td> + * \image html Groups_fig6.gif "The group object" + * </td> + * </tr> + * </table> + * + * Every HDF5 file has a single root group, with the name /. The root group is identical to any other + * HDF5 group, except: + * \li The root group is automatically created when the HDF5 file is created (#H5Fcreate). + * \li The root group has no parent, but by convention has a reference count of 1. + * \li The root group cannot be deleted (in other words, unlinked)! + * + * \subsubsection subsubsec_group_descr_model The Hierarchy of Data Objects + * An HDF5 file is organized as a rooted, directed graph using HDF5 group objects. The named + * data objects are the nodes of the graph, and the links are the directed arcs. Each arc of the graph + * has a name, with the special name / reserved for the root group. New objects are created and then + * inserted into the graph with a link operation that is automatically executed by the library; + * existing objects are inserted into the graph with a link operation explicitly called by the user, + * which creates a named link from a group to the object. + * + * An object can be the target of more than one link. + * + * The names on the links must be unique within each group, but there may be many links with the + * same name in different groups. These are unambiguous, because some ancestor must have a + * different name, or else they are the same object. The graph is navigated with path names, + * analogous to Unix file systems. For more information, @see @ref subsubsec_group_descr_path. + * + * An object can be opened with a full path starting at the root group, or with a relative path and a + * starting point. That starting point is always a group, though it may be the current working group, + * another specified group, or the root group of the file. Note that all paths are relative to a single + * HDF5 file. In this sense, an HDF5 file is analogous to a single UNIX file system. + * + * It is important to note that, just like the UNIX file system, HDF5 objects do not have names, the + * names are associated with paths. An object has an object identifier that is unique within the file, + * but a single object may have many names because there may be many paths to the same object. + * An object can be renamed, or moved to another group, by adding and deleting links. In this case, + * the object itself never moves. For that matter, membership in a group has no implication for the + * physical location of the stored object. + * + * Deleting a link to an object does not necessarily delete the object. The object remains available + * as long as there is at least one link to it. After all links to an object are deleted, it can no longer + * be opened, and the storage may be reclaimed. + * + * It is also important to realize that the linking mechanism can be used to construct very complex + * graphs of objects. For example, it is possible for an object to be shared between several groups + * and even to have more than one name in the same group. It is also possible for a group to be a + * member of itself, or to create other cycles in the graph, such as in the case where a child group is + * linked to one of its ancestors. + * + * HDF5 also has soft links similar to UNIX soft links. A soft link is an object that has a name and + * a path name for the target object. The soft link can be followed to open the target of the link just + * like a regular or hard link. The differences are that the hard link cannot be created if the target + * object does not exist and it always points to the same object. A soft link can be created with any + * path name, whether or not the object exists; it may or may not, therefore, be possible to follow a + * soft link. Furthermore, a soft link’s target object may be changed. + * + * \subsubsection subsubsec_group_descr_path HDF5 Path Names + * The structure of the HDF5 file constitutes the name space for the objects in the file. A path name + * is a string of components separated by slashes (/). Each component is the name of a hard or soft + * link which points to an object in the file. The slash not only separates the components, but + * indicates their hierarchical relationship; the component indicated by the link name following a + * slash is a always a member of the component indicated by the link name preceding that slash. + * + * The first component in the path name may be any of the following: + * \li The special character dot (., a period), indicating the current group + * \li The special character slash (/), indicating the root group + * \li Any member of the current group + * + * Component link names may be any string of ASCII characters not containing a slash or a dot + * (/ and ., which are reserved as noted above). However, users are advised to avoid the use of + * punctuation and non-printing characters, as they may create problems for other software. The + * figure below provides a BNF grammar for HDF5 path names. + * + * <em>A BNF grammar for HDF5 path names</em> + * \code + * PathName ::= AbsolutePathName | RelativePathName + * Separator ::= "/" ["/"]* + * AbsolutePathName ::= Separator [ RelativePathName ] + * RelativePathName ::= Component [ Separator RelativePathName ]* + * Component ::= "." | Characters + * Characters ::= Character+ - { "." } + * Character ::= {c: c Î { { legal ASCII characters } - {'/'} } + * \endcode + * + * An object can always be addressed by either a full or an absolute path name, starting at the root + * group, or by a relative path name, starting in a known location such as the current working + * group. As noted elsewhere, a given object may have multiple full and relative path names. + * + * Consider, for example, the file illustrated in the figure below. Dataset1 can be identified by either + * of these absolute path names: + * <em>/GroupA/Dataset1</em> + * + * <em>/GroupA/GroupB/GroupC/Dataset1</em> + * + * Since an HDF5 file is a directed graph structure, and is therefore not limited to a strict tree + * structure, and since this illustrated file includes the sort of circular reference that a directed graph + * enables, Dataset1 can also be identified by this absolute path name: + * <em>/GroupA/GroupB/GroupC/GroupA/Dataset1</em> + * + * Alternatively, if the current working location is GroupB, Dataset1 can be identified by either of + * these relative path names: + * <em>GroupC/Dataset1</em> + * + * <em>GroupC/GroupA/Dataset1</em> + * + * Note that relative path names in HDF5 do not employ the ../ notation, the UNIX notation + * indicating a parent directory, to indicate a parent group. + * + * <table> + * <tr> + * <td> + * \image html Groups_fig2.gif "A file with a circular reference" + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_group_descr_impl Group Implementations in HDF5 + * The original HDF5 group implementation provided a single indexed structure for link storage. A + * new group implementation, as of HDF5 Release 1.8.0, enables more efficient compact storage + * for very small groups, improved link indexing for large groups, and other advanced features. + * <ul> + * <li>The original indexed format remains the default. Links are stored in a B-tree in the + * group’s local heap.</li> + * <li>Groups created in the new compact-or-indexed format, the implementation introduced + * with Release 1.8.0, can be tuned for performance, switching between the compact and + * indexed formats at thresholds set in the user application. + * <ul> + * <li>The compact format will conserve file space and processing overhead when + * working with small groups and is particularly valuable when a group contains + * no links. Links are stored as a list of messages in the group’s header.</li> + * <li>The indexed format will yield improved performance when working with large + * groups. A large group may contain thousands to millions of members. Links + * are stored in a fractal heap and indexed with an improved B-tree.</li> + * </ul></li> + * <li>The new implementation also enables the use of link names consisting of non-ASCII + * character sets (see #H5Pset_char_encoding) and is required for all link types other than + * hard or soft links; the link types other than hard or soft links are external links and + * user-defined links @see @ref H5L APIs.</li> + * </ul> + * + * The original group structure and the newer structures are not directly interoperable. By default, a + * group will be created in the original indexed format. An existing group can be changed to a + * compact-or-indexed format if the need arises; there is no capability to change back. As stated + * above, once in the compact-or-indexed format, a group can switch between compact and indexed + * as needed. + * + * Groups will be initially created in the compact-or-indexed format only when one or more of the + * following conditions is met: + * <ul> + * <li>The low version bound value of the library version bounds property has been set to + * Release 1.8.0 or later in the file access property list (see #H5Pset_libver_bounds). + * Currently, that would require an #H5Pset_libver_bounds call with the low parameter + * set to #H5F_LIBVER_LATEST. + * + * When this property is set for an HDF5 file, all objects in the file will be created using + * the latest available format; no effort will be made to create a file that can be read by + * older libraries.</li> + * <li>The creation order tracking property, #H5P_CRT_ORDER_TRACKED, has been set + * in the group creation property list (see #H5Pset_link_creation_order).</li> + * </ul> + * + * An existing group, currently in the original indexed format, will be converted to the compact-or- + * indexed format upon the occurrence of any of the following events: + * <ul> + * <li>An external or user-defined link is inserted into the group. + * <li>A link named with a string composed of non-ASCII characters is inserted into the + * group. + * </ul> + * + * The compact-or-indexed format offers performance improvements that will be most notable at + * the extremes (for example, in groups with zero members and in groups with tens of thousands of + * members). But measurable differences may sometimes appear at a threshold as low as eight + * group members. Since these performance thresholds and criteria differ from application to + * application, tunable settings are provided to govern the switch between the compact and indexed + * formats (see #H5Pset_link_phase_change). Optimal thresholds will depend on the application and + * the operating environment. + * + * Future versions of HDF5 will retain the ability to create, read, write, and manipulate all groups + * stored in either the original indexed format or the compact-or-indexed format. + * + * \subsection subsec_group_h5dump Using h5dump + * You can use h5dump, the command-line utility distributed with HDF5, to examine a file for + * purposes either of determining where to create an object within an HDF5 file or to verify that + * you have created an object in the intended place. + * + * In the case of the new group created later in this chapter, the following h5dump command will + * display the contents of FileA.h5: + * \code + * h5dump FileA.h5 + * \endcode + * + * For more information, @see @ref subsubsec_group_program_create. + * + * Assuming that the discussed objects, GroupA and GroupB are the only objects that exist in + * FileA.h5, the output will look something like the following: + * \code + * HDF5 "FileA.h5" { + * GROUP "/" { + * GROUP GroupA { + * GROUP GroupB { + * } + * } + * } + * } + * \endcode + * + * h5dump is described on the “HDF5 Tools” page of the \ref RM. + * + * The HDF5 DDL grammar is described in the @ref DDLBNF110. + * + * \subsection subsec_group_function Group Function Summaries + * Functions that can be used with groups (\ref H5G functions) and property list functions that can used + * with groups (\ref H5P functions) are listed below. A number of group functions have been + * deprecated. Most of these have become link (\ref H5L) or object (\ref H5O) functions. These replacement + * functions are also listed below. + * + * <table> + * <caption>Group functions</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Gcreate</td> + * <td>Creates a new empty group and gives it a name. The + * C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Gcreate_anon</td> + * <td>Creates a new empty group without linking it into the file structure.</td> + * </tr> + * <tr> + * <td>#H5Gopen</td> + * <td>Opens an existing group for modification and returns a group identifier for that group. + * The C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Gclose</td> + * <td>Closes the specified group.</td> + * </tr> + * <tr> + * <td>#H5Gget_create_plist</td> + * <td>Gets a group creation property list identifier.</td> + * </tr> + * <tr> + * <td>#H5Gget_info</td> + * <td>Retrieves information about a group. Use instead of H5Gget_num_objs.</td> + * </tr> + * <tr> + * <td>#H5Gget_info_by_idx</td> + * <td>Retrieves information about a group according to the group’s position within an index.</td> + * </tr> + * <tr> + * <td>#H5Gget_info_by_name</td> + * <td>Retrieves information about a group.</td> + * </tr> + * </table> + * + * <table> + * <caption>Link and object functions</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Lcreate_hard</td> + * <td>Creates a hard link to an object. Replaces H5Glink and H5Glink2.</td> + * </tr> + * <tr> + * <td>#H5Lcreate_soft</td> + * <td>Creates a soft link to an object. Replaces H5Glink and H5Glink2.</td> + * </tr> + * <tr> + * <td>#H5Lcreate_external</td> + * <td>Creates a soft link to an object in a different file. Replaces H5Glink and H5Glink2.</td> + * </tr> + * <tr> + * <td>#H5Lcreate_ud</td> + * <td>Creates a link of a user-defined type.</td> + * </tr> + * </tr> + * <tr> + * <td>#H5Lget_val</td> + * <td>Returns the value of a symbolic link. Replaces H5Gget_linkval.</td> + * </tr> + * <tr> + * <td>#H5Literate</td> + * <td>Iterates through links in a group. Replaces H5Giterate. + * See also #H5Ovisit and #H5Lvisit.</td> + * </tr> + * <tr> + * <td>#H5Literate_by_name</td> + * <td>Iterates through links in a group.</td> + * </tr> + * <tr> + * <td>#H5Lvisit</td> + * <td>Recursively visits all links starting from a specified group.</td> + * </tr> + * <tr> + * <td>#H5Ovisit</td> + * <td>Recursively visits all objects accessible from a specified object.</td> + * </tr> + * <tr> + * <td>#H5Lget_info</td> + * <td>Returns information about a link. Replaces H5Gget_objinfo.</td> + * </tr> + * <tr> + * <td>#H5Oget_info</td> + * <td>Retrieves the metadata for an object specified by an identifier. Replaces H5Gget_objinfo.</td> + * </tr> + * <tr> + * <td>#H5Lget_name_by_idx</td> + * <td>Retrieves name of the nth link in a group, according to the order within a specified field + * or index. Replaces H5Gget_objname_by_idx.</td> + * </tr> + * <tr> + * <td>#H5Oget_info_by_idx</td> + * <td>Retrieves the metadata for an object, identifying the object by an index position. Replaces + * H5Gget_objtype_by_idx.</td> + * </tr> + * <tr> + * <td>#H5Oget_info_by_name</td> + * <td>Retrieves the metadata for an object, identifying the object by location and relative name.</td> + * </tr> + * <tr> + * <td>#H5Oset_comment</td> + * <td>Sets the comment for specified object. Replaces H5Gset_comment.</td> + * </tr> + * <tr> + * <td>#H5Oget_comment</td> + * <td>Gets the comment for specified object. Replaces H5Gget_comment.</td> + * </tr> + * <tr> + * <td>#H5Ldelete</td> + * <td>Removes a link from a group. Replaces H5Gunlink.</td> + * </tr> + * <tr> + * <td>#H5Lmove</td> + * <td>Renames a link within an HDF5 file. Replaces H5Gmove and H5Gmove2.</td> + * </tr> + * </table> + * + * <table> + * <caption>Group creation property list functions</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pall_filters_avail</td> + * <td>Verifies that all required filters are available.</td> + * </tr> + * <tr> + * <td>#H5Pget_filter</td> + * <td>Returns information about a filter in a pipeline. The + * C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Pget_filter_by_id</td> + * <td>Returns information about the specified filter. The + * C function is a macro: \see \ref api-compat-macros.</td> + * </tr> + * <tr> + * <td>#H5Pget_nfilters</td> + * <td>Returns the number of filters in the pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pmodify_filter</td> + * <td>Modifies a filter in the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Premove_filter</td> + * <td>Deletes one or more filters in the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pset_deflate</td> + * <td>Sets the deflate (GNU gzip) compression method and compression level.</td> + * </tr> + * <tr> + * <td>#H5Pset_filter</td> + * <td>Adds a filter to the filter pipeline.</td> + * </tr> + * <tr> + * <td>#H5Pset_fletcher32</td> + * <td>Sets up use of the Fletcher32 checksum filter.</td> + * </tr> + * <tr> + * <td>#H5Pset_link_phase_change</td> + * <td>Sets the parameters for conversion between compact and dense groups.</td> + * </tr> + * <tr> + * <td>#H5Pget_link_phase_change</td> + * <td>Queries the settings for conversion between compact and dense groups.</td> + * </tr> + * <tr> + * <td>#H5Pset_est_link_info</td> + * <td>Sets estimated number of links and length of link names in a group.</td> + * </tr> + * <tr> + * <td>#H5Pget_est_link_info</td> + * <td>Queries data required to estimate required local heap or object header size.</td> + * </tr> + * <tr> + * <td>#H5Pset_nlinks</td> + * <td>Sets maximum number of soft or user-defined link traversals.</td> + * </tr> + * <tr> + * <td>#H5Pget_nlinks</td> + * <td>Retrieves the maximum number of link traversals.</td> + * </tr> + * <tr> + * <td>#H5Pset_link_creation_order</td> + * <td>Sets creation order tracking and indexing for links in a group.</td> + * </tr> + * <tr> + * <td>#H5Pget_link_creation_order</td> + * <td>Queries whether link creation order is tracked and/or indexed in a group.</td> + * </tr> + * <tr> + * <td>#H5Pset_create_intermediate_group</td> + * <td>Specifies in the property list whether to create missing intermediate groups.</td> + * </tr> + * <tr> + * <td>#H5Pget_create_intermediate_group</td> + * <td>Determines whether the property is set to enable creating missing intermediate groups.</td> + * </tr> + * <tr> + * <td>#H5Pset_char_encoding</td> + * <td>Sets the character encoding used to encode a string. Use to set ASCII or UTF-8 character + * encoding for object names.</td> + * </tr> + * <tr> + * <td>#H5Pget_char_encoding</td> + * <td>Retrieves the character encoding used to create a string.</td> + * </tr> + * </table> + * + * <table> + * <caption>Other external link functions</caption> + * <tr> + * <th>Function</th> + * <th>Purpose</th> + * </tr> + * <tr> + * <td>#H5Pset_elink_file_cache_size</td> + * <td>Sets the size of the external link open file cache from the specified + * file access property list.</td> + * </tr> + * <tr> + * <td>#H5Pget_elink_file_cache_size</td> + * <td>Retrieves the size of the external link open file cache from the specified + * file access property list.</td> + * </tr> + * <tr> + * <td>#H5Fclear_elink_file_cache</td> + * <td>Clears the external link open file cache for a file.</td> + * </tr> + * </table> + * + * \subsection subsec_group_program Programming Model for Groups + * The programming model for working with groups is as follows: + * <ol><li>Create a new group or open an existing one.</li> + * <li>Perform the desired operations on the group. + * <ul><li>Create new objects in the group.</li> + * <li>Insert existing objects as group members.</li> + * <li>Delete existing members.</li> + * <li>Open and close member objects.</li> + * <li>Access information regarding member objects.</li> + * <li>Iterate across group members.</li> + * <li>Manipulate links.</li></ul> + * <li>Terminate access to the group (Close the group).</li></ol> + * + * \subsubsection subsubsec_group_program_create Creating a Group + * To create a group, use #H5Gcreate, specifying the location and the path of the new group. The + * location is the identifier of the file or the group in a file with respect to which the new group is to + * be identified. The path is a string that provides either an absolute path or a relative path to the + * new group. For more information, @see @ref subsubsec_group_descr_path. + * + * A path that begins with a slash (/) is + * an absolute path indicating that it locates the new group from the root group of the HDF5 file. A + * path that begins with any other character is a relative path. When the location is a file, a relative + * path is a path from that file’s root group; when the location is a group, a relative path is a path + * from that group. + * + * The sample code in the example below creates three groups. The group Data is created in the + * root directory; two groups are then created in /Data, one with absolute path, the other with a + * relative path. + * + * <em>Creating three new groups</em> + * \code + * hid_t file; + * file = H5Fopen(....); + * + * group = H5Gcreate(file, "/Data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * group_new1 = H5Gcreate(file, "/Data/Data_new1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * group_new2 = H5Gcreate(group, "Data_new2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * The third #H5Gcreate parameter optionally specifies how much file space to reserve to store the + * names that will appear in this group. If a non-positive value is supplied, a default size is chosen. + * + * \subsubsection subsubsec_group_program_open Opening a Group and Accessing an Object in that Group + * Though it is not always necessary, it is often useful to explicitly open a group when working + * with objects in that group. Using the file created in the example above, the example below + * illustrates the use of a previously-acquired file identifier and a path relative to that file to open + * the group Data. + * + * Any object in a group can be also accessed by its absolute or relative path. To open an object + * using a relative path, an application must first open the group or file on which that relative path + * is based. To open an object using an absolute path, the application can use any location identifier + * in the same file as the target object; the file identifier is commonly used, but object identifier for + * any object in that file will work. Both of these approaches are illustrated in the example below. + * + * Using the file created in the examples above, the example below provides sample code + * illustrating the use of both relative and absolute paths to access an HDF5 data object. The first + * sequence (two function calls) uses a previously-acquired file identifier to open the group Data, + * and then uses the returned group identifier and a relative path to open the dataset CData. The + * second approach (one function call) uses the same previously-acquired file identifier and an + * absolute path to open the same dataset. + * + * <em>Open a dataset with relative and absolute paths</em> + * \code + * group = H5Gopen(file, "Data", H5P_DEFAULT); + * + * dataset1 = H5Dopen(group, "CData", H5P_DEFAULT); + * dataset2 = H5Dopen(file, "/Data/CData", H5P_DEFAULT); + * \endcode + * + * \subsubsection subsubsec_group_program_dataset Creating a Dataset in a Specific Group + * Any dataset must be created in a particular group. As with groups, a dataset may be created in a + * particular group by specifying its absolute path or a relative path. The example below illustrates + * both approaches to creating a dataset in the group /Data. + * + * <em> Create a dataset with absolute and relative paths</em> + * \code + * dataspace = H5Screate_simple(RANK, dims, NULL); + * dataset1 = H5Dcreate(file, "/Data/CData", H5T_NATIVE_INT, dataspace, + * H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * group = H5Gopen(file, "Data", H5P_DEFAULT); + * dataset2 = H5Dcreate(group, "Cdata2", H5T_NATIVE_INT, dataspace, + * H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * \subsubsection subsubsec_group_program_close Closing a Group + * To ensure the integrity of HDF5 objects and to release system resources, an application should + * always call the appropriate close function when it is through working with an HDF5 object. In + * the case of groups, H5Gclose ends access to the group and releases any resources the HDF5 + * library has maintained in support of that access, including the group identifier. + * + * As illustrated in the example below, all that is required for an H5Gclose call is the group + * identifier acquired when the group was opened; there are no relative versus absolute path + * considerations. + * + * <em>Close a group</em> + * \code + * herr_t status; + * + * status = H5Gclose(group); + * \endcode + * + * A non-negative return value indicates that the group was successfully closed and the resources + * released; a negative return value indicates that the attempt to close the group or release resources + * failed. + * + * \subsubsection subsubsec_group_program_links Creating Links + * As previously mentioned, every object is created in a specific group. Once created, an object can + * be made a member of additional groups by means of links created with one of the H5Lcreate_* + * functions. + * + * A link is, in effect, a path by which the target object can be accessed; it therefore has a name + * which functions as a single path component. A link can be removed with an #H5Ldelete call, + * effectively removing the target object from the group that contained the link (assuming, of + * course, that the removed link was the only link to the target object in the group). + * + * <h4>Hard Links</h4> + * There are two kinds of links, hard links and symbolic links. Hard links are reference counted; + * symbolic links are not. When an object is created, a hard link is automatically created. An object + * can be deleted from the file by removing all the hard links to it. + * + * Working with the file from the previous examples, the code in the example below illustrates the + * creation of a hard link, named Data_link, in the root group, /, to the group Data. Once that link is + * created, the dataset Cdata can be accessed via either of two absolute paths, /Data/Cdata or + * /Data_Link/Cdata. + * + * <em>Create a hard link</em> + * \code + * status = H5Lcreate_hard(Data_loc_id, "Data", DataLink_loc_id, "Data_link", H5P_DEFAULT, H5P_DEFAULT); + * + * dataset1 = H5Dopen(file, "/Data_link/CData", H5P_DEFAULT); + * dataset2 = H5Dopen(file, "/Data/CData", H5P_DEFAULT); + * \endcode + * + * The example below shows example code to delete a link, deleting the hard link Data from the + * root group. The group /Data and its members are still in the file, but they can no longer be + * accessed via a path using the component /Data. + * + * <em>Delete a link</em> + * \code + * status = H5Ldelete(Data_loc_id, "Data", H5P_DEFAULT); + * + * dataset1 = H5Dopen(file, "/Data_link/CData", H5P_DEFAULT); + * // This call should succeed; all path components still exist + * dataset2 = H5Dopen(file, "/Data/CData", H5P_DEFAULT); + * // This call will fail; the path component '/Data' has been deleted. + * \endcode + * + * When the last hard link to an object is deleted, the object is no longer accessible. #H5Ldelete will + * not prevent you from deleting the last link to an object. To see if an object has only one link, use + * the #H5Oget_info function. If the value of the rc (reference count) field in the is greater than 1, + * then the link can be deleted without making the object inaccessible. + * + * The example below shows #H5Oget_info to the group originally called Data. + * + * <em>Finding the number of links to an object</em> + * \code + * status = H5Oget_info(Data_loc_id, object_info); + * \endcode + * + * It is possible to delete the last hard link to an object and not make the object inaccessible. + * Suppose your application opens a dataset, and then deletes the last hard link to the dataset. While + * the dataset is open, your application still has a connection to the dataset. If your application + * creates a hard link to the dataset before it closes the dataset, then the dataset will still be + * accessible. + * + * <h4>Symbolic Links</h4> + * Symbolic links are objects that assign a name in a group to a path. Notably, the target object is + * determined only when the symbolic link is accessed, and may, in fact, not exist. Symbolic links + * are not reference counted, so there may be zero, one, or more symbolic links to an object. + * + * The major types of symbolic links are soft links and external links. Soft links are symbolic links + * within an HDF5 file and are created with the #H5Lcreate_soft function. Symbolic links to objects + * located in external files, in other words external links, can be created with the + * #H5Lcreate_external function. Symbolic links are removed with the #H5Ldelete function. + * + * The example below shows the creating two soft links to the group /Data. + * + * <em>Create a soft link</em> + * \code + * status = H5Lcreate_soft(path_to_target, link_loc_id, "Soft2", H5P_DEFAULT, H5P_DEFAULT); + * status = H5Lcreate_soft(path_to_target, link_loc_id, "Soft3", H5P_DEFAULT, H5P_DEFAULT); + * dataset = H5Dopen(file, "/Soft2/CData", H5P_DEFAULT); + * \endcode + * + * With the soft links defined in the example above, the dataset CData in the group /Data can now + * be opened with any of the names /Data/CData, /Soft2/CData, or /Soft3/CData. + * + * In release 1.8.7, a cache was added to hold the names of files accessed via external links. The + * size of this cache can be changed to help improve performance. For more information, see the + * entry in the \ref RM for the #H5Pset_elink_file_cache_size function call. + * + * <h4>Note Regarding Hard Links and Soft Links</h4> + * Note that an object’s existence in a file is governed by the presence of at least one hard link to + * that object. If the last hard link to an object is removed, the object is removed from the file and + * any remaining soft link becomes a dangling link, a link whose target object does not exist. + * + * <h4>Moving or Renaming Objects, and a Warning</h4> + * An object can be renamed by changing the name of a link to it with #H5Lmove. This has the same + * effect as creating a new link with the new name and deleting the link with the old name. + * + * Exercise caution in the use of #H5Lmove and #H5Ldelete as these functions each include a step + * that unlinks a pointer to an HDF5 object. If the link that is removed is on the only path leading to + * an HDF5 object, that object will become permanently inaccessible in the file. + * + * <h5>Scenario 1: Removing the Last Link</h5> + * To avoid removing the last link to an object or otherwise making an object inaccessible, use the + * #H5Oget_info function. Make sure that the value of the reference count field (rc) is greater than 1. + * + * <h5>Scenario 2: Moving a Link that Isolates an Object</h5> + * Consider the following example: assume that the group group2 can only be accessed via the + * following path, where top_group is a member of the file’s root group: + * <em>/top_group/group1/group2/</em> + * + * Using #H5Lmove, top_group is renamed to be a member ofgroup2. At this point, since + * top_group was the only route from the root group to group1, there is no longer a path by which + * one can access group1, group2, or any member datasets. And since top_group is now a member + * of group2, top_group itself and any member datasets have thereby also become inaccessible. + * + * <h4>Mounting a File</h4> + * An external link is a permanent connection between two files. A temporary connection can be set + * up with the #H5Fmount function. For more information, @see sec_file. + * For more information, see the #H5Fmount function in the \ref RM. + * + * \subsubsection subsubsec_group_program_info Discovering Information about Objects + * There is often a need to retrieve information about a particular object. The #H5Lget_info and + * #H5Oget_info functions fill this niche by returning a description of the object or link in an + * #H5L_info_t or #H5O_info_t structure. + * + * \subsubsection subsubsec_group_program_objs Discovering Objects in a Group + * To examine all the objects or links in a group, use the #H5Literate or #H5Ovisit functions to + * examine the objects, and use the #H5Lvisit function to examine the links. #H5Literate is useful + * both with a single group and in an iterative process that examines an entire file or section of a + * file (such as the contents of a group or the contents of all the groups that are members of that + * group) and acts on objects as they are encountered. #H5Ovisit recursively visits all objects + * accessible from a specified object. #H5Lvisit recursively visits all the links starting from a + * specified group. + * + * \subsubsection subsubsec_group_program_all Discovering All of the Objects in the File + * The structure of an HDF5 file is self-describing, meaning that an application can navigate an + * HDF5 file to discover and understand all the objects it contains. This is an iterative process + * wherein the structure is traversed as a graph, starting at one node and recursively visiting linked + * nodes. To explore the entire file, the traversal should start at the root group. + * + * \subsection subsec_group_examples Examples of File Structures + * This section presents several samples of HDF5 file structures. + * + * Figure 9 shows examples of the structure of a file with three groups and one dataset. The file in + * part a contains three groups: the root group and two member groups. In part b, the dataset + * dset1 has been created in /group1. In part c, a link named dset2 from /group2 to the dataset has + * been added. Note that there is only one copy of the dataset; there are two links to it and it can be + * accessed either as /group1/dset1 or as /group2/dset2. + * + * Part d illustrates that one of the two links to the dataset can be deleted. In this case, the link from + * <em>/group1</em> + * has been removed. The dataset itself has not been deleted; it is still in the file but can only be + * accessed as + * <em>/group2/dset2</em> + * + * <table> + * <caption>Figure 9 - Some file structures</caption> + * <tr> + * <td> + * \image html Groups_fig9_a.gif "a) The file contains three groups: the root group, /group1, and /group2." + * </td> + * <td> + * \image html Groups_fig9_b.gif "b) The dataset dset1 (or /group1/dset1) is created in /group1." + * </td> + * </tr> + * <tr> + * <td> + * \image html Groups_fig9_aa.gif "c) A link named dset2 to the same dataset is created in /group2." + * </td> + * <td> + * \image html Groups_fig9_bb.gif "d) The link from /group1 to dset1 is removed. The dataset is + * still in the file, but can be accessed only as /group2/dset2." + * </td> + * </tr> + * </table> + * + * Figure 10 illustrates loops in an HDF5 file structure. The file in part a contains three groups + * and a dataset; group2 is a member of the root group and of the root group’s other member group, + * group1. group2 thus can be accessed by either of two paths: /group2 or /group1/GXX. Similarly, + * the dataset can be accessed either as /group2/dset1 or as /group1/GXX/dset1. + * + * Part b illustrates a different case: the dataset is a member of a single group but with two links, or + * names, in that group. In this case, the dataset again has two names, /group1/dset1 and + * /group1/dset2. + * + * In part c, the dataset dset1 is a member of two groups, one of which can be accessed by either of + * two names. The dataset thus has three path names: /group1/dset1, /group2/dset2, and + * /group1/GXX/dset2. + * + * And in part d, two of the groups are members of each other and the dataset is a member of both + * groups. In this case, there are an infinite number of paths to the dataset because GXX and + * GYY can be traversed any number of times on the way from the root group, /, to the dataset. This + * can yield a path name such as /group1/GXX/GYY/GXX/GYY/GXX/dset2. + * + * <table> + * <caption>Figure 10 - More sample file structures</caption> + * <tr> + * <td> + * \image html Groups_fig10_a.gif "a) dset1 has two names: /group2/dset1 and /group1/GXX/dset1." + * </td> + * <td> + * \image html Groups_fig10_b.gif "b) dset1 again has two names: /group1/dset1 and /group1/dset2." + * </td> + * </tr> + * <tr> + * <td> + * \image html Groups_fig10_c.gif "c) dset1 has three names: /group1/dset1, /group2/dset2, and + * /group1/GXX/dset2." + * </td> + * <td> + * \image html Groups_fig10_d.gif "d) dset1 has an infinite number of available path names." + * </td> + * </tr> + * </table> + * + * Figure 11 takes us into the realm of soft links. The original file, in part a, contains only three + * hard links. In part b, a soft link named dset2 from group2 to /group1/dset1 has been created, + * making this dataset accessible as /group2/dset2. + * + * In part c, another soft link has been created in group2. But this time the soft link, dset3, points + * to a target object that does not yet exist. That target object, dset, has been added in part d and is + * now accessible as either /group2/dset or /group2/dset3. + * + * It could be said that HDF5 extends the organizing concepts of a file system to the internal + * structure of a single file. + * + * <table> + * <caption>Figure 11 - Hard and soft links</caption> + * <tr> + * <td> + * \image html Groups_fig11_a.gif "a) The file contains only hard links." + * </td> + * <td> + * \image html Groups_fig11_b.gif "b) A soft link is added from group2 to /group1/dset1." + * </td> + * </tr> + * <tr> + * <td> + * \image html Groups_fig11_c.gif "c) A soft link named dset3 is added with a target that does not yet exist." + * </td> + * <td> + * \image html Groups_fig11_d.gif "d) The target of the soft link is created or linked." + * </td> + * </tr> + * </table> + * + * Previous Chapter \ref sec_file - Next Chapter \ref sec_dataset + * + */ + +/** + * \defgroup H5G Groups (H5G) * * Use the functions in this module to manage HDF5 groups. * diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 1d8f8fb..74f0da7 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -167,7 +167,7 @@ H5_DLL hid_t H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcp * H5Gclose() when the group is no longer needed so that resource * leaks will not develop. * - * \see H5Olink(), H5Dcreate(), Using Identifiers + * \see H5Olink(), H5Dcreate(), \ref api-compat-macros * * \since 1.8.0 * @@ -660,7 +660,7 @@ H5_DLL herr_t H5Glink2(hid_t cur_loc_id, const char *cur_name, H5G_link_t type, * * \attention Exercise care in moving groups as it is possible to render data in * a file inaccessible with H5Gmove(). See The Group Interface in the - * HDF5 User's Guide. + * \ref UG. * * \version 1.8.0 Function deprecated in this release. * @@ -691,7 +691,7 @@ H5_DLL herr_t H5Gmove(hid_t src_loc_id, const char *src_name, const char *dst_na * * \attention Exercise care in moving groups as it is possible to render data in * a file inaccessible with H5Gmove2(). See The Group Interface in the - * HDF5 User's Guide. + * \ref UG. * * \version 1.8.0 Function deprecated in this release. * @@ -728,11 +728,11 @@ H5_DLL herr_t H5Gmove2(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, * Note that space identified as freespace is available for re-use only * as long as the file remains open; once a file has been closed, the * HDF5 library loses track of freespace. See “Freespace Management” in - * the HDF5 User's Guide for further details. + * the \ref UG for further details. * * \attention Exercise care in moving groups as it is possible to render data in * a file inaccessible with H5Gunlink(). See The Group Interface in the - * HDF5 User's Guide. + * \ref UG. * * \version 1.8.0 Function deprecated in this release. * diff --git a/src/H5Imodule.h b/src/H5Imodule.h index d77591d..1ad9f1b 100644 --- a/src/H5Imodule.h +++ b/src/H5Imodule.h @@ -29,7 +29,8 @@ #define H5_MY_PKG_ERR H5E_ATOM #define H5_MY_PKG_INIT NO -/**\defgroup H5I H5I +/** + * \defgroup H5I Identifiers (H5I) * * Use the functions in this module to manage identifiers defined by the HDF5 * library. See \ref H5IUD for user-defined identifiers and identifier diff --git a/src/H5Lmodule.h b/src/H5Lmodule.h index cffd25c..f61b891 100644 --- a/src/H5Lmodule.h +++ b/src/H5Lmodule.h @@ -29,7 +29,8 @@ #define H5_MY_PKG_ERR H5E_LINK #define H5_MY_PKG_INIT YES -/**\defgroup H5L H5L +/** + * \defgroup H5L Links (H5L) * * Use the functions in this module to manage HDF5 links and link types. * diff --git a/src/H5Mmodule.h b/src/H5Mmodule.h index 848f63f..6c49a45 100644 --- a/src/H5Mmodule.h +++ b/src/H5Mmodule.h @@ -26,10 +26,24 @@ #define H5_MY_PKG_ERR H5E_MAP #define H5_MY_PKG_INIT YES -/**\defgroup H5M H5M +/** + * \page H5M_UG The HDF5 VOL Data Mapping + * \Bold{The HDF5 Data Mapping can only be used with the HDF5 VOL connectors that + * implement map objects.} The native HDF5 library does not support this feature. + * + * \section sec_map The HDF5 Map Object * * \todo Describe the map life cycle. * + * \todo How does MAPL fit into \ref subsubsec_plist_class. + * + * Previous Chapter \ref sec_vol - Next Chapter \ref sec_addition + * + */ + +/** + * \defgroup H5M VOL Mapping (H5M) + * * \details \Bold{The interface can only be used with the HDF5 VOL connectors that * implement map objects.} The native HDF5 library does not support this * feature. diff --git a/src/H5Omodule.h b/src/H5Omodule.h index 8afba29..977861b 100644 --- a/src/H5Omodule.h +++ b/src/H5Omodule.h @@ -29,7 +29,8 @@ #define H5_MY_PKG_ERR H5E_OHDR #define H5_MY_PKG_INIT YES -/**\defgroup H5O H5O +/** + * \defgroup H5O Objects (H5O) * * Use the functions in this module to manage HDF5 objects. * diff --git a/src/H5Opublic.h b/src/H5Opublic.h index ec2d97a..cc131e1 100644 --- a/src/H5Opublic.h +++ b/src/H5Opublic.h @@ -755,7 +755,7 @@ H5_DLL herr_t H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_ * * An object’s reference count is the number of hard links in the * file that point to that object. See the “Programming Model” - * section of the HDF5 Groups chapter in the -- <em>HDF5 User’s Guide</em> + * section of the HDF5 Groups chapter in the -- <em>\ref UG</em> * for a more complete discussion of reference counts. * * If a user application needs to determine an object’s reference @@ -790,7 +790,7 @@ H5_DLL herr_t H5Oincr_refcount(hid_t object_id); * * An object’s reference count is the number of hard links in the * file that point to that object. See the “Programming Model” - * section of the HDF5 Groups chapter in the <em>HDF5 User’s Guide</em> + * section of the HDF5 Groups chapter in the <em>\ref UG</em> * for a more complete discussion of reference counts. * * If a user application needs to determine an object’s reference diff --git a/src/H5PLmodule.h b/src/H5PLmodule.h index a093096..84d3583 100644 --- a/src/H5PLmodule.h +++ b/src/H5PLmodule.h @@ -2,7 +2,7 @@ * Copyright by The HDF Group. * * All rights reserved. * * * - * This file is part of HDF5. The full HDF5 copyright notice, including * + * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * @@ -27,7 +27,8 @@ #define H5_MY_PKG_ERR H5E_PLUGIN #define H5_MY_PKG_INIT YES -/**\defgroup H5PL H5PL +/** + * \defgroup H5PL Dynamically-loaded Plugins (H5PL) * * Use the functions in this module to manage the loading behavior of HDF5 * plugins. diff --git a/src/H5Pmodule.h b/src/H5Pmodule.h index 66a9574..c7ab3bd 100644 --- a/src/H5Pmodule.h +++ b/src/H5Pmodule.h @@ -29,7 +29,860 @@ #define H5_MY_PKG_ERR H5E_PLIST #define H5_MY_PKG_INIT YES -/**\defgroup H5P H5P +/** \page H5P_UG Properties and Property Lists in HDF5 + * + * \section sec_plist Properties and Property Lists in HDF5 + * + * HDF5 property lists are the main vehicle to configure the + * behavior of HDF5 API functions. + * + * Typically, property lists are created by instantiating one of the built-in + * or user-defined property list classes. After adding suitable properties, + * property lists are used when opening or creating HDF5 items, or when reading + * or writing data. Property lists can be modified by adding or changing + * properties. Property lists are deleted by closing the associated handles. + * + * \subsection subsec_plist_intro Introduction + * + * HDF5 properties and property lists make it possible to shape or modify an HDF5 file, group, + * dataset, attribute, committed datatype, or even an I/O stream, in a number of ways. For example, + * you can do any of the following: + * \li Customize the storage layout of a file to suit a project or task. + * \li Create a chunked dataset. + * \li Apply compression or filters to raw data. + * \li Use either ASCII or UTF-8 character encodings. + * \li Create missing groups on the fly. + * \li Switch between serial and parallel I/O. + * \li Create consistency within a single file or across an international project. + * + * Some properties enable an HDF5 application to take advantage of the capabilities of a specific + * computing environment while others make a file more compact; some speed the reading or + * writing of data while others enable more record-keeping at a per-object level. HDF5 offers + * nearly one hundred specific properties that can be used in literally thousands of combinations to + * maximize the usability of HDF5-stored data. + * + * At the most basic level, a property list is a collection of properties, represented by name/value + * pairs that can be passed to various HDF5 functions, usually modifying default settings. A + * property list inherits a set of properties and values from a property list class. But that statement + * hardly provides a complete picture; in the rest of this section and in the next section, + * \ref subsec_plist_class , we will discuss these things in much more detail. + * After reading that material, the reader should have a reasonably complete understanding of how + * properties and property lists can be used in HDF5 applications. + * + * <table> + * <tr> + * <td> + * \image html PropListEcosystem.gif "The HDF5 property environment" + * </td> + * </tr> + * </table> + * + * The remaining sections in this chapter discuss the following topics: + * \li What are properties, property lists, and property list classes? + * \li Property list programming model + * \li Generic property functions + * \li Summary listings of property list functions + * \li Additional resources + * + * The discussions and function listings in this chapter focus on general property operations, object + * and link properties, and related functions. + * + * File, group, dataset, datatype, and attribute properties are discussed in the chapters devoted to + * those features, where that information will be most convenient to users. For example, \ref sec_dataset + * discusses dataset creation property lists and functions, dataset access property lists and + * functions, and dataset transfer property lists and functions. This chapter does not duplicate those + * discussions. + * + * Generic property operations are an advanced feature and are beyond the scope of this guide. + * + * This chapter assumes an understanding of the following chapters of this \ref UG + * \li \ref sec_data_model + * \li \ref sec_program + * + * \subsection subsec_plist_class Property List Classes, Property Lists, and Properties + * + * HDF5 property lists and the property list interface \ref H5P provide a mechanism for storing + * characteristics of objects in an HDF5 file and economically passing them around in an HDF5 + * application. In this capacity, property lists significantly reduce the burden of additional function + * parameters throughout the HDF5 API. Another advantage of property lists is that features can + * often be added to HDF5 by adding only property list functions to the API; this is particularly true + * when all other requirements of the feature can be accomplished internally to the library. + * + * For instance, a file creation operation needs to know several things about a file, such as the size + * of the userblock or the sizes of various file data structures. Bundling this information as a + * property list simplifies the interface by reducing the number of parameters to the function + * \ref H5Fcreate. + * + * As illustrated in the figure above ("The HDF5 property environment"), the HDF5 property + * environment is a three-level hierarchy: + * \li Property list classes + * \li Property lists + * \li Properties + * + * The following subsections discuss property list classes, property lists, and properties in more detail. + * + * \subsubsection subsubsec_plist_class Property List Classes + * + * A property list class defines the roles that property lists of that class can play. Each class includes + * all properties that are valid for that class with each property set to its default value. HDF5 offers + * a property lists class for each of the following situations. + * + * <table> + * <caption align=top id="table_plist">Property list classes in HDF5</caption> + * <tr><th>Property List Class</th><th></th><th>For further discussion</th></tr> + * <tr valign="top"> + * <td> + * File creation (FCPL) + * </td> + * <td> + * \ref H5P_FILE_CREATE + * </td> + * <td> + * See various sections of \ref sec_file + * </td> + * <tr valign="top"> + * <td> + * File access (FAPL) + * </td> + * <td> + * \ref H5P_FILE_ACCESS + * </td> + * <td> + * Used only as \ref H5P_DEFAULT. + * </td> + * </tr> + * <tr valign="top"> + * <td> + * File mount (FMPL) + * </td> + * <td> + * \ref H5P_FILE_MOUNT + * </td> + * <td> + * For more information, see \ref FileMountProps "File Mount Properties" + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Object creation (OCPL) + * </td> + * <td> + * \ref H5P_OBJECT_CREATE + * </td> + * <td> + * See \ref OCPL + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Object copy (OCPYPL) + * </td> + * <td> + * \ref H5P_OBJECT_COPY + * </td> + * <td> + * + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Group creation (GCPL) + * </td> + * <td> + * \ref H5P_GROUP_CREATE + * </td> + * <td> + * See \ref subsec_group_program + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Group access (GAPL) + * </td> + * <td> + * \ref H5P_GROUP_ACCESS + * </td> + * <td> + * + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Link creation (LCPL) + * </td> + * <td> + * \ref H5P_LINK_CREATE + * </td> + * <td> + * See examples in \ref subsec_plist_program and \ref LCPL + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Link access (LAPL) + * </td> + * <td> + * \ref H5P_LINK_ACCESS + * </td> + * <td> + * + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Dataset creation (DCPL) + * </td> + * <td> + * \ref H5P_DATASET_CREATE + * </td> + * <td> + * See \ref subsec_dataset_program + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Dataset access (DAPL) + * </td> + * <td> + * \ref H5P_DATASET_ACCESS + * </td> + * <td> + * + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Dataset transfer (DXPL) + * </td> + * <td> + * \ref H5P_DATASET_XFER + * </td> + * <td> + * + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Datatype creation (TCPL) + * </td> + * <td> + * \ref H5P_DATATYPE_CREATE + * </td> + * <td> + * See various sections of \ref sec_datatype + * </td> + * </tr> + * <tr valign="top"> + * <td> + * String creation (STRCPL) + * </td> + * <td> + * \ref H5P_STRING_CREATE + * </td> + * <td> + * See \ref subsec_dataset_program and \ref subsec_datatype_program + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Attribute creation (ACPL) + * </td> + * <td> + * \ref H5P_ATTRIBUTE_CREATE + * </td> + * <td> + * See \ref subsec_attribute_work. + * </td> + * </tr> + * </table> + * + * Note: In the table above, the abbreviations to the right of each property list class name in this + * table are widely used in both HDF5 programmer documentation and HDF5 source code. For + * example, \ref FCPL (FCPL) is the file creation property list, \ref OCPL (OCPL) is the object creation + * property list, \ref OCPYPL (OCPYPL) is object copy property list, and \ref STRCPL (STRCPL) is the string + * creation property list. These abbreviations may appear in either uppercase or lowercase. + * + * The “HDF5 property list class inheritance hierarchy” figure, immediately following, illustrates + * the inheritance hierarchy of HDF5’s property list classes. Properties are defined at the root of the + * HDF5 property environment (\ref PLCR in the figure below). Property list + * classes then inherit properties from that root, either directly or indirectly through a parent class. + * In every case, a property list class inherits only the properties relevant to its role. For example, + * the \ref OCPL (OCPL) inherits all properties that are relevant to the + * creation of any object while the \ref GCPL (GCPL) inherits only those + * properties that are relevant to group creation. + * + * <table> + * <tr> + * <td> + * \image html PropListClassInheritance.gif "HDF5 property list class inheritance hierarchy" + * </td> + * </tr> + * </table> + * Note: In the figure above, property list classes displayed in black are directly accessible through + * the programming interface; the root of the property environment and the \ref STRCPL and \ref OCPL + * property list classes, in gray above, are not user-accessible. The red empty set symbol indicates + * that the \ref FMPL (FMPL) is an empty class; that is, it has no set table + * properties. For more information, see \ref FileMountProps "File Mount Properties". Abbreviations + * used in this figure are defined in the preceding table, \ref table_plist "Property list classes in HDF5". + * + * \subsubsection subsubsec_plist_lists Property Lists + * + * A property list is a collection of related properties that are used together in specific + * circumstances. A new property list created from a property list class inherits the properties of the + * property list class and each property’s default value. A fresh dataset creation property list, for + * example, includes all of the HDF5 properties relevant to the creation of a new dataset. + * + * Property lists are implemented as containers holding a collection of name/value pairs. Each pair + * specifies a property name and a value for the property. A property list usually contains + * information for one to many properties. + * + * HDF5’s default property values are designed to be reasonable for general use cases. Therefore, + * an application can often use a property list without modification. On the other hand, adjusting + * property list settings is a routine action and there are many reasons for an application to do so. + * + * A new property list may either be derived from a property list class or copied from an existing + * property list. When a property list is created from a property list class, it contains all the + * properties that are relevant to the class, with each property set to its default value. A new + * property list created by copying an existing property list will contain the same properties and + * property values as the original property list. In either case, the property values can be changed as + * needed through the HDF5 API. + * + * Property lists can be freely reused to create consistency. For example, a single set of file, group, + * and dataset creation property lists might be created at the beginning of a project and used to + * create hundreds, thousands, even millions, of consistent files, file structures, and datasets over + * the project’s life. When such consistency is important to a project, this is an economical means + * of providing it. + * + * \subsubsection subsubsec_plist_props Properties + * + * A property is the basic element of the property list hierarchy. HDF5 offers nearly one hundred + * properties controlling things ranging from file access rights, to the storage layout of a dataset, + * through optimizing the use of a parallel computing environment. + * + * Further examples include the following: + * <table> + * <tr><th>Purpose</th><th>Examples</th><th>Property List</th></tr> + * <tr valign="top"> + * <td> + * Specify the driver to be used to open a file + * </td> + * <td> + * A POSIX driver or an MPI IO driver + * </td> + * <td> + * \ref FAPL + * </td> + * <tr valign="top"> + * <td> + * Specify filters to be applied to a dataset + * </td> + * <td> + * Gzip compression or checksum evaluation + * </td> + * <td> + * \ref DCPL + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Specify whether to record key times associated with an object + * </td> + * <td> + * Creation time and/or last-modified time + * </td> + * <td> + * \ref OCPL + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Specify the access mode for a file opened via an external link + * </td> + * <td> + * Read-only or read-write + * </td> + * <td> + * \ref LAPL + * </td> + * </tr> + * </table> + * + * Each property is initialized with a default value. For each property, there are one or more + * dedicated H5Pset_*calls that can be used to change that value. + * + * <h4>Creation, access, and transfer properties:</h4> + * + * Properties fall into one of several major categories: creation properties, access properties, and + * transfer properties. + * + * Creation properties control permanent object characteristics. These characteristics must be + * established when an object is created, cannot change through the life of the object (they are + * immutable), and the property setting usually has a permanent presence in the file. + * + * <table> + * <caption align=top>Examples of creation properties include:</caption> + * <tr> + * <td> + * <p> + * Whether a dataset is stored in a compact, contiguous, or chunked layout <br /> + * <br /> + * The default for this dataset creation property (\ref H5Pset_layout) is that a dataset is + * stored in a contiguous block. This works well for datasets with a known size limit that + * will fit easily in system memory. <br /> + * <br /> + * A chunked layout is important if a dataset is to be compressed, to enable extending + * the dataset’s size, or to enable caching during I/O. <br /> + * <br /> + * A compact layout is suitable only for very small datasets because the raw data is + * stored in the object header. + * </p> + * </td> + * </tr> + * <tr> + * <td> + * <p> + * Creation of intermediate groups when adding an object to an HDF5 file<br /> + * <br /> + * This link creation property, \ref H5Pset_create_intermediate_group, enables an + * application to add an object in a file without having to know that the group or group + * hierarchy containing that object already exists. With this property set, HDF5 + * automatically creates missing groups. If this property is not set, an application must + * verify that each group in the path exists, and create those that do not, before creating + * the new object; if any group is missing, the create operation will fail. + * </p> + * </td> + * </tr> + * <tr> + * <td> + * <p> + * Whether an HDF5 file is a single file or a set of tightly related files that form a virtual + * HDF5 file<br /> + * <br /> + * Certain file creation properties enable the application to select one of several file + * layouts. Examples of the available layouts include a standard POSIX-compliant + * layout (\ref H5Pset_fapl_sec2), a family of files (\ref H5Pset_fapl_family), and a split file + * layout that separates raw data and metadata into separate files (\ref H5Pset_fapl_split). + * These and other file layout options are discussed in \ref subsec_file_alternate_drivers. + * </p> + * </td> + * </tr> + * <tr> + * <td> + * <p> + * To enable error detection when creating a dataset<br /> + * <br /> + * In settings where data integrity is vulnerable, it may be desirable to set + * checksumming when datasets are created (\ref H5Pset_fletcher32). A subsequent + * application will then have a means to verify data integrity when reading the dataset. + * </p> + * </td> + * </tr> + * </table> + * + * Access properties control transient object characteristics. These characteristics may change with + * the circumstances under which an object is accessed. + * + * <table> + * <caption align=top>Examples of access properties include:</caption> + * <tr> + * <td> + * <p> + * The driver used to open a file<br /> + * <br /> + * For example, a file might be created with the MPI I/O driver (\ref H5Pset_fapl_mpio) + * during high-speed data acquisition in a parallel computing environment. The same + * file might later be analyzed in a serial computing environment with I/O access + * handled through the serial POSIX driver (\ref H5Pset_fapl_sec2). + * </p> + * </td> + * </tr> + * <tr> + * <td> + * <p> + * Optimization settings in specialized environments<br /> + * <br /> + * Optimizations differ across computing environments and according to the needs of + * the task being performed, so are transient by nature. + * </p> + * </td> + * </tr> + * </table> + * + * Transfer properties apply only to datasets and control transient aspects of data I/O. These + * characteristics may change with the circumstances under which data is accessed. + * + * <table> + * <caption align=top>Examples of dataset transfer properties include:</caption> + * <tr> + * <td> + * <p> + * To enable error detection when reading a dataset<br /> + * <br /> + * If checksumming has been set on a dataset (with \ref H5Pset_fletcher32, in the dataset + * creation property list), an application reading that dataset can choose whether to check + * for data integrity (\ref H5Pset_edc_check). + * </p> + * </td> + * </tr> + * <tr> + * <td> + * <p> + * Various properties to optimize chunked data I/O on parallel computing systems<br /> + * <br /> + * HDF5 provides several properties for tuning I/O of chunked datasets in a parallel + * computing environment (\ref H5Pset_dxpl_mpio_chunk_opt, \ref H5Pset_dxpl_mpio_chunk_opt_num, + * \ref H5Pset_dxpl_mpio_chunk_opt_ratio, and \ref H5Pget_mpio_actual_chunk_opt_mode).<br /> + * <br /> + * Optimal settings differ due to the characteristics of a computing environment and due + * to an application’s data access patterns; even when working with the same file, these + * settings might change for every application and every platform. + * </p> + * </td> + * </tr> + * </table> + * + * \subsection subsec_plist_program Programming Model for Properties and Property Lists + * + * The programming model for HDF5 property lists is actually quite simple: + * \li Create a property list. + * \li Modify the property list, if required. + * \li Use the property list. + * \li Close the property list. + * + * There are nuances, of course, but that is the basic process. + * + * In some cases, you will not have to define property lists at all. If the default property settings are + * sufficient for your application, you can tell HDF5 to use the default property list. + * + * The following sections first discuss the use of default property lists, then each step of the + * programming model, and finally a few less frequently used property list operations. + * + * \subsubsection subsubsec_plist_default Using Default Property Lists + * + * Default property lists can simplify many routine HDF5 tasks because you do not always have to + * create every property list you use. + * + * An application that would be well-served by HDF5’s default property settings can use the default + * property lists simply by substituting the value \ref H5P_DEFAULT for a property list identifier. + * HDF5 will then apply the default property list for the appropriate property list class. + * + * For example, the function \ref H5Dcreate2 calls for a link creation property list, a dataset creation + * property list, and a dataset access property list. If the default properties are suitable for a dataset, + * this call can be made as + * \code + * dset_id = H5Dcreate2( loc_id, name, dtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ); + * \endcode + * HDF5 will then apply the default link creation, dataset creation, and dataset access property lists + * correctly. + * + * Of course, you would not want to do this without considering where it is appropriate, as there + * may be unforeseen consequences. Consider, for example, the use of chunked datasets. Optimal + * chunking is quite dependent on the makeup of the dataset and the most common access patterns, + * both of which must be taken into account in setting up the size and shape of chunks. + * + * \subsubsection subsubsec_plist_basic Basic Steps of the Programming Model + * + * The steps of the property list programming model are described in the sub-sections below. + * + * <h4>Create a Property List</h4> + * + * A new property list can be created either as an instance of a property list class or by copying an + * existing property list. Consider the following examples. A new dataset creation property list is + * first created "from scratch" with \ref H5Pcreate. A second dataset creation property list is then + * created by copying the first one with \ref H5Pcopy. + * + * \code + * dcplA_id = H5Pcreate (H5P_DATASET_CREATE); + * \endcode + * + * The new dataset creation property list is created as an instance of the property list class + * \ref H5P_DATASET_CREATE. + * + * The new dataset creation property list’s identifier is returned in dcplA_id and the property list is + * initialized with default dataset creation property values. + * + * A list of valid classes appears in the table \ref table_plist "Property list classes in HDF5". + * + * \code + * dcplB_id = H5Pcopy (dcplA_id); + * \endcode + * + * A new dataset creation property list, dcplB_id, is created as a copy of dcplA_id and is initialized + * with dataset creation property values currently in dcplA_id. + * + * At this point, dcplA_id and dcplB_id are identical; they will both contain any modified property + * values that were changed in dcplA_id before dcplB_id was created. They may, however, diverge + * as additional property values are reset in each. + * + * While we are creating property lists, let’s create a link creation property list; we will need this + * property list when the new dataset is linked into the file below: + * \code + * lcplAB_id = H5Pcreate (H5P_LINK_CREATE); + * \endcode + * + * <h4>Change Property Values</h4> + * + * This section describes how to set property values. + * + * Later in this section, the dataset creation property lists dcplA_id and dcplB_id created in the + * section above will be used respectively to create chunked and contiguous datasets. To set this up, + * we must set the layout property in each property list. The following example sets dcplA_id for + * chunked datasets and dcplB_id for contiguous datasets: + * \code + * error = H5Pset_layout (dcplA_id, H5D_CHUNKED); + * error = H5Pset_layout (dcplB_id, H5D_CONTIGUOUS); + * \endcode + * + * Since dcplA_id specifies a chunked layout, we must also set the number of dimensions and the + * size of the chunks. The example below specifies that datasets created with dcplA_id will be + * 3-dimensional and that the chunk size will be 100 in each dimension: + * \code + * error = H5Pset_chunk (dcplA_id, 3, [100,100,100]); + * \endcode + * + * These datasets will be created with UTF-8 encoded names. To accomplish that, the following + * example sets the character encoding property in the link creation property list to create link + * names with UTF-8 encoding: + * \code + * error = H5Pset_char_encoding (lcplAB_id, H5T_CSET_UTF8); + * \endcode + * + * dcplA_id can now be used to create chunked datasets and dcplB_id to create contiguous datasets. + * And with the use of lcplAB_id, they will be created with UTF-8 encoded names. + * + * <h4>Use the Property List</h4> + * + * Once the required property lists have been created, they can be used to control various HDF5 + * processes. For illustration, consider dataset creation. + * + * Assume that the datatype dtypeAB and the dataspaces dspaceA and dspaceB have been defined + * and that the location identifier locAB_id specifies the group AB in the current HDF5 file. We + * have already created the required link creation and dataset creation property lists. + * For the sake of illustration, we assume that the default dataset access property list meets our application + * requirements. The following calls would create the datasets dsetA and dsetB in the group AB. + * The raw data in dsetA will be contiguous while dsetB raw data will be chunked; both datasets + * will have UTF-8 encoded link names: + * + * \code + * dsetA_id = H5Dcreate2( locAB_id, dsetA, dtypeAB, dspaceA_id, + * lcplAB_id, dcplA_id, H5P_DEFAULT ); + * dsetB_id = H5Dcreate2( locAB_id, dsetB, dtypeAB, dspaceB_id, + * lcplAB_id, dcplB_id, H5P_DEFAULT ); + * \endcode + * + * <h4>Close the Property List</h4> + * + * Generally, creating or opening anything in an HDF5 file results in an HDF5 identifier. These + * identifiers are of HDF5 type hid_t and include things like file identifiers, often expressed as + * file_id; dataset identifiers, dset_id; and property list identifiers, plist_id. To reduce the risk of + * memory leaks, all of these identifiers must be closed once they are no longer needed. + * + * Property list identifiers are no exception to this rule, and \ref H5Pclose is used for this purpose. The + * calls immediately following would close the property lists created and used in the examples above. + * + * \code + * error = H5Pclose (dcplA_id); + * error = H5Pclose (dcplB_id); + * error = H5Pclose (lcplAB_id); + * \endcode + * + * \subsubsection subsubsec_plist_additional Additional Property List Operations + * + * A few property list operations fall outside of the programming model described above. This + * section describes those operations. + * + * <h4>Query the Class of an Existing Property List</h4> + * + * Occasionally an application will have a property list but not know the corresponding property list + * class. A call such as in the following example will retrieve the unknown class of a known property list: + * \code + * PList_Class = H5Pget_class (dcplA_id); + * \endcode + * + * Upon this function’s return, PList_Class will contain the value \ref H5P_DATASET_CREATE indicating that + * dcplA_id is a dataset creation property list. + + * <h4>Determine Current Creation Property List Settings in an Existing Object</h4> + * + * After a file has been created, another application may work on the file without knowing how the + * creation properties for the file were set up. Retrieving these property values is often unnecessary; + * HDF5 can read the data and knows how to deal with any properties it encounters. + * + * But sometimes an application must do something that requires knowing the creation property + * settings. HDF5 makes the acquisition of this information fairly straight-forward; for each + * property setting call, H5Pset_*, there is a corresponding H5Pget_*call to retrieve the property’s + * current setting. + * + * Consider the following examples which illustrate the determination of dataset layout and chunking settings: + * + * The application must first identify the creation property list with the appropriate get creation property + * list call. There is one such call for each kind of object. + * + * \ref H5Dget_create_plist will return a property list identifier for the creation property list that was + * used to create the dataset. Call it DCPL1_id. + * + * \ref H5Pset_layout sets a dataset’s layout to be compact, contiguous, or chunked. + * + * \ref H5Pget_layout called with DCPL1_id will return the dataset’s layout, + * either \ref H5D_COMPACT, \ref H5D_CONTIGUOUS, or \ref H5D_CHUNKED. + * + * \ref H5Pset_chunk sets the rank of a dataset, that is the number of dimensions it will have, and the + * maximum size of each dimension. + * + * \ref H5Pget_chunk, also called with DCPL1_id, will return the rank of the dataset and the maximum + * size of each dimension. + * + * If a creation property value has not been explicitly set, these H5Pget_calls will return the + * property’s default value. + * + * <h4>Determine Access Property Settings</h4> + * + * Access property settings are quite different from creation properties. Since access property + * settings are not retained in an HDF5 file or object, there is normally no knowledge of the settings + * that were used in the past. On the other hand, since access properties do not affect characteristics + * of the file or object, this is not normally an issue. For more information, see "Access and + * Creation Property Exceptions." + * + * One circumstance under which an application might need to determine access property settings + * might be when a file or object is already open but the application does not know the property list + * settings. In that case, the application can use the appropriate get access property list + * call to retrieve a property list identifier. For example, if the dataset dsetA + * from the earlier examples is still open, the following call would return an identifier for the dataset + * access property list in use: + * \code + * dsetA_dacpl_id = H5Dget_access_plist( dsetA_id ); + * \endcode + * + * The application could then use the returned property list identifier to analyze the property settings + * + * \subsection subsec_plist_generic Generic Properties Interface and User-defined Properties + * + * HDF5’s generic property interface provides tools for managing the entire property hierarchy and + * for the creation and management of user-defined property lists and properties. This interface also + * makes it possible for an application or a driver to create, modify, and manage custom properties, + * property lists, and property list classes. A comprehensive list of functions for this interface + * appears under "Generic Property Operations (Advanced)" in the "H5P: Property List Interface" + * section of the \ref RM. + * + * Further discussion of HDF5’s generic property interface and user-defined properties and + * property lists is beyond the scope of this document. + * + * \subsection subsec_plist_H5P Property List Function Summaries + * + * General property functions, generic property functions and macros, property functions that are + * used with multiple types of objects, and object and link property functions are listed below. + * + * Property list functions that apply to a specific type of object are listed in the chapter that + * discusses that object. For example, the \ref sec_dataset chapter has two property list function listings: + * one for dataset creation property list functions and one for dataset access property list functions. + * As has been stated, this chapter is not intended to describe every property list function. + * + * \ref H5P reference manual + * + * \subsection subsec_plist_resources Additional Property List Resources + * Property lists are ubiquitous in an HDF5 environment and are therefore discussed in many places + * in HDF5 documentation. The following sections and listings in the \ref UG are of + * particular interest: + * \li In the \ref sec_data_model chapter, see \ref subsubsec_data_model_abstract_plist. + * \li In the \ref sec_file chapter, see the following sections and listings: + * <ul> <li>\ref subsec_file_creation_access</li> + * <li>\ref subsec_file_property_lists</li> + * <li>\ref subsubsec_file_examples_props</li> + * <li>\ref subsubsec_file_examples_access</li> + * <li>"File creation property list functions (H5P)"</li> + * <li>"File access property list functions (H5P)"</li> + * <li>"File driver functions (H5P)"</li></ul> + * \li In the \ref sec_attribute chapter, see "Attribute creation property list functions (H5P)". + * \li In the \ref sec_group chapter, see "Group creation property list functions (H5P)". + * \li Property lists are discussed throughout \ref sec_dataset. + * + * All property list functions are described in the \ref H5P section of the + * \ref RM. The function index at the top of the page provides a categorized listing + * grouped by property list class. Those classes are listed below: + * \li File creation properties + * \li File access properties + * \li Group creation properties + * \li Dataset creation properties + * \li Dataset access properties + * \li Dataset transfer properties + * \li Link creation properties + * \li Link access properties + * \li Object creation properties + * \li Object copy properties + * + * Additional categories not related to the class structure are as follows: + * \li General property list operations + * \li Generic property list functions + * + * The general property functions can be used with any property list; the generic property functions + * constitute an advanced feature. + * + * The in-memory file image feature of HDF5 uses property lists in a manner that differs + * substantially from their use elsewhere in HDF5. Those who plan to use in-memory file images + * must study "File Image Operations" (PDF) in the Advanced Topics in HDF5collection. + * + * \subsection subsec_plist_notes Notes + * + * \anchor FileMountProps <h4>File Mount Properties</h4> + * + * While the file mount property list class \ref H5P_FILE_MOUNT is a valid HDF5 property list class, + * no file mount properties are defined by the HDF5 Library. References to a file mount property + * list should always be expressed as \ref H5P_DEFAULT, meaning the default file mount property list. + * + * <h4>Access and Creation Property Exceptions</h4> + * + * There are a small number of exceptions to the rule that creation properties are always retained in + * a file or object and access properties are never retained. + * + * The following properties are file access properties but they are not transient; they have + * permanent and different effects on a file. They could be validly classified as file creation + * properties as they must be set at creation time to properly create the file. But they are access + * properties because they must also be set when a file is reopened to properly access the file. + * <table> + * <tr><th>Property</th><th>Related function</th></tr> + * <tr valign="top"> + * <td> + * Family file driver + * </td> + * <td> + * \ref H5Pset_fapl_family + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Split file driver + * </td> + * <td> + * \ref H5Pset_fapl_split + * </td> + * </tr> + * <tr valign="top"> + * <td> + * Core file driver + * </td> + * <td> + * \ref H5Pset_fapl_core + * </td> + * </tr> + * </table> + * + * The following is a link creation property, but it is not relevant after an object has been created + * and is not retained in the file or object. + * <table> + * <tr><th>Property</th><th>Related function</th></tr> + * <tr valign="top"> + * <td> + * Create missing intermediate groups + * </td> + * <td> + * \ref H5Pset_create_intermediate_group + * </td> + * </tr> + * </table> + * + * Previous Chapter \ref sec_error - Next Chapter \ref sec_vol + * + * \defgroup H5P Property Lists (H5P) * * Use the functions in this module to manage HDF5 property lists and property * list classes. HDF5 property lists are the main vehicle to configure the @@ -61,135 +914,118 @@ * </tr> * </table> * - * \defgroup ALCAPL Attribute and Link Creation Properties - * \ingroup H5P + * \defgroup STRCPL String Creation Properties * Currently, there are only two creation properties that you can use to control * the creation of HDF5 attributes and links. The first creation property, the * choice of a character encoding, applies to both attributes and links. * The second creation property applies to links only, and advises the library * to automatically create missing intermediate groups when creating new objects. + * \ingroup H5P * - * \defgroup DAPL Dataset Access Properties + * \defgroup LCPL Link Creation Properties + * The first creation property, the choice of a character encoding, applies to + * both attributes and links. + * The second creation property applies to links only, and advises the library + * to automatically create missing intermediate groups when creating new objects. + * \ingroup STRCPL + * + * @see STRCPL + * + * \defgroup ACPL Attribute Creation Properties + * The creation property, the choice of a character encoding, applies to attributes. + * \ingroup STRCPL + * + * @see STRCPL + * + * \defgroup LAPL Link Access Properties * \ingroup H5P + * + * \defgroup DAPL Dataset Access Properties * Use dataset access properties to modify the default behavior of the HDF5 * library when accessing datasets. The properties include adjusting the size * of the chunk cache, providing prefixes for external content and virtual * dataset file paths, and controlling flush behavior, etc. These properties * are \Emph{not} persisted with datasets, and can be adjusted at runtime before * a dataset is created or opened. + * \ingroup LAPL * * \defgroup DCPL Dataset Creation Properties - * \ingroup H5P * Use dataset creation properties to control aspects of dataset creation such * as fill time, storage layout, compression methods, etc. * Unlike dataset access and transfer properties, creation properties \Emph{are} * stored with the dataset, and cannot be changed once a dataset has been * created. + * \ingroup OCPL * * \defgroup DXPL Dataset Transfer Properties - * \ingroup H5P * Use dataset transfer properties to customize certain aspects of reading * and writing datasets such as transformations, MPI-IO I/O mode, error * detection, etc. These properties are \Emph{not} persisted with datasets, * and can be adjusted at runtime before a dataset is read or written. + * \ingroup H5P * * \defgroup FAPL File Access Properties - * \ingroup H5P * Use file access properties to modify the default behavior of the HDF5 * library when accessing files. The properties include selecting a virtual * file driver (VFD), configuring the metadata cache (MDC), control * file locking, etc. These properties are \Emph{not} persisted with files, and * can be adjusted at runtime before a file is created or opened. + * \ingroup H5P * * \defgroup FCPL File Creation Properties - * \ingroup H5P * Use file creation properties to control aspects of file creation such * as setting a file space management strategy or creating a user block. * Unlike file access properties, creation properties \Emph{are} * stored with the file, and cannot be changed once a file has been * created. + * \ingroup GCPL * * \defgroup GAPL General Access Properties - * \ingroup H5P * The functions in this section can be applied to different kinds of property * lists. + * \ingroup LAPL * * \defgroup GCPL Group Creation Properties - * \ingroup H5P * Use group creation properties to control aspects of group creation such * as storage layout, compression, and link creation order tracking. * Unlike file access properties, creation properties \Emph{are} * stored with the group, and cannot be changed once a group has been * created. + * \ingroup OCPL * - * \defgroup GPLO General Property List Operations - * \ingroup H5P - * + * \defgroup PLCR Property List Class Root * Use the functions in this module to manage HDF5 property lists. - * - * <table> - * <tr><th>Create</th><th>Read</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5P_examples.c create - * </td> - * <td> - * \snippet{lineno} H5P_examples.c read - * </td> - * <tr><th>Update</th><th>Delete</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5P_examples.c update - * </td> - * <td> - * \snippet{lineno} H5P_examples.c delete - * </td> - * </tr> - * </table> - * - * \defgroup GPLOA General Property List Operations (Advanced) * \ingroup H5P * + * \defgroup PLCRA Property List Class Root (Advanced) * You can create and customize user-defined property list classes using the * functions described below. Arbitrary user-defined properties can also * be inserted into existing property lists as so-called temporary properties. - * - * <table> - * <tr><th>Create</th><th>Read</th></tr> - * - * <tr valign="top"> - * <td> - * \snippet{lineno} H5P_examples.c create_class - * </td> - * <td> - * \snippet{lineno} H5P_examples.c read_class - * </td> - * <tr><th>Update</th><th>Delete</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5P_examples.c update_class - * </td> - * <td> - * \snippet{lineno} H5P_examples.c delete_class - * </td> - * </tr> - * </table> - * - * \defgroup LAPL Link Access Properties * \ingroup H5P * * - * \defgroup MAPL Map Access Properties - * \ingroup H5P - * \defgroup OCPL Object Creation Properties * \ingroup H5P * + * \defgroup OCPYPL Object Copy Properties + * \ingroup H5P * - * \defgroup OCPPL Object Copy Properties + * \defgroup FMPL File Mount Properties + * Empty property class. * \ingroup H5P * * + * \defgroup TCPL Datatype Creation Properties + * TCPL isn't supported yet. + * \ingroup OCPL + * + * + * \defgroup TAPL Datatype Access Properties + * TAPL isn't supported yet. + * \ingroup LAPL + * + * + * */ #endif /* H5Pmodule_H */ diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 211ac71..1f4503d 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -392,7 +392,7 @@ H5_DLLVAR hid_t H5P_CLS_LINK_ACCESS_ID_g; H5_DLLVAR hid_t H5P_CLS_VOL_INITIALIZE_ID_g; H5_DLLVAR hid_t H5P_CLS_REFERENCE_ACCESS_ID_g; -/* Default roperty list IDs */ +/* Default property list IDs */ /* (Internal to library, do not use! Use macros above) */ H5_DLLVAR hid_t H5P_LST_FILE_CREATE_ID_g; H5_DLLVAR hid_t H5P_LST_FILE_ACCESS_ID_g; @@ -421,7 +421,7 @@ H5_DLLVAR hid_t H5P_LST_REFERENCE_ACCESS_ID_g; /* Generic property list routines */ /** - * \ingroup GPLO + * \ingroup PLCR * * \brief Terminates access to a property list * @@ -439,7 +439,7 @@ H5_DLLVAR hid_t H5P_LST_REFERENCE_ACCESS_ID_g; */ H5_DLL herr_t H5Pclose(hid_t plist_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Closes an existing property list class * @@ -456,7 +456,7 @@ H5_DLL herr_t H5Pclose(hid_t plist_id); */ H5_DLL herr_t H5Pclose_class(hid_t plist_id); /** - * \ingroup GPLO + * \ingroup PLCR * * \brief Copies an existing property list to create a new property list * @@ -473,7 +473,7 @@ H5_DLL herr_t H5Pclose_class(hid_t plist_id); */ H5_DLL hid_t H5Pcopy(hid_t plist_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Copies a property from one list or class to another * @@ -509,7 +509,7 @@ H5_DLL hid_t H5Pcopy(hid_t plist_id); */ H5_DLL herr_t H5Pcopy_prop(hid_t dst_id, hid_t src_id, const char *name); /** - * \ingroup GPLO + * \ingroup PLCR * * \brief Creates a new property list as an instance of a property list class * @@ -633,7 +633,7 @@ H5_DLL herr_t H5Pcopy_prop(hid_t dst_id, hid_t src_id, const char *name); */ H5_DLL hid_t H5Pcreate(hid_t cls_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Creates a new property list class * @@ -676,7 +676,7 @@ H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, H5P_cls_create_func H5P_cls_copy_func_t copy, void *copy_data, H5P_cls_close_func_t close, void *close_data); /** - * \ingroup GPLO + * \ingroup PLCR * * \brief Decodes property list received in a binary object buffer and * returns a new property list identifier @@ -705,7 +705,7 @@ H5_DLL hid_t H5Pcreate_class(hid_t parent, const char *name, H5P_cls_create_func */ H5_DLL hid_t H5Pdecode(const void *buf); /** - * \ingroup GPLO + * \ingroup PLCR * * \brief Encodes the property values in a property list into a binary * buffer @@ -759,7 +759,7 @@ H5_DLL hid_t H5Pdecode(const void *buf); */ H5_DLL herr_t H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Compares two property lists or classes for equality * @@ -779,7 +779,7 @@ H5_DLL herr_t H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_i */ H5_DLL htri_t H5Pequal(hid_t id1, hid_t id2); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Queries whether a property name exists in a property list or * class @@ -797,7 +797,7 @@ H5_DLL htri_t H5Pequal(hid_t id1, hid_t id2); */ H5_DLL htri_t H5Pexist(hid_t plist_id, const char *name); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Queries the value of a property * @@ -829,7 +829,7 @@ H5_DLL htri_t H5Pexist(hid_t plist_id, const char *name); */ H5_DLL herr_t H5Pget(hid_t plist_id, const char *name, void *value); /** - *\ingroup GPLO + *\ingroup PLCR * * \brief Returns the property list class identifier for a property list * @@ -892,7 +892,7 @@ H5_DLL herr_t H5Pget(hid_t plist_id, const char *name, void *value); */ H5_DLL hid_t H5Pget_class(hid_t plist_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Retrieves the name of a class * @@ -1036,7 +1036,7 @@ H5_DLL hid_t H5Pget_class(hid_t plist_id); */ H5_DLL char *H5Pget_class_name(hid_t pclass_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Retrieves the parent class of a property class * @@ -1052,7 +1052,7 @@ H5_DLL char *H5Pget_class_name(hid_t pclass_id); */ H5_DLL hid_t H5Pget_class_parent(hid_t pclass_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Queries the number of properties in a property list or class * @@ -1075,7 +1075,7 @@ H5_DLL hid_t H5Pget_class_parent(hid_t pclass_id); */ H5_DLL herr_t H5Pget_nprops(hid_t id, size_t *nprops); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Queries the size of a property value in bytes * @@ -1096,7 +1096,7 @@ H5_DLL herr_t H5Pget_nprops(hid_t id, size_t *nprops); */ H5_DLL herr_t H5Pget_size(hid_t id, const char *name, size_t *size); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Registers a temporary property with a property list * @@ -1346,7 +1346,7 @@ H5_DLL herr_t H5Pinsert2(hid_t plist_id, const char *name, size_t size, void *va H5P_prp_get_func_t get, H5P_prp_delete_func_t prp_del, H5P_prp_copy_func_t copy, H5P_prp_compare_func_t compare, H5P_prp_close_func_t close); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Determines whether a property list is a member of a class * @@ -1366,7 +1366,7 @@ H5_DLL herr_t H5Pinsert2(hid_t plist_id, const char *name, size_t size, void *va */ H5_DLL htri_t H5Pisa_class(hid_t plist_id, hid_t pclass_id); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Iterates over properties in a property class or list * @@ -1412,7 +1412,7 @@ H5_DLL htri_t H5Pisa_class(hid_t plist_id, hid_t pclass_id); */ H5_DLL int H5Piterate(hid_t id, int *idx, H5P_iterate_t iter_func, void *iter_data); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Registers a permanent property with a property list class * @@ -1693,7 +1693,7 @@ H5_DLL herr_t H5Pregister2(hid_t cls_id, const char *name, size_t size, void *de H5P_prp_delete_func_t prp_del, H5P_prp_copy_func_t copy, H5P_prp_compare_func_t compare, H5P_prp_close_func_t close); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Removes a property from a property list * @@ -1719,7 +1719,7 @@ H5_DLL herr_t H5Pregister2(hid_t cls_id, const char *name, size_t size, void *de */ H5_DLL herr_t H5Premove(hid_t plist_id, const char *name); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Sets a property list value * @@ -1751,7 +1751,7 @@ H5_DLL herr_t H5Premove(hid_t plist_id, const char *name); */ H5_DLL herr_t H5Pset(hid_t plist_id, const char *name, const void *value); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Removes a property from a property list class * @@ -1770,8 +1770,6 @@ H5_DLL herr_t H5Pset(hid_t plist_id, const char *name, const void *value); */ H5_DLL herr_t H5Punregister(hid_t pclass_id, const char *name); -/* Object creation property list (OCPL) routines */ - /** * \ingroup DCPL * @@ -1791,6 +1789,9 @@ H5_DLL herr_t H5Punregister(hid_t pclass_id, const char *name); * */ H5_DLL htri_t H5Pall_filters_avail(hid_t plist_id); + +/* Object creation property list (OCPL) routines */ + /** * \ingroup OCPL * @@ -8055,7 +8056,7 @@ H5_DLL herr_t H5Pget_mpio_no_collective_cause(hid_t plist_id, uint32_t *local_no /* Link creation property list (LCPL) routines */ /** - * \ingroup ALCAPL + * \ingroup STRCPL * * \brief Determines whether property is set to enable creating missing * intermediate groups @@ -8086,7 +8087,7 @@ H5_DLL herr_t H5Pget_mpio_no_collective_cause(hid_t plist_id, uint32_t *local_no */ H5_DLL herr_t H5Pget_create_intermediate_group(hid_t plist_id, unsigned *crt_intmd /*out*/); /** - * \ingroup ALCAPL + * \ingroup STRCPL * * \brief Specifies in property list whether to create missing * intermediate groups @@ -8470,7 +8471,7 @@ H5_DLL herr_t H5Pget_map_iterate_hints(hid_t mapl_id, size_t *key_prefetch_size /* String creation property list (STRCPL) routines */ /** - * \ingroup ALCAPL + * \ingroup STRCPL * * \brief Retrieves the character encoding used to create a link or * attribute name @@ -8499,7 +8500,7 @@ H5_DLL herr_t H5Pget_map_iterate_hints(hid_t mapl_id, size_t *key_prefetch_size */ H5_DLL herr_t H5Pget_char_encoding(hid_t plist_id, H5T_cset_t *encoding /*out*/); /** - * \ingroup ALCAPL + * \ingroup STRCPL * * \brief Sets the character encoding used to encode link and attribute * names @@ -8540,7 +8541,6 @@ H5_DLL herr_t H5Pget_char_encoding(hid_t plist_id, H5T_cset_t *encoding /*out*/) */ H5_DLL herr_t H5Pset_char_encoding(hid_t plist_id, H5T_cset_t encoding); -/* Link access property list (LAPL) routines */ /** * \ingroup LAPL * @@ -8899,7 +8899,7 @@ H5_DLL herr_t H5Pset_nlinks(hid_t plist_id, size_t nlinks); /* Object copy property list (OCPYPL) routines */ /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Adds a path to the list of paths that will be searched in the * destination file for a matching committed datatype @@ -9014,7 +9014,7 @@ H5_DLL herr_t H5Pset_nlinks(hid_t plist_id, size_t nlinks); */ H5_DLL herr_t H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path); /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Clears the list of paths stored in the object copy property list * @@ -9065,7 +9065,7 @@ H5_DLL herr_t H5Padd_merge_committed_dtype_path(hid_t plist_id, const char *path */ H5_DLL herr_t H5Pfree_merge_committed_dtype_paths(hid_t plist_id); /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Retrieves the properties to be used when an object is copied * @@ -9090,7 +9090,7 @@ H5_DLL herr_t H5Pfree_merge_committed_dtype_paths(hid_t plist_id); */ H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *copy_options /*out*/); /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Retrieves the callback function from the specified object copy * property list @@ -9128,7 +9128,7 @@ H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *copy_options /*out*/) */ H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, void **op_data); /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Sets properties to be used when an object is copied * @@ -9221,7 +9221,7 @@ H5_DLL herr_t H5Pget_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t *func, */ H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned copy_options); /** - * \ingroup OCPPL + * \ingroup OCPYPL * * \brief Sets the callback function that H5Ocopy() will invoke before * searching the entire destination file for a matching committed @@ -9319,7 +9319,7 @@ H5_DLL herr_t H5Pset_mcdt_search_cb(hid_t plist_id, H5O_mcdt_search_cb_t func, v /* Typedefs */ /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Registers a permanent property with a property list class * @@ -9449,7 +9449,7 @@ H5_DLL herr_t H5Pregister1(hid_t cls_id, const char *name, size_t size, void *de H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_del, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close); /** - * \ingroup GPLOA + * \ingroup PLCRA * * \brief Registers a temporary property with a property list * @@ -9561,7 +9561,7 @@ H5_DLL herr_t H5Pinsert1(hid_t plist_id, const char *name, size_t size, void *va H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close); /** - * \ingroup GPLO + * \ingroup PLCRA * * \brief Encodes the property values in a property list into a binary * buffer diff --git a/src/H5Rmodule.h b/src/H5Rmodule.h index fe28bb2..c561058 100644 --- a/src/H5Rmodule.h +++ b/src/H5Rmodule.h @@ -26,33 +26,12 @@ #define H5_MY_PKG_INIT YES /** - * \defgroup H5R H5R + * \defgroup H5R References (H5R) * * Use the functions in this module to manage HDF5 references. Referents can * be HDF5 objects, attributes, and selections on datasets a.k.a. dataset * regions. * - * - * <table> - * <tr><th>Create</th><th>Read</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5R_examples.c create - * </td> - * <td> - * \snippet{lineno} H5R_examples.c read - * </td> - * <tr><th>Update</th><th>Delete</th></tr> - * <tr valign="top"> - * <td> - * \snippet{lineno} H5R_examples.c update - * </td> - * <td> - * \snippet{lineno} H5R_examples.c delete - * </td> - * </tr> - * </table> - * */ #endif /* H5Rmodule_H */ diff --git a/src/H5Smodule.h b/src/H5Smodule.h index 010f4a6..9c6682e 100644 --- a/src/H5Smodule.h +++ b/src/H5Smodule.h @@ -29,7 +29,1494 @@ #define H5_MY_PKG_ERR H5E_DATASPACE #define H5_MY_PKG_INIT YES -/**\defgroup H5S H5S +/** \page H5S_UG Dataspaces and Partial I/O + * + * + * \section sec_dataspace HDF5 Dataspaces and Partial I/O + * + * HDF5 dataspaces describe the \Emph{shape} of datasets in memory or in HDF5 + * files. Dataspaces can be empty (#H5S_NULL), a singleton (#H5S_SCALAR), or + * a multi-dimensional, regular grid (#H5S_SIMPLE). Dataspaces can be re-shaped. + * + * Subsets of dataspaces can be "book-marked" or used to restrict I/O operations + * using \Emph{selections}. Furthermore, certain set operations are supported + * for selections. + * + * \subsection subsec_dataspace_intro Introduction + * + * The HDF5 \Emph{dataspace} is a required component of an HDF5 dataset or attribute definition. The dataspace + * defines the size and shape of the dataset or attribute raw data. In other words, a dataspace defines the + * number of dimensions and the size of each dimension of the multidimensional array in which the raw data + * is represented. The dataspace must be defined when the dataset or attribute is created. + * + * The \Emph{dataspace} is also used during dataset I/O operations, defining the elements of the dataset that + * participate in the I/O operation. + * + * This chapter explains the \Emph{dataspace} object and its use in dataset and attribute creation and data + * transfer. It also describes selection operations on a dataspace used to implement sub‐setting, + * sub‐sampling, and scatter‐gather access to datasets. + * + * \subsection subsec_dataspace_function Dataspace Function Summaries + * @see H5S reference manual provides a reference list of dataspace functions, the H5S APIs. + * + * \subsection subsec_dataspace_program Definition of Dataspace Objects and the Dataspace Programming Model + * + * This section introduces the notion of the HDF5 dataspace object and a programming model for creating + * and working with dataspaces. + * + * \subsubsection subsubsec_dataspace_program_object Dataspace Objects + * + * An HDF5 dataspace is a required component of an HDF5 dataset or attribute. A dataspace defines the size + * and the shape of a dataset’s or an attribute’s raw data. Currently, HDF5 supports the following types of + * the dataspaces: + * \li Scalar dataspaces + * \li Simple dataspaces + * \li Null dataspaces + * + * A scalar dataspace, #H5S_SCALAR, represents just one element, a scalar. Note that the datatype of this one + * element may be very complex; example would be a compound structure with members being of any + * allowed HDF5 datatype, including multidimensional arrays, strings, and nested compound structures. By + * convention, the rank of a scalar dataspace is always 0 (zero); think of it geometrically as a single, + * dimensionless point, though that point may be complex. + * + * A simple dataspace, #H5S_SIMPLE , is a multidimensional array of elements. The dimensionality of the + * dataspace (or the rank of the array) is fixed and is defined at creation time. The size of each dimension + * can grow during the life time of the dataspace from the current size up to the maximum size. Both the + * current size and the maximum size are specified at creation time. The sizes of dimensions at any particular + * time in the life of a dataspace are called the current dimensions, or the dataspace extent. They can be + * queried along with the maximum sizes. + * + * A null dataspace, #H5S_NULL, contains no data elements. Note that no selections can be applied to a null + * dataset as there is nothing to select. + * + * As shown in the UML diagram in the figure below, an HDF5 simple dataspace object has three attributes: + * the rank or number of dimensions; the current sizes, expressed as an array of length rank with each element + * of the array denoting the current size of the corresponding dimension; and the maximum sizes, + * expressed as an array of length rank with each element of the array denoting the maximum size of the + * corresponding dimension. + * + * <table> + * <tr> + * <td> + * \image html Dspace_simple.gif "A simple dataspace" + * </td> + * </tr> + * </table> + * + * \em Note: A simple dataspace is defined by its rank, the current size of each dimension, and the maximum + * size of each dimension. + * + * The size of a current dimension cannot be greater than the maximum size, which can be unlimited, specified + * as #H5S_UNLIMITED. Note that while the HDF5 file format and library impose no maximum size on an + * unlimited dimension, practically speaking its size will always be limited to the biggest integer available + * on the particular system being used. + * + * Dataspace rank is restricted to 32, the standard limit in C on the rank of an array, in the current + * implementation of the HDF5 Library. The HDF5 file format, on the other hand, allows any rank up to the + * maximum integer value on the system, so the library restriction can be raised in the future if higher + * dimensionality is required. + * + * Note that most of the time Fortran applications calling HDF5 will work with dataspaces of rank less than + * or equal to seven, since seven is the maximum number of dimensions in a Fortran array. But dataspace rank + * is not limited to seven for Fortran applications. + * + * The current dimensions of a dataspace, also referred to as the dataspace extent, define the bounding box + * for dataset elements that can participate in I/O operations. + * + * \subsubsection subsubsec_dataspace_program_model Dataspace Programming Model + * + * The programming model for creating and working with HDF5 dataspaces can be summarized as follows: + * \li 1. Create a dataspace + * \li 2. Use the dataspace to create a dataset in the file or to describe a data array in memory + * \li 3. Modify the dataspace to define dataset elements that will participate in I/O operations + * \li 4. Use the modified dataspace while reading/writing dataset raw data or to create a region reference + * \li 5. Close the dataspace when no longer needed + * + * The rest of this section will address steps 1, 2, and 5 of the programming model; steps 3 and 4 will be + * discussed in later sections of this chapter. + * + * <h4>Creating a Dataspace</h4> + * + * A dataspace can be created by calling the \ref H5Screate function. Since the + * definition of a simple dataspace requires the specification of dimensionality (or rank) and initial and + * maximum dimension sizes, the HDF5 Library provides a convenience API, \ref H5Screate_simple to create a + * simple dataspace in one step. + * + * The following examples illustrate the usage of these APIs. + * + * <h4>Creating a Scalar Dataspace</h4> + * + * Creating a Scalar Dataspace + * \code + * hid_t space_id; + * . . . + * space_id = H5Screate(H5S_SCALAR); + * \endcode + * As mentioned above, the dataspace will contain only one element. Scalar dataspaces are used more often + * for describing attributes that have just one value. For example, the attribute temperature with the value + * Celsius is used to indicate that the dataset with this attribute stores temperature values using the + * Celsius scale. + * + * <h4>Creating a Null Dataspace</h4> + * + * A null dataspace is created with the \ref H5Screate function. + * \code + * hid_t space_id; + * . . . + * space_id = H5Screate(H5S_NULL); + * \endcode + * As mentioned above, the dataspace will contain no elements. + * + * <h4>Creating a Simple Dataspace</h4> + * + * Let’s assume that an application wants to store a two‐dimensional array of data, A(20,100). During the + * life of the application, the first dimension of the array can grow up to 30; there is no restriction on + * the size of the second dimension. The following steps are used to declare a dataspace for the dataset + * in which the array data will be stored. + * \code + * hid_t space_id; + * int rank = 2; + * hsize_t current_dims[2] = {20, 100}; + * hsize_t max_dims[2] = {30, H5S_UNLIMITED}; + * . . . + * space_id = H5Screate(H5S_NULL); + * H5Sset_extent_simple(space_id, rank, current_dims, max_dims); + * \endcode + * + * Alternatively, the convenience APIs H5Screate_simple/h5screate_simple_f can replace the + * H5Screate/h5screate_f and H5Sset_extent_simple/h5sset_extent_simple_f calls. + * \code + * space_id = H5Screate_simple(rank, current_dims, max_dims); + * \endcode + * + * In this example, a dataspace with current dimensions of 20 by 100 is created. The first dimension can be + * extended only up to 30. The second dimension, however, is declared unlimited; it can be extended up to + * the largest available integer value on the system. + * + * Note that when there is a difference between the current dimensions and the maximum dimensions of an + * array, then chunking storage must be used. In other words, if the number of dimensions may change over + * the life of the dataset, then chunking must be used. If the array dimensions are fixed (if the number of + * current dimensions is equal to the maximum number of dimensions when the dataset is created), then + * contiguous storage can be used. For more information, see "Data Transfer". + * + * Maximum dimensions can be the same as current dimensions. In such a case, the sizes of dimensions + * cannot be changed during the life of the dataspace object. In C, \c NULL can be used to indicate to the + * \ref H5Screate_simple and \ref H5Sset_extent_simple functions that the maximum sizes of all dimensions + * are the same as the current sizes. + * \code + * space_id = H5Screate_simple(rank, current_dims, NULL); + * \endcode + * The created dataspace will have current and maximum dimensions of 20 and 100 correspondingly, and the + * sizes of those dimensions cannot be changed. + * + * <h4>C versus Fortran Dataspaces</h4> + * + * Dataspace dimensions are numbered from 1 to rank. HDF5 uses C storage conventions, assuming that the + * last listed dimension is the fastest‐changing dimension and the first‐listed dimension is the slowest + * changing. The HDF5 file format storage layout specification adheres to the C convention and the HDF5 + * Library adheres to the same convention when storing dataspace dimensions in the file. This affects how + * C programs and tools interpret data written from Fortran programs and vice versa. The example below + * illustrates the issue. + * + * When a Fortran application describes a dataspace to store an array as A(20,100), it specifies the value of + * the first dimension to be 20 and the second to be 100. Since Fortran stores data by columns, the + * first‐listed dimension with the value 20 is the fastest‐changing dimension and the last‐listed dimension + * with the value 100 is the slowest‐changing. In order to adhere to the HDF5 storage convention, the HDF5 + * Fortran wrapper transposes dimensions, so the first dimension becomes the last. The dataspace dimensions + * stored in the file will be 100,20 instead of 20,100 in order to correctly describe the Fortran data that + * is stored in 100 columns, each containing 20 elements. + * + * When a Fortran application reads the data back, the HDF5 Fortran wrapper transposes the dimensions + * once more, returning the first dimension to be 20 and the second to be 100, describing correctly the sizes + * of the array that should be used to read data in the Fortran array A(20,100). + * + * When a C application reads data back, the dimensions will come out as 100 and 20, correctly describing + * the size of the array to read data into, since the data was written as 100 records of 20 elements each. + * Therefore C tools such as h5dump and h5ls always display transposed dimensions and values for the data + * written by a Fortran application. + * + * Consider the following simple example of equivalent C 3 x 5 and Fortran 5 x 3 arrays. As illustrated in + * the figure below, a C application will store a 3 x 5 2‐dimensional array as three 5‐element rows. In order + * to store the same data in the same order, a Fortran application must view the array as a 5 x 3 array with + * three 5‐element columns. The dataspace of this dataset, as written from Fortran, will therefore be + * described as 5 x 3 in the application but stored and described in the file according to the C convention + * as a 3 x 5 array. This ensures that C and Fortran applications will always read the data in the order in + * which it was written. The HDF5 Fortran interface handles this transposition automatically. + * \code + * // C + * \#define NX 3 // dataset dimensions + * \#define NY 5 + * . . . + * int data[NX][NY]; // data to write + * . . . + * // Data and output buffer initialization. + * for (j = 0; j < NX; j++) + * for (i = 0; i < NY; i++) + * data[j][i] = i + j; + * // + * // 1 2 3 4 5 + * // 6 7 8 9 10 + * // 11 12 13 14 15 + * // + * . . . + * dims[0] = NX; + * dims[1] = NY; + * dataspace = H5Screate_simple(RANK, dims, NULL); + * \endcode + * + * \code + * ! Fortran + * INTEGER, PARAMETER :: NX = 3 + * INTEGER, PARAMETER :: NX = 5 + * . . . + * INTEGER(HSIZE_T), DIMENSION(2) :: dims = (/NY, NX/) ! Dataset dimensions + * . . . + * ! + * ! Initialize data + * ! + * do i = 1, NY + * do j = 1, NX + * data(i,j) = i + (j-1)*NY + * enddo + * enddo + * ! + * ! Data + * ! + * ! 1 6 11 + * ! 2 7 12 + * ! 3 8 13 + * ! 4 9 14 + * ! 5 10 15 + * . . . + * CALL h5screate_simple_f(rank, dims, dspace_id, error) + * \endcode + * + * <table> + * <caption align=top>Comparing C and Fortran dataspaces</caption> + * <tr> + * <td> + * A dataset stored by a C program in a 3 x 5 array: + * </td> + * </tr> + * <tr> + * <td> + * \image html Dspace_CvsF1.gif + * </td> + * </tr> + * <tr> + * <td> + * The same dataset stored by a Fortran program in a 5 x 3 array: + * </td> + * </tr> + * <tr> + * <td> + * \image html Dspace_CvsF2.gif + * </td> + * </tr> + * <tr> + * <td> + * The first dataset above as written to an HDF5 file from C or the second dataset above as written + * from Fortran: + * </td> + * </tr> + * <tr> + * <td> + * \image html Dspace_CvsF3.gif + * </td> + * </tr> + * <tr> + * <td> + * The first dataset above as written to an HDF5 file from Fortran: + * </td> + * </tr> + * <tr> + * <td> + * \image html Dspace_CvsF4.gif + * </td> + * </tr> + * </table> + * + * <em>Note: The HDF5 Library stores arrays along the fastest‐changing dimension. This approach is often + * referred to as being “in C order.” C, C++, and Java work with arrays in row‐major order. In other words, + * the row, or the last dimension, is the fastest‐changing dimension. Fortran, on the other hand, handles + * arrays in column‐major order making the column, or the first dimension, the fastest‐changing dimension. + * Therefore, the C and Fortran arrays illustrated in the top portion of this figure are stored identically + * in an HDF5 file. This ensures that data written by any language can be meaningfully read, interpreted, + * and manipulated by any other.</em> + * + * <h4>Finding Dataspace Characteristics</h4> + * + * The HDF5 Library provides several APIs designed to query the characteristics of a dataspace. + * + * The function \ref H5Sis_simple returns information about the type of a dataspace. + * This function is rarely used and currently supports only simple and scalar dataspaces. + * + * To find out the dimensionality, or rank, of a dataspace, use \ref H5Sget_simple_extent_ndims. + * \ref H5Sget_simple_extent_dims can also be used to find out the rank. See + * the example below. If both functions return 0 for the value of rank, then the dataspace is scalar. + * + * To query the sizes of the current and maximum dimensions, use \ref H5Sget_simple_extent_dims. + * + * The following example illustrates querying the rank and dimensions of a dataspace using these functions. + * \code + * hid_t space_id; + * int rank; + * hsize_t *current_dims; + * hsize_t *max_dims; + * . . . + * rank = H5Sget_simple_extent_ndims(space_id); + * // (or rank = H5Sget_simple_extent_dims(space_id, NULL, NULL);) + * current_dims = (hsize_t)malloc(rank * sizeof(hsize_t)); + * max_dims = (hsize_t)malloc(rank * sizeof(hsize_t)); + * H5Sget_simple_extent_dims(space_id, current_dims, max_dims); + * // Print values here + * \endcode + * + * \subsection subsec_dataspace_transfer Dataspaces and Data Transfer + * + * Read and write operations transfer data between an HDF5 file on disk and in memory. The shape that the + * array data takes in the file and in memory may be the same, but HDF5 also allows users the ability to + * represent data in memory in a different shape than in the file. If the shape of an array in the file and + * in memory will be the same, then the same dataspace definition can be used for both. If the shape of an + * array in memory needs to be different than the shape in the file, then the dataspace definition for the + * shape of the array in memory can be changed. During a read operation, the array will be read into the + * different shape in memory, and during a write operation, the array will be written to the file in the + * shape specified by the dataspace in the file. The only qualification is that the number of elements read + * or written must be the same in both the source and the destination dataspaces. + * + * Item a in the figure below shows a simple example of a read operation in which the data is stored as a 3 + * by 4 array in the file (item b) on disk, but the program wants it to be a 4 by 3 array in memory. This is + * accomplished by setting the memory dataspace to describe the desired memory layout, as in item c. The read + * operation reads the data in the file array into the memory array. + * + * <table> + * <tr> + * <td> + * \image html Dspace_read.gif "Data layout before and after a read operation" + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Dspace_move.gif "Moving data from disk to memory" + * </td> + * </tr> + * </table> + + * Both the source and destination are stored as contiguous blocks of storage with the elements in the order + * specified by the dataspace. The figure above shows one way the elements might be organized. In item a, + * the elements are stored as 3 blocks of 4 elements. The destination is an array of 12 elements in memory + * (see item c). As the figure suggests, the transfer reads the disk blocks into a memory buffer (see item b), + * and then writes the elements to the correct locations in memory. A similar process occurs in reverse when + * data is written to disk. + * + * \subsubsection subsubsec_dataspace_transfer_select Data Selection + * + * In addition to rearranging data, the transfer may select the data elements from the source and destination. + * + * Data selection is implemented by creating a dataspace object that describes the selected elements (within + * the hyper rectangle) rather than the whole array. Two dataspace objects with selections can be used in + * data transfers to read selected elements from the source and write selected elements to the destination. + * When data is transferred using the dataspace object, only the selected elements will be transferred. + * + * This can be used to implement partial I/O, including: + * \li Sub‐setting ‐ reading part of a large dataset + * \li Sampling ‐ reading selected elements (for example, every second element) of a dataset + * \li Scatter‐gather ‐ read non‐contiguous elements into contiguous locations (gather) or read contiguous + * elements into non‐contiguous locations (scatter) or both + * + * To use selections, the following steps are followed: + * \li 1. Get or define the dataspace for the source and destination + * \li 2. Specify one or more selections for source and destination dataspaces + * \li 3. Transfer data using the dataspaces with selections + * + * A selection is created by applying one or more selections to a dataspace. A selection may override any + * other selections (#H5S_SELECT_SET) or may be “Ored” with previous selections on the same dataspace + * (#H5S_SELECT_OR). In the latter case, the resulting selection is the union of the selection and all + * previously selected selections. Arbitrary sets of points from a dataspace can be selected by specifying + * an appropriate set of selections. + * + * Two selections are used in data transfer, so the source and destination must be compatible, as described + * below. + * + * There are two forms of selection, hyperslab and point. A selection must be either a point selection or a + * set of hyperslab selections. Selections cannot be mixed. + * + * The definition of a selection within a dataspace, not the data in the selection, cannot be saved to the + * file unless the selection definition is saved as a region reference. For more information, + * see \ref subsec_dataspace_refer. + * + * <h4>Hyperslab Selection</h4> + * + * A hyperslab is a selection of elements from a hyper rectangle. An HDF5 hyperslab is a rectangular pattern + * defined by four arrays. The four arrays are summarized in the table below. + * + * The offset defines the origin of the hyperslab in the original dataspace. + * + * The stride is the number of elements to increment between selected elements. A stride of ‘1’ is every + * element, a stride of ‘2’ is every second element, etc. Note that there may be a different stride for + * each dimen‐sion of the dataspace. The default stride is 1. + * + * The count is the number of elements in the hyperslab selection. When the stride is 1, the selection is a + * hyper rectangle with a corner at the offset and size count[0] by count[1] by.... When stride is greater + * than one, the hyperslab bounded by the offset and the corners defined by stride[n] * count[n]. + * + * <table> + * <caption align=top>Hyperslab elements</caption> + * <tr> + * <th> + * Parameter + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * Offset + * </td> + * <td> + * The starting location for the hyperslab. + * </td> + * </tr> + * <tr> + * <td> + * Stride + * </td> + * <td> + * The number of elements to separate each element or block to be selected. + * </td> + * </tr> + * <tr> + * <td> + * Count + * </td> + * <td> + * The number of elements or blocks to select along each dimension. + * </td> + * </tr> + * <tr> + * <td> + * Block + * </td> + * <td> + * The size of the block selected from the dataspace. + * </td> + * </tr> + * </table> + * + * The block is a count on the number of repetitions of the hyperslab. The default block size is '1', which is + * one hyperslab. A block of 2 would be two hyperslabs in that dimension, with the second starting at + * offset[n] + (count[n] * stride[n]) + 1. + * + * A hyperslab can be used to access a sub‐set of a large dataset. The figure below shows an example of a + * hyperslab that reads a rectangle from the middle of a larger two dimensional array. The destination is the + * same shape as the source. + * + * <table> + * <tr> + * <td> + * \image html Dspace_subset.gif "Access a sub‐set of data with a hyperslab" + * </td> + * </tr> + * </table> + * + * Hyperslabs can be combined to select complex regions of the source and destination. The figure below + * shows an example of a transfer from one non‐rectangular region into another non‐rectangular region. The + * source is defined as the union of two hyperslabs, and the destination is the union of three hyperslabs. + * + * <table> + * <tr> + * <td> + * \image html Dspace_complex.gif "Build complex regions with hyperslab unions" + * </td> + * </tr> + * </table> + * + * Hyperslabs may also be used to collect or scatter data from regular patterns. The figure below shows an + * example where the source is a repeating pattern of blocks, and the destination is a single, one dimensional + * array. + * + * <table> + * <tr> + * <td> + * \image html Dspace_combine.gif "Use hyperslabs to combine or disperse data" + * </td> + * </tr> + * </table> + * + * <h4>Select Points</h4> + * + * The second type of selection is an array of points such as coordinates. Essentially, this selection is a + * list of all the points to include. The figure below shows an example of a transfer of seven elements from + * a two dimensional dataspace to a three dimensional dataspace using a point selection to specify the points. + * + * <table> + * <tr> + * <td> + * \image html Dspace_point.gif "Point selection" + * </td> + * </tr> + * </table> + * + * <h4>Rules for Defining Selections</h4> + * + * A selection must have the same number of dimensions (rank) as the dataspace it is applied to, although it + * may select from only a small region such as a plane from a 3D dataspace. Selections do not affect the + * extent of the dataspace, the selection may be larger than the dataspace. The boundaries of selections are + * reconciled with the extent at the time of the data transfer. + * + * <h4>Data Transfer with Selections</h4> + * + * A data transfer (read or write) with selections is the same as any read or write, except the source + * and destination dataspace have compatible selections. + * + * During the data transfer, the following steps are executed by the library: + * \li The source and destination dataspaces are checked to assure that the selections are compatible. + * <ul><li>Each selection must be within the current extent of the dataspace. A selection may be + * defined to extend outside the current extent of the dataspace, but the dataspace cannot be + * accessed if the selection is not valid at the time of the access.</li> + * <li> The total number of points selected in the source and destination must be the same. Note + * that the dimensionality of the source and destination can be different (for example, the + * source could be 2D, the destination 1D or 3D), and the shape can be different, but the number of + * elements selected must be the same.</li></ul> + * \li The data is transferred, element by element. + * + * Selections have an iteration order for the points selected, which can be any permutation of the dimensions + * involved (defaulting to 'C' array order) or a specific order for the selected points, for selections + * composed of single array elements with \ref H5Sselect_elements. + * + * The elements of the selections are transferred in row‐major, or C order. That is, it is assumed that the + * first dimension varies slowest, the second next slowest, and so forth. For hyperslab selections, the order + * can be any permutation of the dimensions involved (defaulting to ‘C’ array order). When multiple hyperslabs + * are combined, the hyperslabs are coalesced into contiguous reads and writes. + * + * In the case of point selections, the points are read and written in the order specified. + * + * \subsubsection subsubsec_dataspace_transfer_model Programming Model + * + * <h4>Selecting Hyperslabs</h4> + * + * Suppose we want to read a 3x4 hyperslab from a dataset in a file beginning at the element <1,2> in the + * dataset, and read it into a 7 x 7 x 3 array in memory. See the figure below. In order to do this, we must + * create a dataspace that describes the overall rank and dimensions of the dataset in the file as well as + * the position and size of the hyperslab that we are extracting from that dataset. + * + * <table> + * <tr> + * <td> + * \image html Dspace_select.gif "Selecting a hyperslab" + * </td> + * </tr> + * </table> + * + * The code in the first example below illustrates the selection of the hyperslab in the file dataspace. + * The second example below shows the definition of the destination dataspace in memory. Since the in‐memory + * dataspace has three dimensions, the hyperslab is an array with three dimensions with the last dimension + * being 1: <3,4,1>. The third example below shows the read using the source and destination dataspaces + * with selections. + * + * <em>Selecting a hyperslab</em> + * \code + * //get the file dataspace. + * dataspace = H5Dget_space(dataset); // dataspace identifier + * + * // Define hyperslab in the dataset. + * offset[0] = 1; + * offset[1] = 2; + * count[0] = 3; + * count[1] = 4; + * status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, count, NULL); + * \endcode + * + * <em>Defining the destination memory</em> + * \code + * // Define memory dataspace. + * dimsm[0] = 7; + * dimsm[1] = 7; + * dimsm[2] = 3; + * memspace = H5Screate_simple(3,dimsm,NULL); + * + * // Define memory hyperslab. + * offset_out[0] = 3; + * offset_out[1] = 0; + * offset_out[2] = 0; + * count_out[0] = 3; + * count_out[1] = 4; + * count_out[2] = 1; + * status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, count_out, NULL); + * \endcode + * + * <em>A sample read specifying source and destination dataspaces</em> + * \code + * ret = H5Dread(dataset, H5T_NATIVE_INT, memspace,dataspace, H5P_DEFAULT, data); + * \endcode + * + * <h4>Example with Strides and Blocks</h4> + * + * Consider an 8 x 12 dataspace into which we want to write eight 3 x 2 blocks in a two dimensional array + * from a source dataspace in memory that is a 50‐element one dimensional array. See the figure below. + * + * <table> + * <tr> + * <td> + * \image html Dspace_write1to2.gif "Write from a one dimensional array to a two dimensional array" + * </td> + * </tr> + * </table> + * + * The example below shows code to write 48 elements from the one dimensional array to the file dataset + * starting with the second element in vector. The destination hyperslab has the following parameters: + * offset=(0,1), stride=(4,3), count=(2,4), block=(3,2). The source has the parameters: offset=(1), + * stride=(1), count=(48), block=(1). After these operations, the file dataspace will have the values + * shown in item b in the figure above. Notice that the values are inserted in the file dataset in + * row‐major order. + * + * <em>Write from a one dimensional array to a two dimensional array</em> + * \code + * // Select hyperslab for the dataset in the file, using 3 x 2 blocks, (4,3) stride (2,4) + * // count starting at the position (0,1). + * offset[0] = 0; offset[1] = 1; + * stride[0] = 4; stride[1] = 3; + * count[0] = 2; count[1] = 4; + * block[0] = 3; block[1] = 2; + * ret = H5Sselect_hyperslab(fid, H5S_SELECT_SET, offset, stride, count, block); + * + * // Create dataspace for the first dataset. + * mid1 = H5Screate_simple(MSPACE1_RANK, dim1, NULL); + * + * // Select hyperslab. + * // We will use 48 elements of the vector buffer starting + * // at the second element. Selected elements are + * // 1 2 3 . . . 48 + * offset[0] = 1; + * stride[0] = 1; + * count[0] = 48; + * block[0] = 1; + * ret = H5Sselect_hyperslab(mid1, H5S_SELECT_SET, offset, stride, count, block); + * + * // Write selection from the vector buffer to the dataset in the file. + * ret = H5Dwrite(dataset, H5T_NATIVE_INT, midd1, fid, H5P_DEFAULT, vector) + * \endcode + * + * <h4>Selecting a Union of Hyperslabs</h4> + * + * The HDF5 Library allows the user to select a union of hyperslabs and write or read the selection into + * another selection. The shapes of the two selections may differ, but the number of elements must be + * equal. + * + * <table> + * <tr> + * <td> + * \image html Dspace_transfer.gif "Transferring hyperslab unions" + * </td> + * </tr> + * </table> + * + * The figure above shows the transfer of a selection that is two overlapping hyperslabs from the dataset + * into a union of hyperslabs in the memory dataset. Note that the destination dataset has a different shape + * from the source dataset. Similarly, the selection in the memory dataset could have a different shape than + * the selected union of hyperslabs in the original file. For simplicity, the selection is that same shape + * at the destination. + * + * To implement this transfer, it is necessary to: + * \li 1. Get the source dataspace + * \li 2. Define one hyperslab selection for the source + * \li 3. Define a second hyperslab selection, unioned with the first + * \li 4. Get the destination dataspace + * \li 5. Define one hyperslab selection for the destination + * \li 6. Define a second hyperslab selection, unioned with the first + * \li 7. Execute the data transfer (H5Dread or H5Dwrite) using the source and destination dataspaces + * + * The example below shows example code to create the selections for the source dataspace (the file). The + * first hyperslab is size 3 x 4 and the left upper corner at the position (1,2). The hyperslab is a simple + * rectangle, so the stride and block are 1. The second hyperslab is 6 x 5 at the position (2,4). The second + * selection is a union with the first hyperslab (#H5S_SELECT_OR). + * + * <em> Select source hyperslabs</em> + * \code + * fid = H5Dget_space(dataset); + * + * // Select first hyperslab for the dataset in the file. + * offset[0] = 1; offset[1] = 2; + * block[0] = 1; block[1] = 1; + * stride[0] = 1; stride[1] = 1; + * count[0] = 3; count[1] = 4; + * ret = H5Sselect_hyperslab(fid, H5S_SELECT_SET, offset, stride, count, block); + * + * // Add second selected hyperslab to the selection. + * offset[0] = 2; offset[1] = 4; + * block[0] = 1; block[1] = 1; + * stride[0] = 1; stride[1] = 1; + * count[0] = 6; count[1] = 5; + * ret = H5Sselect_hyperslab(fid, H5S_SELECT_OR, offset, stride, count, block); + * \endcode + * + * The example below shows example code to create the selection for the destination in memory. The steps + * are similar. In this example, the hyperslabs are the same shape, but located in different positions in the + * dataspace. The first hyperslab is 3 x 4 and starts at (0,0), and the second is 6 x 5 and starts at (1,2). + * Finally, the H5Dread call transfers the selected data from the file dataspace to the selection in memory. + * In this example, the source and destination selections are two overlapping rectangles. In general, any + * number of rectangles can be OR’ed, and they do not have to be contiguous. The order of the selections + * does not matter, but the first should use #H5S_SELECT_SET ; subsequent selections are unioned using + * #H5S_SELECT_OR. + * + * It is important to emphasize that the source and destination do not have to be the same shape (or number + * of rectangles). As long as the two selections have the same number of elements, the data can be + * transferred. + * + * <em>Select destination hyperslabs</em> + * \code + * // Create memory dataspace. + * mid = H5Screate_simple(MSPACE_RANK, mdim, NULL); + * + * // Select two hyperslabs in memory. Hyperslabs has the + * // same size and shape as the selected hyperslabs for + * // the file dataspace. + * offset[0] = 0; offset[1] = 0; + * block[0] = 1; block[1] = 1; + * stride[0] = 1; stride[1] = 1; + * count[0] = 3; count[1] = 4; + * ret = H5Sselect_hyperslab(mid, H5S_SELECT_SET, offset, stride, count, block); + * + * offset[0] = 1; offset[1] = 2; + * block[0] = 1; block[1] = 1; + * stride[0] = 1; stride[1] = 1; + * count[0] = 6; count[1] = 5; + * ret = H5Sselect_hyperslab(mid, H5S_SELECT_OR, offset, stride, count, block); + * + * ret = H5Dread(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, matrix_out); + * \endcode + * + * <h4>Selecting a List of Independent Points</h4> + * + * It is also possible to specify a list of elements to read or write using the function H5Sselect_elements. + * + * The procedure is similar to hyperslab selections. + * \li 1. Get the source dataspace + * \li 2. Set the selected points + * \li 3. Get the destination dataspace + * \li 4. Set the selected points + * \li 5. Transfer the data using the source and destination dataspaces + * + * The figure below shows an example where four values are to be written to four separate points in a two + * dimensional dataspace. The source dataspace is a one dimensional array with the values 53, 59, 61, 67. + * The destination dataspace is an 8 x 12 array. The elements are to be written to the points + * (0,0), (3,3), (3,5), and (5,6). In this example, the source does not require a selection. The example + * below the figure shows example code to implement this transfer. + * + * A point selection lists the exact points to be transferred and the order they will be transferred. The + * source and destination are required to have the same number of elements. A point selection can be used + * with a hyperslab (for example, the source could be a point selection and the destination a hyperslab, + * or vice versa), so long as the number of elements selected are the same. + * + * <table> + * <tr> + * <td> + * \image html Dspace_separate.gif "Write data to separate points" + * </td> + * </tr> + * </table> + * + * <em>Write data to separate points</em> + * \code + * hsize_t dim2[] = {4}; + * int values[] = {53, 59, 61, 67}; + * + * // file dataspace + * hssize_t coord[4][2]; + * + * // Create dataspace for the second dataset. + * mid2 = H5Screate_simple(1, dim2, NULL); + * + * // Select sequence of NPOINTS points in the file dataspace. + * coord[0][0] = 0; coord[0][1] = 0; + * coord[1][0] = 3; coord[1][1] = 3; + * coord[2][0] = 3; coord[2][1] = 5; + * coord[3][0] = 5; coord[3][1] = 6; + * + * ret = H5Sselect_elements(fid, H5S_SELECT_SET, NPOINTS, (const hssize_t **)coord); + * + * ret = H5Dwrite(dataset, H5T_NATIVE_INT, mid2, fid, H5P_DEFAULT, values); + * \endcode + * + * <h4>Combinations of Selections</h4> + * + * Selections are a very flexible mechanism for reorganizing data during a data transfer. With different + * combinations of dataspaces and selections, it is possible to implement many kinds of data transfers + * including sub‐setting, sampling, and reorganizing the data. The table below gives some example combinations + * of source and destination, and the operations they implement. + * + * <table> + * <caption>Selection operations</caption> + * <tr> + * <th> + * <p>Source</p> + * </th> + * <th> + * <p>Destination</p> + * </th> + * <th> + * <p>Operation</p> + * </th> + * </tr> + * <tr> + * <td> + * <p>All</p> + * </td> + * <td> + * <p>All</p> + * </td> + * <td> + * <p>Copy whole array</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>All</p> + * </td> + * <td> + * <p>All (different shape)</p> + * </td> + * <td> + * <p>Copy and reorganize array</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Hyperslab</p> + * </td> + * <td> + * <p>All</p> + * </td> + * <td> + * <p>Sub-set</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Hyperslab</p> + * </td> + * <td> + * <p>Hyperslab (same shape)</p> + * </td> + * <td> + * <p>Selection</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Hyperslab</p> + * </td> + * <td> + * <p>Hyperslab (different shape)</p> + * </td> + * <td> + * <p>Select and rearrange</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Hyperslab with stride or block</p> + * </td> + * <td> + * <p>All or hyperslab with stride 1</p> + * </td> + * <td> + * <p>Sub-sample, scatter</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Hyperslab</p> + * </td> + * <td> + * <p>Points</p> + * </td> + * <td> + * <p>Scatter</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Points</p> + * </td> + * <td> + * <p>Hyperslab or all</p> + * </td> + * <td> + * <p>Gather</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Points</p> + * </td> + * <td> + * <p>Points (same)</p> + * </td> + * <td> + * <p>Selection</p> + * </td> + * </tr> + * <tr> + * <td> + * <p>Points</p> + * </td> + * <td> + * <p>Points (different)</p> + * </td> + * <td> + * <p>Reorder points</p> + * </td> + * </tr> + * </table> + * + * \subsection subsec_dataspace_select Dataspace Selection Operations and Data Transfer + * + * This section is under construction. + * + * \subsection subsec_dataspace_refer References to Dataset Regions + * + * Another use of selections is to store a reference to a region of a dataset. An HDF5 object reference + * object is a pointer to an object (dataset, group, or committed datatype) in the file. A selection can + * be used to create a pointer to a set of selected elements of a dataset, called a region reference. The + * selection can be either a point selection or a hyperslab selection. + * + * A region reference is an object maintained by the HDF5 Library. The region reference can be stored in a + * dataset or attribute, and then read. The dataset or attribute is defined to have the special datatype, + * #H5T_STD_REF_DSETREG. + * + * To discover the elements and/or read the data, the region reference can be dereferenced. The + * #H5Rdereference call returns an identifier for the dataset, and then the selected dataspace can be + * retrieved with a call to #H5Rget_region(). The selected dataspace can be used to read the selected data + * elements. + * + * For more information, \see subsubsec_datatype_other_refs. + * + * \subsubsection subsubsec_dataspace_refer_use Example Uses for Region References + * + * Region references are used to implement stored pointers to data within a dataset. For example, features + * in a large dataset might be indexed by a table. See the figure below. This table could be stored as an + * HDF5 dataset with a compound datatype, for example, with a field for the name of the feature and a region + * reference to point to the feature in the dataset. See the second figure below. + * + * <table> + * <tr> + * <td> + * \image html Dspace_features.gif " Features indexed by a table" + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Dspace_features_cmpd.gif "Storing the table with a compound datatype" + * </td> + * </tr> + * </table> + * + * + * \subsubsection subsubsec_dataspace_refer_create Creating References to Regions + * + * To create a region reference: + * \li 1. Create or open the dataset that contains the region + * \li 2. Get the dataspace for the dataset + * \li 3. Define a selection that specifies the region + * \li 4. Create a region reference using the dataset and dataspace with selection + * \li 5. Write the region reference(s) to the desired dataset or attribute + * + * The figure below shows a diagram of a file with three datasets. Dataset D1 and D2 are two dimensional + * arrays of integers. Dataset R1 is a one dimensional array of references to regions in D1 and D2. The + * regions can be any valid selection of the dataspace of the target dataset. + * <table> + * <tr> + * <td> + * \image html Dspace_three_datasets.gif "A file with three datasets" + * </td> + * </tr> + * </table> + * <em>Note: In the figure above, R1 is a 1 D array of region pointers; each pointer refers to a selection + * in one dataset.</em> + * + * The example below shows code to create the array of region references. The references are created in an + * array of type #hdset_reg_ref_t. Each region is defined as a selection on the dataspace of the dataset, + * and a reference is created using \ref H5Rcreate(). The call to \ref H5Rcreate() specifies the file, + * dataset, and the dataspace with selection. + * + * <em>Create an array of region references</em> + * \code + * // create an array of 4 region references + * hdset_reg_ref_t ref[4]; + * + * // Create a reference to the first hyperslab in the first Dataset. + * offset[0] = 1; offset[1] = 1; + * count[0] = 3; count[1] = 2; + * status = H5Sselect_hyperslab(space_id, H5S_SELECT_SET, offset, NULL, count, NULL); + * status = H5Rcreate(&ref[0], file_id, "D1", H5R_DATASET_REGION, space_id); + * + * // The second reference is to a union of hyperslabs in the first Dataset + * offset[0] = 5; offset[1] = 3; + * count[0] = 1; count[1] = 4; + * status = H5Sselect_none(space_id); + * status = H5Sselect_hyperslab(space_id, H5S_SELECT_SET, offset, NULL, count, NULL); + * offset[0] = 6; offset[1] = 5; + * count[0] = 1; count[1] = 2; + * status = H5Sselect_hyperslab(space_id, H5S_SELECT_OR, offset, NULL, count, NULL); + * status = H5Rcreate(&ref[1], file_id, "D1", H5R_DATASET_REGION, space_id); + * + * // the fourth reference is to a selection of points in the first Dataset + * status = H5Sselect_none(space_id); + * coord[0][0] = 4; coord[0][1] = 4; + * coord[1][0] = 2; coord[1][1] = 6; + * coord[2][0] = 3; coord[2][1] = 7; + * coord[3][0] = 1; coord[3][1] = 5; + * coord[4][0] = 5; coord[4][1] = 8; + * + * status = H5Sselect_elements(space_id, H5S_SELECT_SET, num_points, (const hssize_t **)coord); + * status = H5Rcreate(&ref[3], file_id, "D1", H5R_DATASET_REGION, space_id); + * + * // the third reference is to a hyperslab in the second Dataset + * offset[0] = 0; offset[1] = 0; + * count[0] = 4; count[1] = 6; + * status = H5Sselect_hyperslab(space_id2, H5S_SELECT_SET, offset, NULL, count, NULL); + * status = H5Rcreate(&ref[2], file_id, "D2", H5R_DATASET_REGION, space_id2); + * \endcode + * + * When all the references are created, the array of references is written to the dataset R1. The + * dataset is declared to have datatype #H5T_STD_REF_DSETREG. See the example below. + * + * <em>Write the array of references to a dataset</em> + * \code + * Hsize_t dimsr[1]; + * dimsr[0] = 4; + * + * // Dataset with references. + * spacer_id = H5Screate_simple(1, dimsr, NULL); + * dsetr_id = H5Dcreate(file_id, "R1", H5T_STD_REF_DSETREG, spacer_id, H5P_DEFAULT, H5P_DEFAULT, + * H5P_DEFAULT); + * + * // Write dataset with the references. + * status = H5Dwrite(dsetr_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref); + * + * \endcode + * + * When creating region references, the following rules are enforced. + * \li The selection must be a valid selection for the target dataset, just as when transferring data + * \li The dataset must exist in the file when the reference is created; #H5Rcreate + * \li The target dataset must be in the same file as the stored reference + * + * \subsubsection subsubsec_dataspace_refer_read Reading References to Regions + * + * To retrieve data from a region reference, the reference must be read from the file, and then the data can + * be retrieved. The steps are: + * \li 1. Open the dataset or attribute containing the reference objects + * \li 2. Read the reference object(s) + * \li 3. For each region reference, get the dataset (#H5Rdereference) and dataspace (#H5Rget_region) + * \li 4. Use the dataspace and datatype to discover what space is needed to store the data, allocate the + * correct storage and create a dataspace and datatype to define the memory data layout + * + * The example below shows code to read an array of region references from a dataset, and then read the + * data from the first selected region. Note that the region reference has information that records the + * dataset (within the file) and the selection on the dataspace of the dataset. After dereferencing the + * regions reference, the datatype, number of points, and some aspects of the selection can be discovered. + * (For a union of hyperslabs, it may not be possible to determine the exact set of hyperslabs that has been + * combined.) + * The table below the code example shows the inquiry functions. + * + * When reading data from a region reference, the following rules are enforced: + * \li The target dataset must be present and accessible in the file + * \li The selection must be a valid selection for the dataset + * + * <em>Read an array of region references; read from the first selection</em> + * \code + * dsetr_id = H5Dopen (file_id, "R1", H5P_DEFAULT); + * status = H5Dread(dsetr_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ref_out); + * + * // Dereference the first reference. + * // 1) get the dataset (H5Rdereference) + * // 2) get the selected dataspace (H5Rget_region) + * + * dsetv_id = H5Rdereference(dsetr_id, H5R_DATASET_REGION, &ref_out[0]); + * space_id = H5Rget_region(dsetr_id, H5R_DATASET_REGION, &ref_out[0]); + * + * // Discover how many points and shape of the data + * ndims = H5Sget_simple_extent_ndims(space_id); + * H5Sget_simple_extent_dims(space_id,dimsx,NULL); + * + * // Read and display hyperslab selection from the dataset. + * dimsy[0] = H5Sget_select_npoints(space_id); + * spacex_id = H5Screate_simple(1, dimsy, NULL); + * + * status = H5Dread(dsetv_id, H5T_NATIVE_INT, H5S_ALL, space_id, H5P_DEFAULT, data_out); + * printf("Selected hyperslab: "); + * for (i = 0; i < 8; i++) { + * printf("\n"); + * for (j = 0; j < 10; j++) + * printf("%d ", data_out[i][j]); + * } + * printf("\n"); + * \endcode + * + * <table> + * <caption>The inquiry functions</caption> + * <tr> + * <th> + * <p>Function</p> + * </th> + * <th> + * <p>Information</p> + * </th> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_npoints + * </td> + * <td> + * <p>The number of elements in the selection (hyperslab or point selection).</p> + * </td> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_bounds + * </td> + * <td> + * <p>The bounding box that encloses the selected points (hyperslab or point selection).</p> + * </td> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_hyper_nblocks + * </td> + * <td> + * <p>The number of blocks in the selection.</p> + * </td> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_hyper_blocklist + * </td> + * <td> + * <p>A list of the blocks in the selection.</p> + * </td> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_elem_npoints + * </td> + * <td> + * <p>The number of points in the selection.</p> + * </td> + * </tr> + * <tr> + * <td> + * @ref H5Sget_select_elem_pointlist + * </td> + * <td> + * <p>The points.</p> + * </td> + * </tr> + * </table> + * + * + * \subsection subsec_dataspace_sample Sample Programs + * + * This section contains the full programs from which several of the code examples in this chapter were + * derived. The h5dump output from the program’s output file immediately follows each program. + * + * <em>h5_write.c</em> + * \code + * #include "hdf5.h" + * + * #define H5FILE_NAME "SDS.h5" + * #define DATASETNAME "C Matrix" + * #define NX 3 + * #define NY 5 + * #define RANK 2 // dataset dimensions + * + * int + * main (void) + * { + * hid_t file, dataset; // file and dataset identifiers + * hid_t datatype, dataspace; // identifiers + * hsize_t dims[2]; // dataset dimensions + * herr_t status; + * int data[NX][NY]; // data to write + * int i, j; + * + * // + * // Data and output buffer initialization. + * for (j = 0; j < NX; j++) { + * for (i = 0; i < NY; i++) + * data[j][i] = i + 1 + j*NY; + * } + * // 1 2 3 4 5 + * // 6 7 8 9 10 + * // 11 12 13 14 15 + * + * // Create a new file using H5F_ACC_TRUNC access, + * // default file creation properties, and default file + * // access properties. + * file = H5Fcreate(H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + * + * // Describe the size of the array and create the data space for fixed + * // size dataset. + * dims[0] = NX; + * dims[1] = NY; + * dataspace = H5Screate_simple(RANK, dims, NULL); + * + * // Create a new dataset within the file using defined dataspace and + * // datatype and default dataset creation properties. + * dataset = H5Dcreate(file, DATASETNAME, H5T_NATIVE_INT, dataspace, H5P_DEFAULT, + * H5P_DEFAULT, H5P_DEFAULT); + * + * // Write the data to the dataset using default transfer properties. + * status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * + * // Close/release resources. + * H5Sclose(dataspace); + * H5Dclose(dataset); + * H5Fclose(file); + * + * return 0; + * } + * + * SDS.out + * ------- + * HDF5 "SDS.h5" { + * GROUP "/" { + * DATASET "C Matrix" { + * DATATYPE H5T_STD_I32BE + * DATASPACE SIMPLE { ( 3, 5 ) / ( 3, 5 ) } + * DATA { + * 1, 2, 3, 4, 5, + * 6, 7, 8, 9, 10, + * 11, 12, 13, 14, 15 + * } + * } + * + * \endcode + * + * <em>h5_write.f90</em> + * \code + * ---------- + * PROGRAM DSETEXAMPLE + * + * USE HDF5 ! This module contains all necessary modules + * + * IMPLICIT NONE + * + * CHARACTER(LEN=7), PARAMETER :: filename = "SDSf.h5" ! File name + * CHARACTER(LEN=14), PARAMETER :: dsetname = "Fortran Matrix" ! Dataset name + * INTEGER, PARAMETER :: NX = 3 + * INTEGER, PARAMETER :: NY = 5 + * + * INTEGER(HID_T) :: file_id ! File identifier + * INTEGER(HID_T) :: dset_id ! Dataset identifier + * INTEGER(HID_T) :: dspace_id ! Dataspace identifier + * + * INTEGER(HSIZE_T), DIMENSION(2) :: dims = (/3,5/) ! Dataset dimensions + * INTEGER :: rank = 2 ! Dataset rank + * INTEGER :: data(NX,NY) + * INTEGER :: error ! Error flag + * INTEGER :: i, j + * + * ! + * ! Initialize data + * ! + * do i = 1, NX + * do j = 1, NY + * data(i,j) = j + (i-1)*NY + * enddo + * enddo + * ! + * ! Data + * ! + * ! 1 2 3 4 5 + * ! 6 7 8 9 10 + * ! 11 12 13 14 15 + * + * ! + * ! Initialize FORTRAN interface. + * ! + * CALLh5open_f(error) + * + * ! + * ! Create a new file using default properties. + * ! + * CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file_id, error) + * + * ! + * ! Create the dataspace. + * ! + * CALL h5screate_simple_f(rank, dims, dspace_id, error) + * + * ! + * ! Create and write dataset using default properties. + * ! + * CALL h5dcreate_f(file_id, dsetname, H5T_NATIVE_INTEGER, dspace_id, & + * dset_id, error, H5P_DEFAULT_F, H5P_DEFAULT_F, & + * H5P_DEFAULT_F) + * + * CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, data, dims, error) + * + * ! + * ! End access to the dataset and release resources used by it. + * ! + * CALL h5dclose_f(dset_id, error) + * + * ! + * ! Terminate access to the data space. + * ! + * CALL h5sclose_f(dspace_id, error) + * + * ! + * ! Close the file. + * ! + * CALL h5fclose_f(file_id, error) + * + * ! + * ! Close FORTRAN interface. + * ! + * CALL h5close_f(error) + * + * END PROGRAM DSETEXAMPLE + * + * SDSf.out + * -------- + * HDF5 "SDSf.h5" { + * GROUP "/" { + * DATASET "Fortran Matrix" { + * DATATYPE H5T_STD_I32BE + * DATASPACE SIMPLE { ( 5, 3 ) / ( 5, 3 ) } + * DATA { + * 1, 6, 11, + * 2, 7, 12, + * 3, 8, 13, + * 4, 9, 14, + * 5, 10, 15 + * } + * } + * } + * } + * + * \endcode + * + * <em>h5_write_tr.f90</em> + * \code + * PROGRAM DSETEXAMPLE + * + * USE HDF5 ! This module contains all necessary modules + * + * IMPLICIT NONE + * + * CHARACTER(LEN=10), PARAMETER :: filename = "SDSf_tr.h5" ! File name + * CHARACTER(LEN=24), PARAMETER :: dsetname = "Fortran Transpose Matrix"! Dataset name + * + * INTEGER, PARAMETER :: NX = 3 + * INTEGER, PARAMETER :: NY = 5 + * + * INTEGER(HID_T) :: file_id ! File identifier + * INTEGER(HID_T) :: dset_id ! Dataset identifier + * INTEGER(HID_T) :: dspace_id ! Dataspace identifier + * + * INTEGER(HSIZE_T), DIMENSION(2) :: dims = (/NY, NX/) ! Dataset dimensions + * INTEGER :: rank = 2 ! Dataset rank + * INTEGER :: data(NY,NX) + * + * INTEGER :: error ! Error flag + * INTEGER :: i, j + * + * ! + * ! Initialize data + * ! + * do i = 1, NY + * do j = 1, NX + * data(i,j) = i + (j-1)*NY + * enddo + * enddo + * + * ! + * ! Data + * ! + * ! 1 6 11 + * ! 2 7 12 + * ! 3 8 13 + * ! 4 9 14 + * ! 5 10 15 + * + * ! + * ! Initialize FORTRAN interface. + * ! + * CALL h5open_f(error) + * + * ! + * ! Create a new file using default properties. + * ! + * CALL h5fcreate_f(filename, H5F_ACC_TRUNC_F, file_id, error) + * + * ! + * ! Create the dataspace. + * ! + * CALL h5screate_simple_f(rank, dims, dspace_id, error) + * + * ! + * ! Create and write dataset using default properties. + * ! + * CALL h5dcreate_f(file_id, dsetname, H5T_NATIVE_INTEGER, dspace_id, & + * dset_id, error, H5P_DEFAULT_F, H5P_DEFAULT_F, & + * H5P_DEFAULT_F) + * CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, data, dims, error) + * + * ! + * ! End access to the dataset and release resources used by it. + * ! + * CALL h5dclose_f(dset_id, error) + * + * ! + * ! Terminate access to the data space. + * ! + * CALL h5sclose_f(dspace_id, error) + * + * ! + * ! Close the file. + * ! + * CALL h5fclose_f(file_id, error) + * + * ! + * ! Close FORTRAN interface. + * ! + * CALL h5close_f(error) + * + * END PROGRAM DSETEXAMPLE + * + * SDSf_tr.out + * ----------- + * HDF5 "SDSf_tr.h5" { + * GROUP "/" { + * DATASET "Fortran Transpose Matrix" { + * DATATYPE H5T_STD_I32LE + * DATASPACE SIMPLE { ( 3, 5 ) / ( 3, 5 ) } + * DATA { + * 1, 2, 3, 4, 5, + * 6, 7, 8, 9, 10, + * 11, 12, 13, 14, 15 + * } + * } + * } + * } + * + * \endcode + * + * Previous Chapter \ref sec_datatype - Next Chapter \ref sec_attribute + * + */ + +/** + * \defgroup H5S Dataspaces (H5S) * * Use the functions in this module to manage HDF5 dataspaces \Emph{and} selections. * @@ -41,6 +1528,7 @@ * using \Emph{selections}. Furthermore, certain set operations are supported * for selections. * + * <!-- * <table> * <tr><th>Create</th><th>Read</th></tr> * <tr valign="top"> @@ -60,7 +1548,7 @@ * </td> * </tr> * </table> - * + * --> */ #endif /* H5Smodule_H */ diff --git a/src/H5Tmodule.h b/src/H5Tmodule.h index 30ac702..83f7467 100644 --- a/src/H5Tmodule.h +++ b/src/H5Tmodule.h @@ -29,7 +29,3837 @@ #define H5_MY_PKG_ERR H5E_DATATYPE #define H5_MY_PKG_INIT YES -/**\defgroup H5T H5T +/** \page H5T_UG HDF5 Datatypes + * + * \section sec_datatype HDF5 Datatypes + * HDF5 datatypes describe the element type of HDF5 datasets and attributes. + * There's a large set of predefined datatypes, but users may find it useful + * to define new datatypes through a process called \Emph{derivation}. + * + * The element type is automatically persisted as part of the HDF5 metadata of + * attributes and datasets. Additionally, datatype definitions can be persisted + * to HDF5 files and linked to groups as HDF5 datatype objects or so-called + * \Emph{committed datatypes}. + * + * \subsection subsec_datatype_intro Introduction and Definitions + * + * An HDF5 dataset is an array of data elements, arranged according to the specifications + * of the dataspace. In general, a data element is the smallest addressable unit of storage + * in the HDF5 file. (Compound datatypes are the exception to this rule.) The HDF5 datatype + * defines the storage format for a single data element. See the figure below. + * + * The model for HDF5 attributes is extremely similar to datasets: an attribute has a dataspace + * and a data type, as shown in the figure below. The information in this chapter applies to both + * datasets and attributes. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig1.gif "Datatypes, dataspaces, and datasets" + * </td> + * </tr> + * </table> + * + * Abstractly, each data element within the dataset is a sequence of bits, interpreted as a single + * value from a set of values (for example, a number or a character). For a given datatype, there is a + * standard or convention for representing the values as bits, and when the bits are represented in a + * particular storage the bits are laid out in a specific storage scheme such as 8-bit bytes with a + * specific ordering and alignment of bytes within the storage array. + * + * HDF5 datatypes implement a flexible, extensible, and portable mechanism for specifying and + * discovering the storage layout of the data elements, determining how to interpret the elements + * (for example, as floating point numbers), and for transferring data from different compatible + * layouts. + * + * An HDF5 datatype describes one specific layout of bits. A dataset has a single datatype which + * applies to every data element. When a dataset is created, the storage datatype is defined. After + * the dataset or attribute is created, the datatype cannot be changed. + * \li The datatype describes the storage layout of a singledata element + * \li All elements of the dataset must have the same type + * \li The datatype of a dataset is immutable + * + * When data is transferred (for example, a read or write), each end point of the transfer has a + * datatype, which describes the correct storage for the elements. The source and destination may + * have different (but compatible) layouts, in which case the data elements are automatically + * transformed during the transfer. + * + * HDF5 datatypes describe commonly used binary formats for numbers (integers + * and floating point) and characters (ASCII). A given computing architecture and programming language + * supports certain number and character representations. For example, a computer may support 8-, + * 16-, 32-, and 64-bit signed integers, stored in memory in little-endian byte order. These would + * presumably correspond to the C programming language types \Emph{char}, \Emph{short}, + * \Emph{int}, and \Emph{long}. + * + * When reading and writing from memory, the HDF5 library must know the appropriate datatype + * that describes the architecture specific layout. The HDF5 library provides the platform + * independent \Emph{NATIVE} types, which are mapped to an appropriate datatype for each platform. + * So the type #H5T_NATIVE_INT is an alias for the appropriate descriptor for each platform. + * + * Data in memory has a datatype: + * \li The storage layout in memory is architecture-specific + * \li The HDF5 \Emph{NATIVE} types are predefined aliases for the architecture-specific memory layout + * \li The memory datatype need not be the same as the stored datatype of the dataset + * + * In addition to numbers and characters, an HDF5 datatype can describe more abstract classes of + * types including enumerations, strings, bit strings, and references (pointers to objects in the HDF5 + * file). HDF5 supports several classes of composite datatypes which are combinations of one or + * more other datatypes. In addition to the standard predefined datatypes, users can define new + * datatypes within the datatype classes. + * + * The HDF5 datatype model is very general and flexible: + * \li For common simple purposes, only predefined types will be needed + * \li Datatypes can be combined to create complex structured datatypes + * \li If needed, users can define custom atomic datatypes + * \li Committed datatypes can be shared by datasets or attributes + * + * \subsection subsec_datatype_model Datatype Model + * The HDF5 library implements an object-oriented model of datatypes. HDF5 datatypes are + * organized as a logical set of base types, or datatype classes. Each datatype class defines + * a format for representing logical values as a sequence of bits. For example the #H5T_INTEGER + * class is a format for representing twos complement integers of various sizes. + * + * A datatype class is defined as a set of one or more datatype properties. A datatype property is + * a property of the bit string. The datatype properties are defined by the logical model of the + * datatype class. For example, the integer class (twos complement integers) has properties such as + * “signed or unsigned”, “length”, and “byte-order”. The float class (IEEE floating point numbers) + * has these properties, plus “exponent bits”, “exponent sign”, etc. + * + * A datatype is derived from one datatype class: a given datatype has a specific value for the + * datatype properties defined by the class. For example, for 32-bit signed integers, stored + * big-endian, the HDF5 datatype is a sub-type of integer with the properties set to + * signed=1, size=4(bytes), and byte-order=BE. + * + * The HDF5 datatype API (H5T functions) provides methods to create datatypes of different + * datatype classes, to set the datatype properties of a new datatype, and to discover the datatype + * properties of an existing datatype. + * + * The datatype for a dataset is stored in the HDF5 file as part of the metadata for the dataset. + * A datatype can be shared by more than one dataset in the file if the datatype is saved to the + * file with a name. This shareable datatype is known as a committed datatype. In the past, + * this kind of datatype was called a named datatype. + * + * When transferring data (for example, a read or write), the data elements of the source and + * destination storage must have compatible types. As a general rule, data elements with the same + * datatype class are compatible while elements from different datatype classes are not compatible. + * When transferring data of one datatype to another compatible datatype, the HDF5 Library uses + * the datatype properties of the source and destination to automatically transform each data + * element. For example, when reading from data stored as 32-bit signed integers, big + * endian into 32-bit signed integers, little-endian, the HDF5 Library will automatically swap the + * bytes. + * + * Thus, data transfer operations (\ref H5Dread, \ref H5Dwrite, \ref H5Aread, \ref H5Awrite) require + * a datatype for both the source and the destination. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig2.gif "The datatype model" + * </td> + * </tr> + * </table> + * + * The HDF5 library defines a set of predefined datatypes, corresponding to commonly used + * storage formats, such as twos complement integers, IEEE Floating point numbers, etc., 4- + * and 8-byte sizes, big-endian and little-endian byte orders. In addition, a user can derive types with + * custom values for the properties. For example, a user program may create a datatype to describe + * a 6-bit integer, or a 600-bit floating point number. + * + * In addition to atomic datatypes, the HDF5 library supports composite datatypes. A composite + * datatype is an aggregation of one or more datatypes. Each class of composite datatypes has + * properties that describe the organization of the composite datatype. See the figure below. + * Composite datatypes include: + * \li Compound datatypes: structured records + * \li Array: a multidimensional array of a datatype + * \li Variable-length: a one-dimensional array of a datatype + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig3.gif "Composite datatypes" + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_model_class Datatype Classes and Properties + * The figure below shows the HDF5 datatype classes. Each class is defined to have a set of + * properties which describe the layout of the data element and the interpretation of the bits. The + * table below lists the properties for the datatype classes. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig4.gif "Datatype classes" + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Datatype classes and their properties</caption> + * <tr> + * <th> + * Class + * </th> + * <th> + * Description + * </th> + * <th> + * Properties + * </th> + * <th> + * Notes + * </th> + * </tr> + * <tr> + * <td> + * Integer + * </td> + * <td> + * Twos complement integers + * </td> + * <td> + * Size (bytes), precision (bits), offset (bits), pad, byte order, signed/unsigned + * </td> + * <td> + * </td> + * </tr> + * <tr> + * <td> + * Float + * </td> + * <td> + * Floating Point numbers + * </td> + * <td> + * Size (bytes), precision (bits), offset (bits), pad, byte order, sign position, + * exponent position, exponent size (bits), exponent sign, exponent bias, mantissa position, + * mantissa (size) bits, mantissa sign, mantissa normalization, internal padding + * </td> + * <td> + * See IEEE 754 for a definition of these properties. These properties describe + * non-IEEE 754 floating point formats as well. + * </td> + * </tr> + * <tr> + * <td> + * Character + * </td> + * <td> + * Array of 1-byte character encoding + * </td> + * <td> + * Size (characters), Character set, byte order, pad/no pad, pad character + * </td> + * <td> + * Currently, ASCII and UTF-8 are supported. + * </td> + * </tr> + * <tr> + * <td> + * Bitfield + * </td> + * <td> + * String of bits + * </td> + * <td> + * Size (bytes), precision (bits), offset (bits), pad, byte order + * </td> + * <td> + * A sequence of bit values packed into one or more bytes. + * </td> + * </tr> + * <tr> + * <td> + * Opaque + * </td> + * <td> + * Uninterpreted data + * </td> + * <td> + * Size (bytes), precision (bits), offset (bits), pad, byte order, tag + * </td> + * <td> + * A sequence of bytes, stored and retrieved as a block. + * The ‘tag’ is a string that can be used to label the value. + * </td> + * </tr> + * <tr> + * <td> + * Enumeration + * </td> + * <td> + * A list of discrete values, with symbolic names in the form of strings. + * </td> + * <td> + * Number of elements, element names, element values + * </td> + * <td> + * Enumeration is a list of pairs (name, value). The name is a string; the + * value is an unsigned integer. + * </td> + * </tr> + * <tr> + * <td> + * Reference + * </td> + * <td> + * Reference to object or region within the HDF5 file + * </td> + * <td> + * + * </td> + * <td> + * @see H5R + * </td> + * </tr> + * <tr> + * <td> + * Array + * </td> + * <td> + * Array (1-4 dimensions) of data elements + * </td> + * <td> + * Number of dimensions, dimension sizes, base datatype + * </td> + * <td> + * The array is accessed atomically: no selection or sub-setting. + * </td> + * </tr> + * <tr> + * <td> + * Variable-length + * </td> + * <td> + * A variable-length 1-dimensional array of data elements + * </td> + * <td> + * Current size, base type + * </td> + * <td> + * + * </td> + * </tr> + * <tr> + * <td> + * Compound + * </td> + * <td> + * A Datatype of a sequence of Datatypes + * </td> + * <td> + * Number of members, member names, member types, member offset, member class, + * member size, byte order + * </td> + * <td> + * + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_model_predefine Predefined Datatypes + * The HDF5 library predefines a modest number of commonly used datatypes. These types have + * standard symbolic names of the form H5T_arch_base where arch is an architecture name and + * base is a programming type name <b>Table 2</b>. New types can be derived from the predefined + * types by copying the predefined type \ref H5Tcopy() and then modifying the result. + * + * The base name of most types consists of a letter to indicate the class <b>Table 3</b>, a precision in + * bits, and an indication of the byte order <b>Table 4</b>. + * + * <b>Table 5</b> shows examples of predefined datatypes. The full list can be found in the + * \ref PDT section of the \ref RM. + * + * <table> + * <caption align=top>Table 2. Architectures used in predefined datatypes</caption> + * <tr> + * <th> + * Architecture Name + * </th> + * <th span='3'> + * Description + * </th> + * </tr> + * <tr> + * <td> + * IEEE + * </td> + * <td span='3'> + * IEEE-754 standard floating point types in various byte orders. + * </td> + * </tr> + * <tr> + * <td> + * STD + * </td> + * <td span='3'> + * This is an architecture that contains semi-standard datatypes like signed + * two’s complement integers, unsigned integers, and bitfields in various + * byte orders. + * </td> + * </tr> + * <tr> + * <td> + * C <br \> FORTRAN + * </td> + * <td span='3'> + * Types which are specific to the C or Fortran programming languages + * are defined in these architectures. For instance, #H5T_C_S1 defines a + * base string type with null termination which can be used to derive string + * types of other lengths. + * </td> + * </tr> + * <tr> + * <td> + * NATIVE + * </td> + * <td span='3'> + * This architecture contains C-like datatypes for the machine on which + * the library was compiled. The types were actually defined by running + * the H5detect program when the library was compiled. In order to be + * portable, applications should almost always use this architecture + * to describe things in memory. + * </td> + * </tr> + * <tr> + * <td> + * CRAY + * </td> + * <td span='3'> + * Cray architectures. These are word-addressable, big-endian systems + * with non-IEEE floating point. + * </td> + * </tr> + * <tr> + * <td> + * INTEL + * </td> + * <td span='3'> + * All Intel and compatible CPU’s. + * These are little-endian systems with IEEE floating-point. + * </td> + * </tr> + * <tr> + * <td> + * MIPS + * </td> + * <td span='3'> + * All MIPS CPU’s commonly used in SGI systems. These are big-endian + * systems with IEEE floating-point. + * </td> + * </tr> + * <tr> + * <td> + * ALPHA + * </td> + * <td span='3'> + * All DEC Alpha CPU’s, little-endian systems with IEEE floating-point. + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 3. Base types</caption> + * <tr> + * <th> + * Base + * </th> + * <th span='3'> + * Description + * </th> + * </tr> + * <tr> + * <td> + * B + * </td> + * <td span='3'> + * Bitfield + * </td> + * </tr> + * <tr> + * <td> + * F + * </td> + * <td span='3'> + * Floating point + * </td> + * </tr> + * <tr> + * <td> + * I + * </td> + * <td span='3'> + * Signed integer + * </td> + * </tr> + * <tr> + * <td> + * R + * </td> + * <td span='3'> + * References + * </td> + * </tr> + * <tr> + * <td> + * S + * </td> + * <td span='3'> + * Character string + * </td> + * </tr> + * <tr> + * <td> + * U + * </td> + * <td span='3'> + * Unsigned integer + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 4. Byte order</caption> + * <tr> + * <th> + * Order + * </th> + * <th span='3'> + * Description + * </th> + * </tr> + * <tr> + * <td> + * BE + * </td> + * <td span='3'> + * Big-endian + * </td> + * </tr> + * <tr> + * <td> + * LE + * </td> + * <td span='3'> + * Little-endian + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 5. Some predefined datatypes</caption> + * <tr> + * <th> + * Example + * </th> + * <th span='3'> + * Description + * </th> + * </tr> + * <tr> + * <td> + * #H5T_IEEE_F64LE + * </td> + * <td span='3'> + * Eight-byte, little-endian, IEEE floating-point + * </td> + * </tr> + * <tr> + * <td> + * #H5T_IEEE_F32BE + * </td> + * <td span='3'> + * Four-byte, big-endian, IEEE floating point + * </td> + * </tr> + * <tr> + * <td> + * #H5T_STD_I32LE + * </td> + * <td span='3'> + * Four-byte, little-endian, signed two’s complement integer + * </td> + * </tr> + * <tr> + * <td> + * #H5T_STD_U16BE + * </td> + * <td span='3'> + * Two-byte, big-endian, unsigned integer + * </td> + * </tr> + * <tr> + * <td> + * #H5T_C_S1 + * </td> + * <td span='3'> + * One-byte,null-terminated string of eight-bit characters + * </td> + * </tr> + * <tr> + * <td> + * #H5T_INTEL_B64 + * </td> + * <td span='3'> + * Eight-byte bit field on an Intel CPU + * </td> + * </tr> + * <tr> + * <td> + * #H5T_STD_REF_OBJ + * </td> + * <td span='3'> + * Reference to an entire object in a file + * </td> + * </tr> + * </table> + * + * The HDF5 library predefines a set of \Emph{NATIVE} datatypes which are similar to C type names. + * The native types are set to be an alias for the appropriate HDF5 datatype for each platform. For + * example, #H5T_NATIVE_INT corresponds to a C int type. On an Intel based PC, this type is the same as + * #H5T_STD_I32LE, while on a MIPS system this would be equivalent to #H5T_STD_I32BE. Table 6 shows + * examples of \Emph{NATIVE} types and corresponding C types for a common 32-bit workstation. + * + * <table> + * <caption align=top>Table 6. Native and 32-bit C datatypes</caption> + * <tr> + * <th> + * Example + * </th> + * <th span='3'> + * Corresponding C Type + * </th> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_CHAR + * </td> + * <td span='3'> + * char + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_SCHAR + * </td> + * <td span='3'> + * signed char + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_UCHAR + * </td> + * <td span='3'> + * unsigned char + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_SHORT + * </td> + * <td span='3'> + * short + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_USHORT + * </td> + * <td span='3'> + * unsigned short + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_INT + * </td> + * <td span='3'> + * int + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_UINT + * </td> + * <td span='3'> + * unsigned + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_LONG + * </td> + * <td span='3'> + * long + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_ULONG + * </td> + * <td span='3'> + * unsigned long + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_LLONG + * </td> + * <td span='3'> + * long long + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_ULLONG + * </td> + * <td span='3'> + * unsigned long long + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_FLOAT + * </td> + * <td span='3'> + * float + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_DOUBLE + * </td> + * <td span='3'> + * double + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_LDOUBLE + * </td> + * <td span='3'> + * long double + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_HSIZE + * </td> + * <td span='3'> + * hsize_t + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_HSSIZE + * </td> + * <td span='3'> + * hssize_t + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_HERR + * </td> + * <td span='3'> + * herr_t + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_HBOOL + * </td> + * <td span='3'> + * hbool_t + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_B8 + * </td> + * <td span='3'> + * 8-bit unsigned integer or 8-bit buffer in memory + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_B16 + * </td> + * <td span='3'> + * 16-bit unsigned integer or 16-bit buffer in memory + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_B32 + * </td> + * <td span='3'> + * 32-bit unsigned integer or 32-bit buffer in memory + * </td> + * </tr> + * <tr> + * <td> + * #H5T_NATIVE_B64 + * </td> + * <td span='3'> + * 64-bit unsigned integer or 64-bit buffer in memory + * </td> + * </tr> + * </table> + * + * \subsection subsec_datatype_usage How Datatypes are Used + * + * \subsubsection subsubsec_datatype_usage_object The Datatype Object and the HDF5 Datatype API + * The HDF5 library manages datatypes as objects. The HDF5 datatype API manipulates the + * datatype objects through C function calls. New datatypes can be created from scratch or + * copied from existing datatypes. When a datatype is no longer needed its resources should be released by + * calling \ref H5Tclose(). + * + * The datatype object is used in several roles in the HDF5 data model and library. Essentially, a + * datatype is used whenever the form at of data elements is needed. There are four major uses of + * datatypes in the HDF5 library: at dataset creation, during data transfers, when discovering the + * contents of a file, and for specifying user-defined datatypes. See the table below. + * + * <table> + * <caption align=top>Table 7. Datatype uses</caption> + * <tr> + * <th> + * Use + * </th> + * <th span='2'> + * Description + * </th> + * </tr> + * <tr> + * <td> + * Dataset creation + * </td> + * <td span='2'> + * The datatype of the data elements must be declared when the dataset is created. + * </td> + * </tr> + * <tr> + * <td> + * Dataset transfer + * </td> + * <td span='2'> + * The datatype (format) of the data elements must be defined for both the source and destination. + * </td> + * </tr> + * <tr> + * <td> + * Discovery + * </td> + * <td span='2'> + * The datatype of a dataset can be interrogated to retrieve a complete description of the storage layout. + * </td> + * </tr> + * <tr> + * <td> + * Creating user-defined datatypes + * </td> + * <td span='2'> + * Users can define their own datatypes by creating datatype objects and setting their properties. + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_usage_create Dataset Creation + * All the data elements of a dataset have the same datatype. When a dataset is created, the datatype + * for the data elements must be specified. The datatype of a dataset can never be changed. The + * example below shows the use of a datatype to create a dataset called “/dset”. In this example, the + * dataset will be stored as 32-bit signed integers in big-endian order. + * + * <em> Using a datatype to create a dataset </em> + * \code + * hid_t dt; + * + * dt = H5Tcopy(H5T_STD_I32BE); + * dataset_id = H5Dcreate(file_id, “/dset”, dt, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * \subsubsection subsubsec_datatype_usage_transfer Data Transfer (Read and Write) + * Probably the most common use of datatypes is to write or read data from a dataset or attribute. In + * these operations, each data element is transferred from the source to the destination (possibly + * rearranging the order of the elements). Since the source and destination do not need to be + * identical (in other words, one is disk and the other is memory), the transfer requires + * both the format of the source element and the destination element. Therefore, data transfers use two + * datatype objects, for the source and destination. + * + * When data is written, the source is memory and the destination is disk (file). The memory + * datatype describes the format of the data element in the machine memory, and the file datatype + * describes the desired format of the data element on disk. Similarly, when reading, the source + * datatype describes the format of the data element on disk, and the destination datatype describes + * the format in memory. + * + * In the most common cases, the file datatype is the datatype specified when + * the dataset was + * created, and the memory datatype should be the appropriate \Emph{NATIVE} type. + * The examples below show samples of writing data to and reading data from a dataset. The data + * in memory is declared C type ‘int’, and the datatype #H5T_NATIVE_INT corresponds to this + * type. The datatype of the dataset should be of datatype class #H5T_INTEGER. + * + * <em> Writing to a dataset </em> + * \code + * int dset_data[DATA_SIZE]; + * + * status = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset_data); + * \endcode + * + * <em> Reading from a dataset </em> + * \code + * int dset_data[DATA_SIZE]; + * + * status = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, dset_data); + * \endcode + * + * \subsubsection subsubsec_datatype_usage_discover Discovery of Data Format + * The HDF5 Library enables a program to + * determine the datatype class and properties for any + * datatype. In order to discover the storage format of data in a dataset, the datatype is obtained, and + * the properties are determined by queries to the datatype object. The example below shows code + * that analyzes the datatype for an integer and prints out a description of its storage properties + * (byte order, signed, size). + * + * <em> Discovering datatype properties </em> + * \code + * switch (H5Tget_class(type)) { + * case H5T_INTEGER: + * ord = H5Tget_order(type); + * sgn = H5Tget_sign(type); + * printf(“Integer ByteOrder= ”); + * switch (ord) { + * case H5T_ORDER_LE: + * printf(“LE”); + * break; + * case H5T_ORDER_BE: + * printf(“BE”); + * break; + * } + * printf(“ Sign= ”); + * switch (sgn) { + * case H5T_SGN_NONE: + * printf(“false”); + * break; + * case H5T_SGN_2: + * printf(“true”); + * break; + * } + * printf(“ Size= ”); + * sz = H5Tget_size(type); + * printf(“%d”, sz); + * printf(“\n”); + * break; + * case H5T_???? + * ... + * break; + * } + * \endcode + * + * \subsubsection subsubsec_datatype_usage_user Creating and Using User‐defined Datatypes + * Most programs will primarily use the predefined datatypes described above, possibly in + * composite data types such as compound or array datatypes. However, the HDF5 datatype model + * is extremely general; a user program can define a great variety of atomic datatypes (storage + * layouts). In particular, the datatype properties can define signed and unsigned integers of any + * size and byte order, and floating point numbers with different formats, size, and byte order. The + * HDF5 datatype API provides methods to set these properties. + * + * User-defined types can be used to define the layout of data in memory; examples might match + * some platform specific number format or application defined bit-field. The user-defined type can + * also describe data in the file such as an application-defined format. The user-defined types can be + * translated to and from standard types of the same class, as described above. + * + * \subsection subsec_datatype_function Datatype Function Summaries + * @see H5T reference manual provides a reference list of datatype functions, the H5T APIs. + * + * \subsection subsec_datatype_program Programming Model for Datatypes + * The HDF5 Library implements an object-oriented model of datatypes. HDF5 datatypes are + * organized as a logical set of base types, or datatype classes. The HDF5 Library manages + * datatypes as objects. The HDF5 datatype API manipulates the datatype objects through C + * function calls. The figure below shows the abstract view of the datatype object. The table below + * shows the methods (C functions) that operate on datatype objects. New datatypes can be created + * from scratch or copied from existing datatypes. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig5.gif "The datatype object" + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 8. General operations on datatype objects</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref hid_t \ref H5Tcreate (\ref H5T_class_t class, size_t size) + * </td> + * <td> + * Create a new datatype object of datatype class . The following datatype classes care supported + * with this function: + * \li #H5T_COMPOUND + * \li #H5T_OPAQUE + * \li #H5T_ENUM + * \li Other datatypes are created with \ref H5Tcopy(). + * </td> + * </tr> + * <tr> + * <td> + * \ref hid_t \ref H5Tcopy (\ref hid_t type) + * </td> + * <td> + * Obtain a modifiable transient datatype which is a copy of type. If type is a dataset identifier + * then the type returned is a modifiable transient copy of the datatype of the specified dataset. + * </td> + * </tr> + * <tr> + * <td> + * \ref hid_t \ref H5Topen (\ref hid_t location, const char *name, #H5P_DEFAULT) + * </td> + * <td> + * Open a committed datatype. The committed datatype returned by this function is read-only. + * </td> + * </tr> + * <tr> + * <td> + * \ref htri_t \ref H5Tequal (\ref hid_t type1, \ref hid_t type2) + * </td> + * <td> + * Determines if two types are equal. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tclose (\ref hid_t type) + * </td> + * <td> + * Releases resources associated with a datatype obtained from \ref H5Tcopy, \ref H5Topen, or + * \ref H5Tcreate. It is illegal to close an immutable transient datatype (for example, predefined types). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tcommit (\ref hid_t location, const char *name, hid_t type, + * #H5P_DEFAULT, #H5P_DEFAULT, #H5P_DEFAULT) + * </td> + * <td> + * Commit a transient datatype (not immutable) to a file to become a committed datatype. Committed + * datatypes can be shared. + * </td> + * </tr> + * <tr> + * <td> + * \ref htri_t \ref H5Tcommitted (\ref hid_t type) + * </td> + * <td> + * Test whether the datatype is transient or committed (named). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tlock (\ref hid_t type) + * </td> + * <td> + * Make a transient datatype immutable (read-only and not closable). Predefined types are locked. + * </td> + * </tr> + * </table> + * + * In order to use a datatype, the object must be created (\ref H5Tcreate), or a reference obtained by + * cloning from an existing type (\ref H5Tcopy), or opened (\ref H5Topen). In addition, a reference to the + * datatype of a dataset or attribute can be obtained with \ref H5Dget_type or \ref H5Aget_type. For + * composite datatypes a reference to the datatype for members or base types can be obtained + * (\ref H5Tget_member_type, \ref H5Tget_super). When the datatype object is no longer needed, the + * reference is discarded with \ref H5Tclose. + * + * Two datatype objects can be tested to see if they are the same with \ref H5Tequal. This function + * returns true if the two datatype references refer to the same datatype object. However, if two + * datatype objects define equivalent datatypes (the same datatype class and datatype properties), + * they will not be considered ‘equal’. + * + * A datatype can be written to the file as a first class object (\ref H5Tcommit). This is a committed + * datatype and can be used in thesame way as any other datatype. + * + * \subsubsection subsubsec_datatype_program_discover Discovery of Datatype Properties + * Any HDF5 datatype object can be queried to discover all of its datatype properties. For each + * datatype class, there are a set of API functions to retrieve the datatype properties for this class. + * + * <h4>Properties of Atomic Datatypes</h4> + * Table 9 lists the functions to discover the properties of atomic datatypes. Table 10 lists the + * queries relevant to specific numeric types. Table 11 gives the properties for atomic string + * datatype, and Table 12 gives the property of the opaque datatype. + * + * <table> + * <caption align=top>Table 9. Functions to discover properties of atomic datatypes</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref H5T_class_t \ref H5Tget_class (\ref hid_t type) + * </td> + * <td> + * The datatype class: #H5T_INTEGER, #H5T_FLOAT, #H5T_STRING, #H5T_BITFIELD, #H5T_OPAQUE, #H5T_COMPOUND, + * #H5T_REFERENCE, #H5T_ENUM, #H5T_VLEN, #H5T_ARRAY + * </td> + * </tr> + * <tr> + * <td> + * size_t \ref H5Tget_size (\ref hid_t type) + * </td> + * <td> + * The total size of the element in bytes, including padding which may appear on either side of the + * actual value. + * </td> + * </tr> + * <tr> + * <td> + * \ref H5T_order_t \ref H5Tget_order (\ref hid_t type) + * </td> + * <td> + * The byte order describes how the bytes of the datatype are laid out in memory. If the lowest memory + * address contains the least significant byte of the datum then it is said to be little-endian or + * #H5T_ORDER_LE. If the bytes are in the opposite order then they are said to be big-endianor #H5T_ORDER_BE. + * </td> + * </tr> + * <tr> + * <td> + * size_t \ref H5Tget_precision (\ref hid_t type) + * </td> + * <td> + * The precision property identifies the number of significant bits of a datatype and the offset property + * (defined below) identifies its location. Some datatypes occupy more bytes than what is needed to store + * the value. For instance, a short on a Cray is 32 significant bits in an eight-byte field. + * </td> + * </tr> + * <tr> + * <td> + * int \ref H5Tget_offset (\ref hid_t type) + * </td> + * <td> + * The offset property defines the bit location of the least significant bit of a bit field whose length + * is precision. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tget_pad (\ref hid_t type, \ref H5T_pad_t *lsb, \ref H5T_pad_t *msb) + * </td> + * <td> + * Padding is the bits of a data element which are not significant as defined by the precision and offset + * properties. Padding in the low-numbered bits is lsb padding and padding in the high-numbered bits is msb + * padding. Padding bits can be set to zero (#H5T_PAD_ZERO) or one (#H5T_PAD_ONE). + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 10. Functions to discover properties of atomic datatypes</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref H5T_sign_t \ref H5Tget_sign (\ref hid_t type) + * </td> + * <td> + * (INTEGER)Integer data can be signed two’s complement (#H5T_SGN_2) or unsigned (#H5T_SGN_NONE). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tget_fields (\ref hid_t type, size_t *spos, size_t *epos, size_t *esize, + * size_t*mpos, size_t *msize) + * </td> + * <td> + * (FLOAT)A floating-point data element has bit fields which are the exponent and mantissa as well as a + * mantissa sign bit. These properties define the location (bit position of least significant bit of the + * field) and size (in bits) of each field. The sign bit is always of length one and none of the fields + * are allowed to overlap. + * </td> + * </tr> + * <tr> + * <td> + * size_t \ref H5Tget_ebias (\ref hid_t type) + * </td> + * <td> + * (FLOAT)A floating-point data element has bit fields which are the exponent and + * mantissa as well as a mantissa sign bit. These properties define the location (bit + * position of least significant bit of the field) and size (in bits) of + * each field. The sign bit is always of length one and none of the + * fields are allowed to overlap. + * </td> + * </tr> + * <tr> + * <td> + * \ref H5T_norm_t \ref H5Tget_norm (\ref hid_t type) + * </td> + * <td> + * (FLOAT)This property describes the normalization method of the mantissa. + * <ul><li>#H5T_NORM_MSBSET: the mantissa is shifted left (if non-zero) until the first bit + * after the radix point is set and the exponent is adjusted accordingly. All bits of the + * mantissa after the radix point are stored. </li> + * <li>#H5T_NORM_IMPLIED: the mantissa is shifted left \(if non-zero) until the first + * bit after the radix point is set and the exponent is adjusted accordingly. The first + * bit after the radix point is not stored since it’s always set. </li> + * <li>#H5T_NORM_NONE: the fractional part of the mantissa is stored without normalizing it.</li></ul> + * </td> + * </tr> + * <tr> + * <td> + * \ref H5T_pad_t \ref H5Tget_inpad (\ref hid_t type) + * </td> + * <td> + * (FLOAT)If any internal bits (that is, bits between the sign bit, the mantissa field, + * and the exponent field but within the precision field) are unused, then they will be + * filled according to the value of this property. The padding can be: + * #H5T_PAD_BACKGROUND, #H5T_PAD_ZERO,or #H5T_PAD_ONE. + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 11. Functions to discover properties of atomic string datatypes</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref H5T_cset_t \ref H5Tget_cset (\ref hid_t type) + * </td> + * <td> + * Two character sets are currently supported: + * ASCII (#H5T_CSET_ASCII) and UTF-8 (#H5T_CSET_UTF8). + * </td> + * </tr> + * <tr> + * <td> + * \ref H5T_str_t \ref H5Tget_strpad (\ref hid_t type) + * </td> + * <td> + * The string datatype has a fixed length, but the string may be shorter than the length. + * This property defines the storage mechanism for the left over bytes. The options are: + * \li #H5T_STR_NULLTERM + * \li #H5T_STR_NULLPAD + * \li #H5T_STR_SPACEPAD. + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 12. Functions to discover properties of atomic opaque datatypes</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * char* \ref H5Tget_tag(\ref hid_t type_id) + * </td> + * <td> + * A user-defined string. + * </td> + * </tr> + * </table> + * + * <h4>Properties of Composite Datatypes</h4> + * The composite datatype classes can also be analyzed to discover their datatype properties and the + * datatypes that are members or base types of the composite datatype. The member or base type + * can, in turn, be analyzed. The table below lists the functions that can access the datatype + * properties of the different composite datatypes. + * + * <table> + * <caption align=top>Table 13. Functions to discover properties of composite datatypes</caption> + * <tr> + * <th> + * API Function + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * int \ref H5Tget_nmembers(\ref hid_t type_id) + * </td> + * <td> + * (COMPOUND)The number of fields in the compound datatype. + * </td> + * </tr> + * <tr> + * <td> + * \ref H5T_class_t \ref H5Tget_member_class (\ref hid_t cdtype_id, unsigned member_no) + * </td> + * <td> + * (COMPOUND)The datatype class of compound datatype member member_no. + * </td> + * </tr> + * <tr> + * <td> + * char* \ref H5Tget_member_name (\ref hid_t type_id, unsigned field_idx) + * </td> + * <td> + * (COMPOUND)The name of field field_idx of a compound datatype. + * </td> + * </tr> + * <tr> + * <td> + * size_t \ref H5Tget_member_offset (\ref hid_t type_id, unsigned memb_no) + * </td> + * <td> + * (COMPOUND)The byte offset of the beginning of a field within a compound datatype. + * </td> + * </tr> + * <tr> + * <td> + * \ref hid_t \ref H5Tget_member_type (\ref hid_t type_id, unsigned field_idx) + * </td> + * <td> + * (COMPOUND)The datatype of the specified member. + * </td> + * </tr> + * <tr> + * <td> + * int \ref H5Tget_array_ndims (\ref hid_t adtype_id) + * </td> + * <td> + * (ARRAY)The number of dimensions (rank) of the array datatype object. + * </td> + * </tr> + * <tr> + * <td> + * int \ref H5Tget_array_dims (\ref hid_t adtype_id, hsize_t *dims[]) + * </td> + * <td> + * (ARRAY)The sizes of the dimensions and the dimension permutations of the array datatype object. + * </td> + * </tr> + * <tr> + * <td> + * \ref hid_t \ref H5Tget_super(\ref hid_t type) + * </td> + * <td> + * (ARRAY, VL, ENUM)The base datatype from which the datatype type is derived. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tenum_nameof(\ref hid_t type, const void *value, char *name, size_t size) + * </td> + * <td> + * (ENUM)The symbol name that corresponds to the specified value of the enumeration datatype. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tenum_valueof(\ref hid_t type, const char *name, void *value) + * </td> + * <td> + * (ENUM)The value that corresponds to the specified name of the enumeration datatype. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tget_member_value (\ref hid_t type unsigned memb_no, void *value) + * </td> + * <td> + * (ENUM)The value of the enumeration datatype member memb_no. + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_program_define Definition of Datatypes + * The HDF5 library enables user programs to create and modify datatypes. The essential steps are: + * <ul><li>1. Create a new datatype object of a specific composite datatype class, or copy an existing + * atomic datatype object</li> + * <li>2. Set properties of the datatype object</li> + * <li>3. Use the datatype object</li> + * <li>4. Close the datatype object</li></ul> + * + * To create a user-defined atomic datatype, the procedure is to clone a predefined datatype of the + * appropriate datatype class (\ref H5Tcopy), and then set the datatype properties appropriate to the + * datatype class. The table below shows how to create a datatype to describe a 1024-bit unsigned + * integer. + * + * <em>Create a new datatype</em> + * \code + * hid_t new_type = H5Tcopy (H5T_NATIVE_INT); + * + * H5Tset_precision(new_type, 1024); + * H5Tset_sign(new_type, H5T_SGN_NONE); + * \endcode + * + * Composite datatypes are created with a specific API call for each datatype class. The table below + * shows the creation method for each datatype class. A newly created datatype cannot be used until the + * datatype properties are set. For example, a newly created compound datatype has no members and cannot + * be used. + * + * <table> + * <caption align=top>Table 14. Functions to create each datatype class</caption> + * <tr> + * <th> + * Datatype Class + * </th> + * <th> + * Function to Create + * </th> + * </tr> + * <tr> + * <td> + * COMPOUND + * </td> + * <td> + * #H5Tcreate + * </td> + * </tr> + * <tr> + * <td> + * OPAQUE + * </td> + * <td> + * #H5Tcreate + * </td> + * </tr> + * <tr> + * <td> + * ENUM + * </td> + * <td> + * #H5Tenum_create + * </td> + * </tr> + * <tr> + * <td> + * ARRAY + * </td> + * <td> + * #H5Tarray_create + * </td> + * </tr> + * <tr> + * <td> + * VL + * </td> + * <td> + * #H5Tvlen_create + * </td> + * </tr> + * </table> + * + * Once the datatype is created and the datatype properties set, the datatype object can be used. + * + * Predefined datatypes are defined by the library during initialization using the same mechanisms + * as described here. Each predefined datatype is locked (\ref H5Tlock), so that it cannot be changed or + * destroyed. User-defined datatypes may also be locked using \ref H5Tlock. + * + * <h4>User-defined Atomic Datatypes</h4> + * Table 15 summarizes the API methods that set properties of atomic types. Table 16 shows + * properties specific to numeric types, Table 17 shows properties specific to the string datatype + * class. Note that offset, pad, etc. do not apply to strings. Table 18 shows the specific property of + * the OPAQUE datatype class. + * + * <table> + * <caption align=top>Table 15. API methods that set properties of atomic datatypes</caption> + * <tr> + * <th> + * Functions + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_size (\ref hid_t type, size_t size) + * </td> + * <td> + * Set the total size of the element in bytes. This includes padding which may appear on either + * side of the actual value. If this property is reset to a smaller value which would cause the + * significant part of the data to extend beyond the edge of the datatype, then the offset property + * is decremented a bit at a time. If the offset reaches zero and the significant part of the data + * still extends beyond the edge of the datatype then the precision property is decremented a bit at + * a time. Decreasing the size of a datatype may fail if the #H5T_FLOAT bit fields would extend beyond + * the significant part of the type. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_order (\ref hid_t type, \ref H5T_order_t order) + * </td> + * <td> + * Set the byte order to little-endian (#H5T_ORDER_LE) or big-endian (#H5T_ORDER_BE). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_precision (\ref hid_t type, size_t precision) + * </td> + * <td> + * Set the number of significant bits of a datatype. The offset property (defined below) identifies + * its location. The size property defined above represents the entire size (in bytes) of the datatype. + * If the precision is decreased then padding bits are inserted on the MSB side of the significant + * bits (this will fail for #H5T_FLOAT types if it results in the sign,mantissa, or exponent bit field + * extending beyond the edge of the significant bit field). On the other hand, if the precision is + * increased so that it “hangs over” the edge of the total size then the offset property is decremented + * a bit at a time. If the offset reaches zero and the significant bits still hang over the edge, then + * the total size is increased a byte at a time. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_offset (\ref hid_t type, size_t offset) + * </td> + * <td> + * Set the bit location of the least significant bit of a bit field whose length is precision. The + * bits of the entire data are numbered beginning at zero at the least significant bit of the least + * significant byte (the byte at the lowest memory address for a little-endian type or the byte at + * the highest address for a big-endian type). The offset property defines the bit location of the + * least significant bit of a bit field whose length is precision. If the offset is increased so the + * significant bits “hang over” the edge of the datum, then the size property is automatically incremented. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_pad (\ref hid_t type, \ref H5T_pad_t lsb, \ref H5T_pad_t msb) + * </td> + * <td> + * Set the padding to zeros (#H5T_PAD_ZERO) or ones (#H5T_PAD_ONE). Padding is the bits of a + * data element which are not significant as defined by the precision and offset properties. Padding + * in the low-numbered bits is lsb padding and padding in the high-numbered bits is msb padding. + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 16. API methods that set properties of numeric datatypes</caption> + * <tr> + * <th> + * Functions + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_sign (\ref hid_t type, \ref H5T_sign_t sign) + * </td> + * <td> + * (INTEGER)Integer data can be signed two’s complement (#H5T_SGN_2) or unsigned (#H5T_SGN_NONE). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_fields (\ref hid_t type, size_t spos, size_t epos, size_t esize, + * size_t mpos, size_t msize) + * </td> + * <td> + * (FLOAT)Set the properties define the location (bit position of least significant bit of the field) + * and size (in bits) of each field. The sign bit is always of length one and none of the fields are + * allowed to overlap. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_ebias (\ref hid_t type, size_t ebias) + * </td> + * <td> + * (FLOAT)The exponent is stored as a non-negative value which is ebias larger than the true exponent. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_norm (\ref hid_t type, \ref H5T_norm_t norm) + * </td> + * <td> + * (FLOAT)This property describes the normalization method of the mantissa. + * <ul><li>#H5T_NORM_MSBSET: the mantissa is shifted left (if non-zero) until the first bit + * after theradix point is set and the exponent is adjusted accordingly. All bits of the + * mantissa after the radix point are stored. </li> + * <li>#H5T_NORM_IMPLIED: the mantissa is shifted left (if non-zero) until the first bit + * after the radix point is set and the exponent is adjusted accordingly. The first bit after + * the radix point is not stored since it is always set. </li> + * <li>#H5T_NORM_NONE: the fractional part of the mantissa is stored without normalizing it.</li></ul> + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_inpad (\ref hid_t type, \ref H5T_pad_t inpad) + * </td> + * <td> + * (FLOAT) +If any internal bits (that is, bits between the sign bit, the mantissa field, +and the exponent field but within the precision field) are unused, then they will be +filled according to the value of this property. The padding can be: + * \li #H5T_PAD_BACKGROUND + * \li #H5T_PAD_ZERO + * \li #H5T_PAD_ONE + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 17. API methods that set properties of string datatypes</caption> + * <tr> + * <th> + * Functions + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_size (\ref hid_t type, size_t size) + * </td> + * <td> + * Set the length of the string, in bytes. The precision is automatically set to 8*size. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_precision (\ref hid_t type, size_t precision) + * </td> + * <td> + * The precision must be a multiple of 8. + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_cset (\ref hid_t type_id, \ref H5T_cset_t cset) + * </td> + * <td> + * Two character sets are currently supported: + * \li ASCII (#H5T_CSET_ASCII) + * \li UTF-8 (#H5T_CSET_UTF8). + * </td> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_strpad (\ref hid_t type_id, H5T_str_t strpad) + * </td> + * <td> + * The string datatype has a fixed length, but the string may be shorter than the length. This + * property defines the storage mechanism for the left over bytes. The method used to store + * character strings differs with the programming language: + * \li C usually null terminates strings + * \li Fortran left-justifies and space-pads strings + * + * Valid string padding values, as passed in the parameter strpad, are as follows: + * \li #H5T_STR_NULLTERM: Null terminate (as C does) + * \li #H5T_STR_NULLPAD: Pad with zeros + * \li #H5T_STR_SPACEPAD: Pad with spaces (as FORTRAN does) + * </td> + * </tr> + * </table> + * + * <table> + * <caption align=top>Table 18. API methods that set properties of opaque datatypes</caption> + * <tr> + * <th> + * Functions + * </th> + * <th> + * Description + * </th> + * </tr> + * <tr> + * <td> + * \ref herr_t \ref H5Tset_tag (\ref hid_t type_id, const char *tag) + * </td> + * <td> + * Tags the opaque datatype type_id with an ASCII identifier tag. + * </td> + * </tr> + * </table> + * + * <h4>Examples</h4> + * The example below shows how to create a 128-bit little-endian signed integer type. Increasing + * the precision of a type automatically increases the total size. Note that the proper + * procedure is to begin from a type of the intended datatype class which in this case is a + * NATIVE INT. + * + * <em>Create a new 128-bit little-endian signed integer datatype</em> + * \code + * hid_t new_type = H5Tcopy (H5T_NATIVE_INT); + * H5Tset_precision (new_type, 128); + * H5Tset_order (new_type, H5T_ORDER_LE); + * \endcode + * + * The figure below shows the storage layout as the type is defined. The \ref H5Tcopy creates a + * datatype that is the same as #H5T_NATIVE_INT. In this example, suppose this is a 32-bit + * big-endian number (Figure a). The precision is set to 128 bits, which automatically extends + * the size to 8 bytes (Figure b). Finally, the byte order is set to little-endian (Figure c). + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig6.gif "The storage layout for a new 128-bit little-endian signed integer datatype" + * </td> + * </tr> + * </table> + * + * The significant bits of a data element can be offset from the beginning of the memory for that + * element by an amount of padding. The offset property specifies the number of bits of padding + * that appear to the “right of” the value. The table and figure below show how a 32-bit unsigned + * integer with 16-bits of precision having the value 0x1122 will be laid out in memory. + * + * <table> + * <caption align=top>Table 19. Memory Layout for a 32-bit unsigned integer</caption> + * <tr> + * <th> + * Byte Position + * </th> + * <th> + * Big-Endian<br />Offset=0 + * </th> + * <th> + * Big-Endian<br />Offset=16 + * </th> + * <th> + * Little-Endian<br />Offset=0 + * </th> + * <th> + * Little-Endian<br />Offset=16 + * </th> + * </tr> + * <tr> + * <td> + * 0: + * </td> + * <td> + * [pad] + * </td> + * <td> + * [0x11] + * </td> + * <td> + * [0x22] + * </td> + * <td> + * [pad] + * </td> + * </tr> + * <tr> + * <td> + * 1: + * </td> + * <td> + * [pad] + * </td> + * <td> + * [0x22] + * </td> + * <td> + * [0x11] + * </td> + * <td> + * [pad] + * </td> + * </tr> + * <tr> + * <td> + * 2: + * </td> + * <td> + * [0x11] + * </td> + * <td> + * [pad] + * </td> + * <td> + * [pad] + * </td> + * <td> + * [0x22] + * </td> + * </tr> + * <tr> + * <td> + * 3: + * </td> + * <td> + * [0x22] + * </td> + * <td> + * [pad] + * </td> + * <td> + * [pad] + * </td> + * <td> + * [0x11] + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig7.gif "Memory Layout for a 32-bit unsigned integer" + * </td> + * </tr> + * </table> + * + * If the offset is incremented then the total size is incremented also if necessary to prevent + * significant bits of the value from hanging over the edge of the datatype. + * + * The bits of the entire data are numbered beginning at zero at the least significant bit of the least + * significant byte (the byte at the lowest memory address for a little-endian type or the byte at the + * highest address for a big-endian type). The offset property defines the bit location of the least + * significant bit of a bit field whose length is precision. If the offset is increased so the significant + * bits “hang over” the edge of the datum, then the size property is automatically incremented. + * + * To illustrate the properties of the integer datatype class, the example below shows how to create + * a user-defined datatype that describes a 24-bit signed integer that starts on the third bit of a 32-bit + * word. The datatype is specialized from a 32-bit integer, the precision is set to 24 bits, and the + * offset is set to 3. + * + * <em>A user-defined datatype with a 24-bit signed integer</em> + * \code + * hid_t dt; + * + * dt = H5Tcopy(H5T_SDT_I32LE); + * H5Tset_precision(dt, 24); + * H5Tset_offset(dt,3); + * H5Tset_pad(dt, H5T_PAD_ZERO, H5T_PAD_ONE); + * \endcode + * + * The figure below shows the storage layout for a data element. Note that the unused bits in the + * offset will be set to zero and the unused bits at the end will be set to one, as specified in the + * \ref H5Tset_pad call. + * <table> + * <tr> + * <td> + * \image html Dtypes_fig8.gif "A user-defined integer datatype with a range of -1,048,583 to 1,048,584" + * </td> + * </tr> + * </table> + * + * To illustrate a user-defined floating point number, the example below shows how to create a 24-bit + * floating point number that starts 5 bits into a 4 byte word. The floating point number is defined to + * have a mantissa of 19 bits (bits 5-23), an exponent of 3 bits (25-27), and the sign bit is bit 28. + * (Note that this is an illustration of what can be done and is not necessarily a floating point + * format that a user would require.) + * + * <em>A user-defined datatype with a 24-bit floating point datatype</em> + * \code + * hid_t dt; + * + * dt = H5Tcopy(H5T_SDT_F32LE); + * H5Tset_precision(dt, 24); + * H5Tset_fields (dt, 28, 25, 3, 5, 19); + * H5Tset_pad(dt, H5T_PAD_ZERO, H5T_PAD_ONE); + * H5Tset_inpad(dt, H5T_PAD_ZERO); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig9.gif "A user-defined floating point datatype" + * </td> + * </tr> + * </table> + * The figure above shows the storage layout of a data element for this datatype. Note that there is + * an unused bit (24) between the mantissa and the exponent. This bit is filled with the inpad value + * which in this case is 0. + * + * The sign bit is always of length one and none of the fields are allowed to overlap. When + * expanding a floating-point type one should set the precision first; when decreasing the size one + * should set the field positions and sizes first. + * + * <h4>Composite Datatypes</h4> + * All composite datatypes must be user-defined; there are no predefined composite datatypes. + * + * <h4>Compound Datatypes</h4> + * The subsections below describe how to create a compound datatype and how to write and read + * data of a compound datatype. + * + * <h4>Defining Compound Datatypes</h4> + * + * Compound datatypes are conceptually similar to a C struct or Fortran derived types. The + * compound datatype defines a contiguous sequence of bytes, which are formatted using one up to + * 2^16 datatypes (members). A compound datatype may have any number of members, in any + * order, and the members may have any datatype, including compound. Thus, complex nested + * compound datatypes can be created. The total size of the compound datatype is greater than or + * equal to the sum of the size of its members, up to a maximum of 2^32 bytes. HDF5 does not + * support datatypes with distinguished records or the equivalent of C unions or Fortran + * EQUIVALENCE statements. + * + * Usually a C struct or Fortran derived type will be defined to hold a data point in memory, and the + * offsets of the members in memory will be the offsets of the struct members from the beginning + * of an instance of the struct. The HDF5 C library provides a macro #HOFFSET (s,m)to calculate + * the member’s offset. The HDF5 Fortran applications have to calculate offsets by using sizes of + * members datatypes and by taking in consideration the order of members in the Fortran derived type. + * \code + * HOFFSET(s,m) + * \endcode + * This macro computes the offset of member m within a struct s + * \code + * offsetof(s,m) + * \endcode + * This macro defined in stddef.h does exactly the same thing as the HOFFSET()macro. + * + * Note for Fortran users: Offsets of Fortran structure members correspond to the offsets within a + * packed datatype (see explanation below) stored in an HDF5 file. + * + * Each member of a compound datatype must have a descriptive name which is the key used to + * uniquely identify the member within the compound datatype. A member name in an HDF5 + * datatype does not necessarily have to be the same as the name of the member in the C struct or + * Fortran derived type, although this is often the case. Nor does one need to define all members of + * the C struct or Fortran derived type in the HDF5 compound datatype (or vice versa). + * + * Unlike atomic datatypes which are derived from other atomic datatypes, compound datatypes are + * created from scratch. First, one creates an empty compound datatype and specifies its total size. + * Then members are added to the compound datatype in any order. Each member type is inserted + * at a designated offset. Each member has a name which is the key used to uniquely identify the + * member within the compound datatype. + * + * The example below shows a way of creating an HDF5 C compound datatype to describe a + * complex number. This is a structure with two components, “real” and “imaginary”, and each + * component is a double. An equivalent C struct whose type is defined by the complex_tstruct is + * shown. + * + * <em>A compound datatype for complex numbers in C</em> + * \code + * typedef struct { + * double re; //real part + * double im; //imaginary part + * } complex_t; + * + * hid_t complex_id = H5Tcreate (H5T_COMPOUND, sizeof (complex_t)); + * H5Tinsert (complex_id, “real”, HOFFSET(complex_t,re), + * H5T_NATIVE_DOUBLE); + * H5Tinsert (complex_id, “imaginary”, HOFFSET(complex_t,im), + * H5T_NATIVE_DOUBLE); + * \endcode + * + * The example below shows a way of creating an HDF5 Fortran compound datatype to describe a + * complex number. This is a Fortran derived type with two components, “real” and “imaginary”, + * and each component is DOUBLE PRECISION. An equivalent Fortran TYPE whose type is defined + * by the TYPE complex_t is shown. + * + * <em>A compound datatype for complex numbers in Fortran</em> + * \code + * TYPE complex_t + * DOUBLE PRECISION re ! real part + * DOUBLE PRECISION im; ! imaginary part + * END TYPE complex_t + * + * CALL h5tget_size_f(H5T_NATIVE_DOUBLE, re_size, error) + * CALL h5tget_size_f(H5T_NATIVE_DOUBLE, im_size, error) + * complex_t_size = re_size + im_size + * CALL h5tcreate_f(H5T_COMPOUND_F, complex_t_size, type_id) + * offset = 0 + * CALL h5tinsert_f(type_id, “real”, offset, H5T_NATIVE_DOUBLE, error) + * offset = offset + re_size + * CALL h5tinsert_f(type_id, “imaginary”, offset, H5T_NATIVE_DOUBLE, error) + * \endcode + * + * Important Note: The compound datatype is created with a size sufficient to hold all its members. + * In the C example above, the size of the C struct and the #HOFFSET macro are used as a + * convenient mechanism to determine the appropriate size and offset. Alternatively, the size and + * offset could be manually determined: the size can be set to 16 with “real” at offset 0 and + * “imaginary” at offset 8. However, different platforms and compilers have different sizes for + * “double” and may have alignment restrictions which require additional padding within the + * structure. It is much more portable to use the #HOFFSET macro which assures that the values will + * be correct for any platform. + * + * The figure below shows how the compound datatype would be laid out assuming that + * NATIVE_DOUBLE are 64-bit numbers and that there are no alignment requirements. The total + * size of the compound datatype will be 16 bytes, the “real” component will start at byte 0, and + * “imaginary” will start at byte 8. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig10.gif "Layout of a compound datatype" + * </td> + * </tr> + * </table> + * + * The members of a compound datatype may be any HDF5 datatype including the compound, + * array, and variable-length (VL) types. The figure and example below show the memory layout + * and code which creates a compound datatype composed of two complex values, and each + * complex value is also a compound datatype as in the figure above. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig11.gif "Layout of a compound datatype nested in a compound datatype" + * </td> + * </tr> + * </table> + * + * <em>Code for a compound datatype nested in a compound datatype</em> + * \code + * typedef struct { + * complex_t x; + * complex_t y; + * } surf_t; + * + * hid_t complex_id, surf_id; // hdf5 datatypes + * + * complex_id = H5Tcreate (H5T_COMPOUND, sizeof(complex_t)); + * H5Tinsert (complex_id, “re”, HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE); + * H5Tinsert (complex_id, “im”, HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE); + * + * surf_id = H5Tcreate (H5T_COMPOUND, sizeof(surf_t)); + * H5Tinsert (surf_id, “x”, HOFFSET(surf_t, x), complex_id); + * H5Tinsert (surf_id, “y”, HOFFSET(surf_t, y), complex_id); + * \endcode + * + * Note that a similar result could be accomplished by creating a compound datatype and inserting + * four fields. See the figure below. This results in the same layout as the figure above. The difference + * would be how the fields are addressed. In the first case, the real part of ‘y’ is called ‘y.re’; + * in the second case it is ‘y-re’. + * + * <em>Another compound datatype nested in a compound datatype</em> + * \code + * typedef struct { + * complex_t x; + * complex_t y; + * } surf_t; + * + * hid_t surf_id = H5Tcreate (H5T_COMPOUND, sizeof(surf_t)); + * H5Tinsert (surf_id, “x-re”, HOFFSET(surf_t, x.re), H5T_NATIVE_DOUBLE); + * H5Tinsert (surf_id, “x-im”, HOFFSET(surf_t, x.im), H5T_NATIVE_DOUBLE); + * H5Tinsert (surf_id, “y-re”, HOFFSET(surf_t, y.re), H5T_NATIVE_DOUBLE); + * H5Tinsert (surf_id, “y-im”, HOFFSET(surf_t, y.im), H5T_NATIVE_DOUBLE); + * \endcode + * + * The members of a compound datatype do not always fill all the bytes. The #HOFFSET macro + * assures that the members will be laid out according to the requirements of the platform and + * language. The example below shows an example of a C struct which requires extra bytes of + * padding on many platforms. The second element, ‘b’, is a 1-byte character followed by an 8 byte + * double, ‘c’. On many systems, the 8-byte value must be stored on a 4-or 8-byte boundary. This + * requires the struct to be larger than the sum of the size of its elements. + * + * In the example below, sizeof and #HOFFSET are used to assure that the members are inserted at + * the correct offset to match the memory conventions of the platform. The figure below shows how + * this data element would be stored in memory, assuming the double must start on a 4-byte + * boundary. Notice the extra bytes between ‘b’ and ‘c’. + * + * <em>A compound datatype that requires padding</em> + * \code + * typedef struct { + * int a; + * char b; + * double c; + * } s1_t; + * + * hid_t s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + * H5Tinsert (s1_tid, “x-im”, HOFFSET(s1_t, a), H5T_NATIVE_INT); + * H5Tinsert (s1_tid, “y-re”, HOFFSET(s1_t, b), H5T_NATIVE_CHAR); + * H5Tinsert (s1_tid, “y-im”, HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig12.gif "Memory layout of a compound datatype that requires padding" + * </td> + * </tr> + * </table> + * + * However, data stored on disk does not require alignment, so unaligned versions of compound + * data structures can be created to improve space efficiency on disk. These unaligned compound + * datatypes can be created by computing offsets by hand to eliminate inter-member padding, or the + * members can be packed by calling #H5Tpack (which modifies a datatype directly, so it is usually + * preceded by a call to #H5Tcopy). + * + * The example below shows how to create a disk version of the compound datatype from the + * figure above in order to store data on disk in as compact a form as possible. Packed compound + * datatypes should generally not be used to describe memory as they may violate alignment + * constraints for the architecture being used. Note also that using a packed datatype for disk + * storage may involve a higher data conversion cost. + * + * <em>Create a packed compound datatype in C</em> + * \code + * hid_t s2_tid = H5Tcopy (s1_tid); + * H5Tpack (s2_tid); + * \endcode + * + * The example below shows the sequence of Fortran calls to create a packed compound datatype. + * An HDF5 Fortran compound datatype never describes a compound datatype in memory and + * compound data is ALWAYS written by fields as described in the next section. Therefore packing + * is not needed unless the offset of each consecutive member is not equal to the sum of the sizes of + * the previous members. + * + * <em>Create a packed compound datatype in Fortran</em> + * \code + * CALL h5tcopy_f(s1_id, s2_id, error) + * CALL h5tpack_f(s2_id, error) + * \endcode + * + * <h4>Creating and Writing Datasets with Compound Datatypes</h4> + * + * Creating datasets with compound datatypes is similar to creating datasets with any other HDF5 + * datatypes. But writing and reading may be different since datasets that have compound datatypes + * can be written or read by a field (member) or subsets of fields (members). The compound + * datatype is the only composite datatype that supports “sub-setting” by the elements the datatype + * is built from. + * + * The example below shows a C example of creating and writing a dataset with a compound + * datatype. + * + * + * <em>Create and write a dataset with a compound datatype in C</em> + * \code + * typedef struct s1_t { + * int a; + * float b; + * double c; + * } s1_t; + * + * s1_t data[LENGTH]; + * + * // Initialize data + * for (i = 0; i < LENGTH; i++) { + * data[i].a = i; + * data[i].b = i*i; + * data[i].c = 1./(i+1); + * } + * + * ... + * + * s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + * H5Tinsert(s1_tid, “a_name”, HOFFSET(s1_t, a), H5T_NATIVE_INT); + * H5Tinsert(s1_tid, “b_name”, HOFFSET(s1_t, b), H5T_NATIVE_FLOAT); + * H5Tinsert(s1_tid, “c_name”, HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + * + * ... + * + * dataset_id = H5Dcreate(file_id, “SDScompound.h5”, s1_t, + * space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * H5Dwrite (dataset_id, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * The example below shows the content of the file written on a little-endian machine. + * <em>Create and write a little-endian dataset with a compound datatype in C</em> + * \code + * HDF5 “SDScompound.h5” { + * GROUP “/” { + * DATASET “ArrayOfStructures” { + * DATATYPE H5T_COMPOUND { + * H5T_STD_I32LE “a_name”; + * H5T_IEEE_F32LE “b_name”; + * H5T_IEEE_F64LE “c_name”; + * } + * DATASPACE SIMPLE { ( 3 ) / ( 3 ) } + * DATA { + * (0): { + * 0, + * 0, + * 1 + * }, + * (1): { + * 0, + * 1, + * 0.5 + * }, + * (2): { + * 0, + * 4, + * 0.333333 + * } + * } + * } + * } + * } + * \endcode + * + * It is not necessary to write the whole data at once. Datasets with compound datatypes can be + * written by field or by subsets of fields. In order to do this one has to remember to set the transfer + * property of the dataset using the H5Pset_preserve call and to define the memory datatype that + * corresponds to a field. The example below shows how float and double fields are written to the + * dataset. + * + * <em>Writing floats and doubles to a dataset</em> + * \code + * typedef struct sb_t { + * float b; + * double c; + * } sb_t; + * + * typedef struct sc_t { + * float b; + * double c; + * } sc_t; + * sb_t data1[LENGTH]; + * sc_t data2[LENGTH]; + * + * // Initialize data + * for (i = 0; i < LENGTH; i++) { + * data1.b = i * i; + * data2.c = 1./(i + 1); + * } + * + * ... + * + * // Create dataset as in example 15 + * + * ... + * + * // Create memory datatypes corresponding to float + * // and double datatype fields + * + * sb_tid = H5Tcreate (H5T_COMPOUND, sizeof(sb_t)); + * H5Tinsert(sb_tid, “b_name”, HOFFSET(sb_t, b), H5T_NATIVE_FLOAT); + * sc_tid = H5Tcreate (H5T_COMPOUND, sizeof(sc_t)); + * H5Tinsert(sc_tid, “c_name”, HOFFSET(sc_t, c), H5T_NATIVE_DOUBLE); + * + * ... + * + * // Set transfer property + * xfer_id = H5Pcreate(H5P_DATASET_XFER); + * H5Pset_preserve(xfer_id, 1); + * H5Dwrite (dataset_id, sb_tid, H5S_ALL, H5S_ALL, xfer_id, data1); + * H5Dwrite (dataset_id, sc_tid, H5S_ALL, H5S_ALL, xfer_id, data2); + * \endcode + * + * The figure below shows the content of the file written on a little-endian machine. Only float and + * double fields are written. The default fill value is used to initialize the unwritten integer field. + * <em>Writing floats and doubles to a dataset on a little-endian system</em> + * \code + * HDF5 “SDScompound.h5” { + * GROUP “/” { + * DATASET “ArrayOfStructures” { + * DATATYPE H5T_COMPOUND { + * H5T_STD_I32LE “a_name”; + * H5T_IEEE_F32LE “b_name”; + * H5T_IEEE_F64LE “c_name”; + * } + * DATASPACE SIMPLE { ( 3 ) / ( 3 ) } + * DATA { + * (0): { + * 0, + * 0, + * 1 + * }, + * (1): { + * 0, + * 1, + * 0.5 + * }, + * (2): { + * 0, + * 4, + * 0.333333 + * } + * } + * } + * } + * } + * \endcode + * + * The example below contains a Fortran example that creates and writes a dataset with a + * compound datatype. As this example illustrates, writing and reading compound datatypes in + * Fortran is always done by fields. The content of the written file is the same as shown in the + * example above. + * <em>Create and write a dataset with a compound datatype in Fortran</em> + * \code + * ! One cannot write an array of a derived datatype in + * ! Fortran. + * TYPE s1_t + * INTEGER a + * REAL b + * DOUBLE PRECISION c + * END TYPE s1_t + * TYPE(s1_t) d(LENGTH) + * ! Therefore, the following code initializes an array + * ! corresponding to each field in the derived datatype + * ! and writesthose arrays to the dataset + * + * INTEGER, DIMENSION(LENGTH) :: a + * REAL, DIMENSION(LENGTH) :: b + * DOUBLE PRECISION, DIMENSION(LENGTH) :: c + * + * ! Initialize data + * do i = 1, LENGTH + * a(i) = i-1 + * b(i) = (i-1) * (i-1) + * c(i) = 1./i + * enddo + * + * ... + * + * ! Set dataset transfer property to preserve partially + * ! initialized fields during write/read to/from dataset + * ! with compound datatype. + * ! + * CALL h5pcreate_f(H5P_DATASET_XFER_F, plist_id, error) + * CALL h5pset_preserve_f(plist_id, .TRUE., error) + * + * ... + * + * ! + * ! Create compound datatype. + * ! + * ! First calculate total size by calculating sizes of + * ! each member + * ! + * CALL h5tget_size_f(H5T_NATIVE_INTEGER, type_sizei, error) + * CALL h5tget_size_f(H5T_NATIVE_REAL, type_sizer, error) + * CALL h5tget_size_f(H5T_NATIVE_DOUBLE, type_sized, error) + * type_size = type_sizei + type_sizer + type_sized + * CALL h5tcreate_f(H5T_COMPOUND_F, type_size, dtype_id, error) + * ! + * ! Insert members + * ! + * ! + * ! INTEGER member + * ! + * offset = 0 + * CALL h5tinsert_f(dtype_id, “a_name”, offset, H5T_NATIVE_INTEGER, error) + * ! + * ! REAL member + * ! + * offset = offset + type_sizei + * CALL h5tinsert_f(dtype_id, “b_name”, offset, H5T_NATIVE_REAL, error) + * ! + * ! DOUBLE PRECISION member + * ! + * offset = offset + type_sizer + * CALL h5tinsert_f(dtype_id, “c_name”, offset, H5T_NATIVE_DOUBLE, error) + * ! + * ! Create the dataset with compound datatype. + * ! + * CALL h5dcreate_f(file_id, dsetname, dtype_id, dspace_id, &dset_id, error, H5P_DEFAULT_F, + * H5P_DEFAULT_F, H5P_DEFAULT_F) + * ! + * + * ... + * + * ! Create memory types. We have to create a compound + * ! datatype for each member we want to write. + * ! + * CALL h5tcreate_f(H5T_COMPOUND_F, type_sizei, dt1_id, error) + * offset = 0 + * CALL h5tinsert_f(dt1_id, “a_name”, offset, H5T_NATIVE_INTEGER, error) + * ! + * CALL h5tcreate_f(H5T_COMPOUND_F, type_sizer, dt2_id, error) + * offset = 0 + * CALL h5tinsert_f(dt2_id, “b_name”, offset, H5T_NATIVE_REAL, error) + * ! + * CALL h5tcreate_f(H5T_COMPOUND_F, type_sized, dt3_id, error) + * offset = 0 + * CALL h5tinsert_f(dt3_id, “c_name”, offset, H5T_NATIVE_DOUBLE, error) + * ! + * ! Write data by fields in the datatype. Fields order + * ! is not important. + * ! + * CALL h5dwrite_f(dset_id, dt3_id, c, data_dims, error, xfer_prp = plist_id) + * CALL h5dwrite_f(dset_id, dt2_id, b, data_dims, error, xfer_prp = plist_id) + * CALL h5dwrite_f(dset_id, dt1_id, a, data_dims, error, xfer_prp = plist_id) + * \endcode + * + * <h4>Reading Datasets with Compound Datatypes</h4> + * + * Reading datasets with compound datatypes may be a challenge. For general applications there is + * no way to know a priori the corresponding C structure. Also, C structures cannot be allocated on + * the fly during discovery of the dataset’s datatype. For general C, C++, Fortran and Java + * application the following steps will be required to read and to interpret data from the dataset with + * compound datatype: + * \li 1. Get the identifier of the compound datatype in the file with the #H5Dget_type call + * \li 2. Find the number of the compound datatype members with the #H5Tget_nmembers call + * \li 3. Iterate through compound datatype members + * <ul><li>Get member class with the #H5Tget_member_class call</li> + * <li>Get member name with the #H5Tget_member_name call</li> + * <li>Check class type against predefined classes + * <ul><li>#H5T_INTEGER</li> + * <li>#H5T_FLOAT</li> + * <li>#H5T_STRING</li> + * <li>#H5T_BITFIELD</li> + * <li>#H5T_OPAQUE</li> + * <li>#H5T_COMPOUND</li> + * <li>#H5T_REFERENCE</li> + * <li>#H5T_ENUM</li> + * <li>#H5T_VLEN</li> + * <li>#H5T_ARRAY</li></ul> + * </li> + * <li>If class is #H5T_COMPOUND, then go to step 2 and repeat all steps under step 3. If + * class is not #H5T_COMPOUND, then a member is of an atomic class and can be read + * to a corresponding buffer after discovering all necessary information specific to each + * atomic type (for example, size of the integer or floats, super class for enumerated and + * array datatype, and its sizes)</li></ul> + * + * The examples below show how to read a dataset with a known compound datatype. + * + * The first example below shows the steps needed to read data of a known structure. First, build a + * memory datatype the same way it was built when the dataset was created, and then second use + * the datatype in an #H5Dread call. + * + * <em>Read a dataset using a memory datatype</em> + * \code + * typedef struct s1_t { + * int a; + * float b; + * double c; + * } s1_t; + * + * s1_t *data; + * + * ... + * + * s1_tid = H5Tcreate(H5T_COMPOUND, sizeof(s1_t)); + * H5Tinsert(s1_tid, “a_name”, HOFFSET(s1_t, a), H5T_NATIVE_INT); + * H5Tinsert(s1_tid, “b_name”, HOFFSET(s1_t, b), H5T_NATIVE_FLOAT); + * H5Tinsert(s1_tid, “c_name”, HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + * + * ... + * + * dataset_id = H5Dopen(file_id, “SDScompound.h5”, H5P_DEFAULT); + * + * ... + * + * data = (s1_t *) malloc (sizeof(s1_t)*LENGTH); + * H5Dread(dataset_id, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * Instead of building a memory datatype, the application could use the + * #H5Tget_native_type function. See the example below. + * + * <em>Read a dataset using H5Tget_native_type</em> + * \code + * typedef struct s1_t { + * int a; + * float b; + * double c; + * } s1_t; + * + * s1_t *data; + * hid_t file_s1_t, mem_s1_t; + * + * ... + * + * dataset_id = H5Dopen(file_id, “SDScompound.h5”, H5P_DEFAULT); + * // Discover datatype in the file + * file_s1_t = H5Dget_type(dataset_id); + * // Find corresponding memory datatype + * mem_s1_t = H5Tget_native_type(file_s1_t, H5T_DIR_DEFAULT); + * + * ... + * + * data = (s1_t *) malloc (sizeof(s1_t)*LENGTH); + * H5Dread (dataset_id,mem_s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * The example below shows how to read just one float member of a compound datatype. + * + * <em>Read one floating point member of a compound datatype</em> + * \code + * typedef struct sf_t { + * float b; + * } sf_t; + * + * sf_t *data; + * + * ... + * + * sf_tid = H5Tcreate(H5T_COMPOUND, sizeof(sf_t)); + * H5Tinsert(sf_tid, “b_name”, HOFFSET(sf_t, b), H5T_NATIVE_FLOAT); + * + * ... + * + * dataset_id = H5Dopen(file_id, “SDScompound.h5”, H5P_DEFAULT); + * + * ... + * + * data = (sf_t *) malloc (sizeof(sf_t) * LENGTH); + * H5Dread(dataset_id, sf_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * The example below shows how to read float and double members of a compound datatype into a + * structure that has those fields in a different order. Please notice that #H5Tinsert calls can be used + * in an order different from the order of the structure’s members. + * + * <em>Read float and double members of a compound datatype</em> + * \code + * typedef struct sdf_t { + * double c; + * float b; + * } sdf_t; + * + * sdf_t *data; + * + * ... + * + * sdf_tid = H5Tcreate(H5T_COMPOUND, sizeof(sdf_t)); + * H5Tinsert(sdf_tid, “b_name”, HOFFSET(sdf_t, b), H5T_NATIVE_FLOAT); + * H5Tinsert(sdf_tid, “c_name”, HOFFSET(sdf_t, c), H5T_NATIVE_DOUBLE); + * + * ... + * + * dataset_id = H5Dopen(file_id, “SDScompound.h5”, H5P_DEFAULT); + * + * ... + * + * data = (sdf_t *) malloc (sizeof(sdf_t) * LENGTH); + * H5Dread(dataset_id, sdf_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * <h4>Array</h4> + * + * Many scientific datasets have multiple measurements for each point in a space. There are several + * natural ways to represent this data, depending on the variables and how they are used in + * computation. See the table and the figure below. + * + * <table> + * <caption>Representing data with multiple measurements</caption> + * <tr> + * <th> + * <p>Storage Strategy</p> + * </th> + * <th> + * <p>Stored as</p> + * </th> + * <th> + * <p>Remarks</p> + * </th> + * </tr> + * <tr> + * <td>Multiple planes + * </td> + * <td> + * Several datasets with identical dataspaces + * </td> + * <td> + * This is optimal when variables are accessed individually, or when often uses only selected + * variables. + * </td> + * </tr> + * <tr> + * <td> + * Additional dimension + * </td> + * <td> + * One dataset, the last “dimension” is a vec-tor of variables + * </td> + * <td> + * This can give good performance, although selecting only a few variables may be slow. This may + * not reflect the science. + * </td> + * </tr> + * <tr> + * <td> + * Record with multiple values + * </td> + * <td> + * One dataset with compound datatype + * </td> + * <td> + * This enables the variables to be read all together or selected. Also handles “vectors” of + * heterogeneous data. + * </td> + * </tr> + * <tr> + * <td> + * Vector or Tensor value + * </td> + * <td> + * One dataset, each data element is a small array of values. + * </td> + * <td> + * This uses the same amount of space as the previous two, and may represent the science model + * better. + * </td> + * </tr> + * </table> + * + * <table> + * <caption>Figure 13 Representing data with multiple measurements</caption> + * <tr> + * <td> + * \image html Dtypes_fig13a.gif + * </td> + * <td> + * \image html Dtypes_fig13b.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig13c.gif + * </td> + * <td> + * \image html Dtypes_fig13d.gif + * </td> + * </tr> + * </table> + * + * The HDF5 #H5T_ARRAY datatype defines the data element to be a homogeneous, multi-dimensional array. + * See Figure 13 above. The elements of the array can be any HDF5 datatype + * (including compound and array), and the size of the datatype is the total size of the array. A + * dataset of array datatype cannot be subdivided for I/O within the data element: the entire array of + * the data element must be transferred. If the data elements need to be accessed separately, for + * example, by plane, then the array datatype should not be used. The table below shows + * advantages and disadvantages of various storage methods. + * + * <table> + * <caption>Storage method advantages and disadvantages</caption> + * <tr> + * <th> + * <p>Method</p> + * </th> + * <th> + * <p>Advantages</p> + * </th> + * <th> + * <p>Disadvantages</p> + * </th> + * </tr> + * <tr> + * <td> + * Multiple Datasets + * </td> + * <td> + * Easy to access each plane, can select any plane(s) + * </td> + * <td> + * Less efficient to access a ‘column’ through the planes + * </td> + * </tr> + * </tr> + * <tr> + * <td> + * N+1 Dimension + * </td> + * <td> + * All access patterns supported + * </td> + * <td> + * Must be homogeneous datatype<br /> + * The added dimension may not make sense in the scientific model + * </td> + * </tr> + * </tr> + * <tr> + * <td> + * Compound Datatype + * </td> + * <td> + * Can be heterogeneous datatype + * </td> + * <td> + * Planes must be named, selection is by plane<br /> + * Not a natural representation for a matrix + * </td> + * </tr> + * </tr> + * <tr> + * <td> + * Array + * </td> + * <td> + * A natural representation for vector or tensor data + * </td> + * <td> + * Cannot access elements separately (no access by plane) + * </td> + * </tr> + * </table> + * + * An array datatype may be multi-dimensional with 1 to #H5S_MAX_RANK(the maximum rank + * of a dataset is currently 32) dimensions. The dimensions can be any size greater than 0, but + * unlimited dimensions are not supported (although the datatype can be a variable-length datatype). + * + * An array datatype is created with the #H5Tarray_create call, which specifies the number of + * dimensions, the size of each dimension, and the base type of the array. The array datatype can + * then be used in any way that any datatype object is used. The example below shows the creation + * of a datatype that is a two-dimensional array of native integers, and this is then used to create a + * dataset. Note that the dataset can be a dataspace that is any number and size of dimensions. The figure + * below shows the layout in memory assuming that the native integers are 4 bytes. Each + * data element has 6 elements, for a total of 24 bytes. + * + * <em>Create a two-dimensional array datatype</em> + * \code + * hid_t file, dataset; + * hid_t datatype, dataspace; + * hsize_t adims[] = {3, 2}; + * + * datatype = H5Tarray_create(H5T_NATIVE_INT, 2, adims, NULL); + * + * dataset = H5Dcreate(file, datasetname, datatype, + * dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig14.gif "Memory layout of a two-dimensional array datatype" + * </td> + * </tr> + * </table> + * + * @anchor h4_vlen_datatype <h4>Variable-length Datatypes</h4> + * + * A variable-length (VL) datatype is a one-dimensional sequence of a datatype which are not fixed + * in length from one dataset location to another. In other words, each data element may have a + * different number of members. Variable-length datatypes cannot be divided;the entire data + * element must be transferred. + * + * VL datatypes are useful to the scientific community in many different ways, possibly including: + * <ul> + * <li>Ragged arrays: Multi-dimensional ragged arrays can be implemented with the last (fastest changing) + * dimension being ragged by using a VL datatype as the type of the element stored. + * </li> + * <li>Fractal arrays: A nested VL datatype can be used to implement ragged arrays of ragged arrays, to + * whatever nesting depth is required for the user. + * </li> + * <li>Polygon lists: A common storage requirement is to efficiently store arrays of polygons with + * different numbers of vertices. A VL datatype can be used to efficiently and succinctly describe + * an array of polygons with different numbers of vertices. + * </li> + * <li>Character strings: Perhaps the most common use of VL datatypes will be to store C-like VL + * character strings in dataset elements or as attributes of objects. + * </li> + * <li>Indices (for example, of objects within a file): An array of VL object references could be used + * as an index to all the objects in a file which contain a particular sequence of dataset values. + * </li> + * <li>Object Tracking: An array of VL dataset region references can be used as a method of tracking + * objects or features appearing in a sequence of datasets. + * </li> + * </ul> + * + * A VL datatype is created by calling #H5Tvlen_create which specifies the base datatype. The first + * example below shows an example of code that creates a VL datatype of unsigned integers. Each + * data element is a one-dimensional array of zero or more members and is stored in the + * hvl_t structure. See the second example below. + * + * <em>Create a variable-length datatype of unsigned integers</em> + * \code + * tid1 = H5Tvlen_create (H5T_NATIVE_UINT); + * + * dataset=H5Dcreate(fid1,“Dataset1”, tid1, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * <em>Data element storage for members of the VL datatype</em> + * \code + * typedef struct + * { + * size_t len; // Length of VL data + * //(in base type units) + * void *p; // Pointer to VL data + * } hvl_t; + * \endcode + * + * The first example below shows how the VL data is written. For each of the 10 data elements, a + * length and data buffer must be allocated. Below the two examples is a figure that shows how the + * data is laid out in memory. + * + * An analogous procedure must be used to read the data. See the second example below. An + * appropriate array of vl_t must be allocated, and the data read. It is then traversed one data + * element at a time. The #H5Dvlen_reclaim call frees the data buffer for the buffer. With each + * element possibly being of different sequence lengths for a dataset with a VL datatype, the + * memory for the VL datatype must be dynamically allocated. Currently there are two methods of + * managing the memory for VL datatypes: the standard C malloc/free memory allocation routines + * or a method of calling user-defined memory management routines to allocate or free memory + * (set with #H5Pset_vlen_mem_manager). Since the memory allocated when reading (or writing) + * may be complicated to release, the #H5Dvlen_reclaim function is provided to traverse a memory + * buffer and free the VL datatype information without leaking memory. + * + * <em>Write VL data</em> + * \code + * hvl_t wdata[10]; // Information to write + * + * // Allocate and initialize VL data to write + * for(i = 0; i < 10; i++) { + * wdata[i].p = malloc((i + 1) * sizeof(unsigned int)); + * wdata[i].len = i + 1; + * for(j = 0; j < (i + 1); j++) + * ((unsigned int *)wdata[i].p)[j]=i * 10 + j; + * } + * ret = H5Dwrite(dataset, tid1, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); + * \endcode + * + * <em>Read VL data</em> + * \code + * hvl_t rdata[SPACE1_DIM1]; + * ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, xfer_pid, rdata); + * + * for(i = 0; i < SPACE1_DIM1; i++) { + * printf(“%d: len %d ”,rdata[i].len); + * for(j = 0; j < rdata[i].len; j++) { + * printf(“ value: %u\n”,((unsigned int *)rdata[i].p)[j]); + * } + * } + * ret = H5Dvlen_reclaim(tid1, sid1, xfer_pid, rdata); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig15.gif "Memory layout of a VL datatype" + * </td> + * </tr> + * </table> + * + * The user program must carefully manage these relatively complex data structures. The + * #H5Dvlen_reclaim function performs a standard traversal, freeing all the data. This function + * analyzes the datatype and dataspace objects, and visits each VL data element, recursing through + * nested types. By default, the system free is called for the pointer in each vl_t. Obviously, this + * call assumes that all of this memory was allocated with the system malloc. + * + * The user program may specify custom memory manager routines, one for allocating and one for + * freeing. These may be set with the #H5Pset_vlen_mem_manager, and must have the following + * prototypes: + * <ul> + * <li> + * \code + * typedef void *(*H5MM_allocate_t)(size_t size, void *info); + * \endcode + * </li> + * <li> + * \code + * typedef void (*H5MM_free_t)(void *mem, void *free_info); + * \endcode + * </li> + * </ul> + * The utility function #H5Dvlen_get_buf_size checks the number of bytes required to store the VL + * data from the dataset. This function analyzes the datatype and dataspace object to visit all the VL + * data elements, to determine the number of bytes required to store the data for the in the + * destination storage (memory). The size value is adjusted for data conversion and alignment in the + * destination. + * + * \subsection subsec_datatype_other Other Non-numeric Datatypes + * Several datatype classes define special types of objects. + * + * \subsubsection subsubsec_datatype_other_strings Strings + * Text data is represented by arrays of characters, called strings. Many programming languages + * support different conventions for storing strings, which may be fixed or variable-length, and may + * have different rules for padding unused storage. HDF5 can represent strings in several ways. See + * the figure below. + * + * The strings to store are “Four score” and “lazy programmers.” + * <table> + * <caption>A string stored as one-character elements in a one-dimensional array</caption> + * <tr> + * <td> + * a) #H5T_NATIVE_CHAR: The dataset is a one-dimensional array with 29 elements, and each element + * is a single character. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig16a.gif + * </td> + * </tr> + * <tr> + * <td> + * b) Fixed-length string: The dataset is a one-dimensional array with two elements, and each + * element is 20 characters. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig16b.gif + * </td> + * </tr> + * <tr> + * <td> + * c) Variable-length string: The dataset is a one-dimensional array with two elements, and each + * element is a variable-length string. This is the same result when stored as a fixed-length + * string except that the first element of the array will need only 11 bytes for storage instead of 20. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig16c.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig16d.gif + * </td> + * </tr> + * </table> + * + * First, a dataset may have a dataset with datatype #H5T_NATIVE_CHAR with each character of + * the string as an element of the dataset. This will store an unstructured block of text data, but + * gives little indication of any structure in the text. See item a in the figure above. + * + * A second alternative is to store the data using the datatype class #H5T_STRING with each + * element a fixed length. See item b in the figure above. In this approach, each element might be a + * word or a sentence, addressed by the dataspace. The dataset reserves space for the specified + * number of characters, although some strings may be shorter. This approach is simple and usually + * is fast to access, but can waste storage space if the length of the Strings varies. + * + * A third alternative is to use a variable-length datatype. See item c in the figure above. This can + * be done using the standard mechanisms described above. The program would use vl_t structures + * to write and read the data. + * + * A fourth alternative is to use a special feature of the string datatype class to set the size of the + * datatype to #H5T_VARIABLE. See item c in the figure above. The example below shows a + * declaration of a datatype of type #H5T_C_S1 which is set to #H5T_VARIABLE. The HDF5 + * Library automatically translates between this and the vl_t structure. Note: the #H5T_VARIABLE + * size can only be used with string datatypes. + * <em>Set the string datatype size to H5T_VARIABLE</em> + * \code + * tid1 = H5Tcopy (H5T_C_S1); + * ret = H5Tset_size (tid1, H5T_VARIABLE); + * \endcode + * + * Variable-length strings can be read into C strings (in other words, pointers to zero terminated + * arrays of char). See the example below. + * <em>Read variable-length strings into C strings</em> + * \code + * char *rdata[SPACE1_DIM1]; + * + * ret = H5Dread(dataset, tid1, H5S_ALL, H5S_ALL, xfer_pid, rdata); + * + * for(i = 0; i < SPACE1_DIM1; i++) { + * printf(“%d: len: %d, str is: %s\n”, i, strlen(rdata[i]), rdata[i]); + * } + * + * ret = H5Dvlen_reclaim(tid1, sid1, xfer_pid, rdata); + * \endcode + * + * \subsubsection subsubsec_datatype_other_refs Reference + * In HDF5, objects (groups, datasets, and committed datatypes) are usually accessed by name. + * There is another way to access stored objects - by reference. There are two reference datatypes: + * object reference and region reference. Object reference objects are created with #H5Rcreate and + * other calls (cross reference). These objects can be stored and retrieved in a dataset as elements + * with reference datatype. The first example below shows an example of code that creates + * references to four objects, and then writes the array of object references to a dataset. The second + * example below shows a dataset of datatype reference being read and one of the reference objects + * being dereferenced to obtain an object pointer. + * + * In order to store references to regions of a dataset, the datatype should be #H5T_STD_REF_DSETREG. + * Note that a data element must be either an object reference or a region reference: these are + * different types and cannot be mixed within a single array. + * + * A reference datatype cannot be divided for I/O: an element is read or written completely. + * + * <em>Create object references and write to a dataset</em> + * \code + * dataset= H5Dcreate (fid1, “Dataset3”, H5T_STD_REF_OBJ, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * + * // Create reference to dataset + * ret = H5Rcreate(&wbuf[0], fid1,“/Group1/Dataset1”, H5R_OBJECT, -1); + * + * // Create reference to dataset + * ret = H5Rcreate(&wbuf[1], fid1, “/Group1/Dataset2”, H5R_OBJECT, -1); + * + * // Create reference to group + * ret = H5Rcreate(&wbuf[2], fid1, “/Group1”, H5R_OBJECT, -1); + * + * // Create reference to committed datatype + * ret = H5Rcreate(&wbuf[3], fid1, “/Group1/Datatype1”, H5R_OBJECT, -1); + * + * // Write selection to disk + * ret=H5Dwrite(dataset, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, wbuf); + * \endcode + * + * <em>Read a dataset with a reference datatype</em> + * \code + * rbuf = malloc(sizeof(hobj_ref_t)*SPACE1_DIM1); + * + * // Read selection from disk + * ret=H5Dread(dataset, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf); + * + * // Open dataset object + * dset2 = H5Rdereference(dataset, H5R_OBJECT, &rbuf[0]); + * \endcode + * + * \subsubsection subsubsec_datatype_other_enum ENUM + * The enum datatype implements a set of (name, value) pairs, similar to C/C++ enum. The values + * are currently limited to native integer datatypes. Each name can be the name of only one value, + * and each value can have only one name. + * + * The data elements of the ENUMERATION are stored according to the datatype. An example + * would be as an array of integers. The example below shows an example of how to create an + * enumeration with five elements. The elements map symbolic names to 2-byte integers. See the + * table below. + * <em>Create an enumeration with five elements</em> + * \code + * hid_t hdf_en_colors; + * short val; + * + * hdf_en_colors = H5Tcreate(H5T_ENUM, sizeof(short)); + * H5Tenum_insert(hdf_en_colors, “RED”, (val=0, &val)); + * H5Tenum_insert(hdf_en_colors, “GREEN”, (val=1, &val)); + * H5Tenum_insert(hdf_en_colors, “BLUE”, (val=2, &val)); + * H5Tenum_insert(hdf_en_colors, “WHITE”, (val=3, &val)); + * H5Tenum_insert(hdf_en_colors, “BLACK”, (val=4, &val)); + * H5Dcreate(fileid, datasetname, hdf_en_colors, spaceid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * <table> + * <caption>An enumeration with five elements</caption> + * <tr> + * <th>Name</th> + * <th>Value</th> + * </tr> + * <tr> + * <td>RED</td> + * <td>0</td> + * </tr> + * <tr> + * <td>GREEN</td> + * <td>1</td> + * </tr> + * <tr> + * <td>BLUE</td> + * <td>2</td> + * </tr> + * <tr> + * <td>WHITE</td> + * <td>3</td> + * </tr> + * <tr> + * <td>BLACK</td> + * <td>4</td> + * </tr> + * </table> + * + * The figure below shows how an array of eight values might be stored. Conceptually, the array is + * an array of symbolic names [BLACK, RED, WHITE, BLUE, ...] See item a in the figure below. + * These are stored as the values and are short integers. So, the first 2 bytes are the value associated + * with “BLACK”, which is the number 4, and so on. See item b in the figure below. + * <table> + * <caption>Storing an enum array</caption> + * <tr> + * <td> + * a) Logical data to be written - eight elements + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig17a.gif + * </td> + * </tr> + * <tr> + * <td> + * b) The storage layout. Total size of the array is 16 bytes, 2 bytes per element. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig17b.gif + * </td> + * </tr> + * </table> + * + * The order that members are inserted into an enumeration type is unimportant; the important part + * is the associations between the symbol names and the values. Thus, two enumeration datatypes + * will be considered equal if and only if both types have the same symbol/value associations and + * both have equal underlying integer datatypes. Type equality is tested with the H5Tequal + * function. + * + * If a particular architecture type is required, a little-endian or big-endian datatype for example, + * use a native integer datatype as the ENUM base datatype and use #H5Tconvert on values as they + * are read from or written to a dataset. + * + * \subsubsection subsubsec_datatype_other_opaque Opaque + * In some cases, a user may have data objects that should be stored and retrieved as blobs with no + * attempt to interpret them. For example, an application might wish to store an array of encrypted + * certificates which are 100 bytes long. + * + * While an arbitrary block of data may always be stored as bytes, characters, integers, or whatever, + * this might mislead programs about the meaning of the data. The opaque datatype defines data + * elements which are uninterpreted by HDF5. The opaque data may be labeled with + * #H5Tset_tag with a string that might be used by an application. For example, the encrypted + * certificates might have a tag to indicate the encryption and the certificate standard. + * + * \subsubsection subsubsec_datatype_other_bitfield Bitfield + * Some data is represented as bits, where the number of bits is not an integral byte and the bits are + * not necessarily interpreted as a standard type. Some examples might include readings from + * machine registers (for example, switch positions), a cloud mask, or data structures with several + * small integers that should be store in a single byte. + * + * This data could be stored as integers, strings, or enumerations. However, these storage methods + * would likely result in considerable wasted space. For example, storing a cloud mask with one + * byte per value would use up to eight times the space of a packed array of bits. + * + * The HDF5 bitfield datatype class defines a data element that is a contiguous sequence of bits, + * which are stored on disk in a packed array. The programming model is the same as for unsigned + * integers: the datatype object is created by copying a predefined datatype, and then the precision, + * offset, and padding are set. + * + * While the use of the bitfield datatype will reduce storage space substantially, there will still be + * wasted space if the bitfield as a whole does not match the 1-, 2-, 4-, or 8-byte unit in which it is + * written. The remaining unused space can be removed by applying the N-bit filter to the dataset + * containing the bitfield data. For more information, see "Using the N-bit Filter." + * + * \subsection subsec_datatype_fill Fill Values + * The “fill value” for a dataset is the specification of the default value assigned to data elements + * that have not yet been written. In the case of a dataset with an atomic datatype, the fill value is a + * single value of the appropriate datatype, such as ‘0’ or ‘-1.0’. In the case of a dataset with a + * composite datatype, the fill value is a single data element of the appropriate type. For example, + * for an array or compound datatype, the fill value is a single data element with values for all the + * component elements of the array or compound datatype. + * + * The fill value is set (permanently) when the dataset is created. The fill value is set in the dataset + * creation properties in the #H5Dcreate call. Note that the #H5Dcreate call must also include the + * datatype of the dataset, and the value provided for the fill value will be interpreted as a single + * element of this datatype. The example below shows code which creates a dataset of integers with + * fill value -1. Any unwritten data elements will be set to -1. + * + * <em>Create a dataset with a fill value of -1</em> + * \code + * hid_t plist_id; + * int filler; + * + * filler = -1; + * plist_id = H5Pcreate(H5P_DATASET_CREATE); + * H5Pset_fill_value(plist_id, H5T_NATIVE_INT, &filler); + * + * // Create the dataset with fill value ‘-1’. + * dataset_id = H5Dcreate(file_id, “/dset”, H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, plist_id, + * H5P_DEFAULT); + * \endcode + * + * <em>Create a fill value for a compound datatype</em> + * \code + * typedef struct s1_t { + * int a; + * char b; + * double c; + * } s1_t; + * s1_t filler; + * + * s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + * H5Tinsert(s1_tid, “a_name”, HOFFSET(s1_t, a), H5T_NATIVE_INT); + * H5Tinsert(s1_tid, “b_name”, HOFFSET(s1_t, b), H5T_NATIVE_CHAR); + * H5Tinsert(s1_tid, “c_name”, HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + * + * filler.a = -1; + * filler.b = ‘*’; + * filler.c = -2.0; + * plist_id = H5Pcreate(H5P_DATASET_CREATE); + * H5Pset_fill_value(plist_id, s1_tid, &filler); + * + * // Create the dataset with fill value + * // (-1, ‘*’, -2.0). + * dataset = H5Dcreate(file, datasetname, s1_tid, space, H5P_DEFAULT, plist_id, H5P_DEFAULT); + * \endcode + * + * The code above shows how to create a fill value for a compound datatype. The procedure is the + * same as the previous example except the filler must be a structure with the correct fields. Each + * field is initialized to the desired fill value. + * + * The fill value for a dataset can be retrieved by reading the dataset creation properties of the + * dataset and then by reading the fill value with #H5Pget_fill_value. The data will be read into + * memory using the storage layout specified by the datatype. This transfer will convert data in the + * same way as #H5Dread. The example below shows how to get the fill value from the dataset + * created in the example "Create a dataset with a fill value of -1". + * + * <em>Retrieve a fill value</em> + * \code + * hid_t plist2; + * int filler; + * + * dataset_id = H5Dopen(file_id, “/dset”, H5P_DEFAULT); + * plist2 = H5Dget_create_plist(dataset_id); + * + * H5Pget_fill_value(plist2, H5T_NATIVE_INT, &filler); + * + * // filler has the fill value, ‘-1’ + * \endcode + * + * A similar procedure is followed for any datatype. The example below shows how to read the fill + * value for the compound datatype created in an example above. Note that the program must pass + * an element large enough to hold a fill value of the datatype indicated by the argument to + * #H5Pget_fill_value. Also, the program must understand the datatype in order to interpret its + * components. This may be difficult to determine without knowledge of the application that + * created the dataset. + * + * <em>Read the fill value for a compound datatype</em> + * \code + * char *fillbuf; + * int sz; + * + * dataset = H5Dopen( file, DATASETNAME, H5P_DEFAULT); + * + * s1_tid = H5Dget_type(dataset); + * + * sz = H5Tget_size(s1_tid); + * + * fillbuf = (char *)malloc(sz); + * + * plist_id = H5Dget_create_plist(dataset); + * + * H5Pget_fill_value(plist_id, s1_tid, fillbuf); + * + * printf(“filler.a: %d\n”,((s1_t *) fillbuf)->a); + * printf(“filler.b: %c\n”,((s1_t *) fillbuf)->b); + * printf(“filler.c: %f\n”,((s1_t *) fillbuf)->c); + * \endcode + * + * \subsection subsec_datatype_complex Complex Combinations of Datatypes + * Several composite datatype classes define collections of other datatypes, including other + * composite datatypes. In general, a datatype can be nested to any depth, with any combination of + * datatypes. + * + * For example, a compound datatype can have members that are other compound datatypes, arrays, + * VL datatypes. An array can be an array of array, an array of compound, or an array of VL. And a + * VL datatype can be a variable-length array of compound, array, or VL datatypes. + * + * These complicated combinations of datatypes form a logical tree, with a single root datatype, and + * leaves which must be atomic datatypes (predefined or user-defined). The figure below shows an + * example of a logical tree describing a compound datatype constructed from different datatypes. + * + * Recall that the datatype is a description of the layout of storage. The complicated compound + * datatype is constructed from component datatypes, each of which describes the layout of part of + * the storage. Any datatype can be used as a component of a compound datatype, with the + * following restrictions: + * <ul><li>1. No byte can be part of more than one component datatype (in other words, the fields cannot + * overlap within the compound datatype)</li> + * <li>2. The total size of the components must be less than or equal to the total size of the compound + * datatype</li></ul> + * These restrictions are essentially the rules for C structures and similar record types familiar from + * programming languages. Multiple typing, such as a C union, is not allowed in HDF5 datatypes. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig18.gif "A compound datatype built with different datatypes" + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_complex_create Creating a Complicated Compound Datatype + * To construct a complicated compound datatype, each component is constructed, and then added + * to the enclosing datatype description. The example below shows how to create a compound + * datatype with four members: + * \li “T1”, a compound datatype with three members + * \li “T2”, a compound datatype with two members + * \li “T3”, a one-dimensional array of integers + * \li “T4”, a string + * + * Below the example code is a figure that shows this datatype as a logical tree. The output of the + * h5dump utility is shown in the example below the figure. + * + * Each datatype is created as a separate datatype object. Figure "The storage layout for the + * four member datatypes" below shows the storage layout + * for the four individual datatypes. Then the datatypes are inserted into the outer datatype at an + * appropriate offset. Figure "The storage layout of the combined four members" below shows the + * resulting storage layout. The combined record is 89 bytes long. + * + * The Dataset is created using the combined compound datatype. The dataset is declared to be a 4 + * by 3 array of compound data. Each data element is an instance of the 89-byte compound + * datatype. Figure "The layout of the dataset" below shows the layout of the dataset, and expands + * one of the elements to show the relative position of the component data elements. + * + * Each data element is a compound datatype, which can be written or read as a record, or each + * field may be read or written individually. The first field (“T1”) is itself a compound datatype + * with three fields (“T1.a”, “T1.b”, and “T1.c”). “T1” can be read or written as a record, or + * individual fields can be accessed. Similarly, the second filed is a compound datatype with two + * fields (“T2.f1”, “T2.f2”). + * + * The third field (“T3”) is an array datatype. Thus, “T3” should be accessed as an array of 40 + * integers. Array data can only be read or written as a single element, so all 40 integers must be + * read or written to the third field. The fourth field (“T4”) is a single string of length 25. + * + * <em>Create a compound datatype with four members</em> + * \code + * typedef struct s1_t { + * int a; + * char b; + * double c; + * } s1_t; + * typedef struct s2_t { + * float f1; + * float f2; + * } s2_t; + * hid_t s1_tid, s2_tid, s3_tid, s4_tid, s5_tid; + * + * // Create a datatype for s1 + * s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); + * H5Tinsert(s1_tid, “a_name”, HOFFSET(s1_t, a), H5T_NATIVE_INT); + * H5Tinsert(s1_tid, “b_name”, HOFFSET(s1_t, b), H5T_NATIVE_CHAR); + * H5Tinsert(s1_tid, “c_name”, HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); + * + * // Create a datatype for s2. + * s2_tid = H5Tcreate (H5T_COMPOUND, sizeof(s2_t)); + * H5Tinsert(s2_tid, “f1”, HOFFSET(s2_t, f1), H5T_NATIVE_FLOAT); + * H5Tinsert(s2_tid, “f2”, HOFFSET(s2_t, f2), H5T_NATIVE_FLOAT); + * + * // Create a datatype for an Array of integers + * s3_tid = H5Tarray_create(H5T_NATIVE_INT, RANK, dim); + * + * // Create a datatype for a String of 25 characters + * s4_tid = H5Tcopy(H5T_C_S1); + * H5Tset_size(s4_tid, 25); + * + * // Create a compound datatype composed of one of each of these types. + * // The total size is the sum of the size of each. + * sz = H5Tget_size(s1_tid) + H5Tget_size(s2_tid) + H5Tget_size(s3_tid) + H5Tget_size(s4_tid); + * s5_tid = H5Tcreate (H5T_COMPOUND, sz); + * + * // Insert the component types at the appropriate offsets. + * H5Tinsert(s5_tid, “T1”, 0, s1_tid); + * H5Tinsert(s5_tid, “T2”, sizeof(s1_t), s2_tid); + * H5Tinsert(s5_tid, “T3”, sizeof(s1_t) + sizeof(s2_t), s3_tid); + * H5Tinsert(s5_tid, “T4”, (sizeof(s1_t) + sizeof(s2_t) + H5Tget_size(s3_tid)), s4_tid); + * + * // Create the dataset with this datatype. + * dataset = H5Dcreate(file, DATASETNAME, s5_tid, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig19.gif "Logical tree for the compound datatype with four members" + * </td> + * </tr> + * </table> + * + * <em> Output from h5dump for the compound datatype</em> + * \code + * DATATYPE H5T_COMPOUND { + * H5T_COMPOUND { + * H5T_STD_I32LE “a_name”; + * H5T_STD_I8LE “b_name”; + * H5T_IEEE_F64LE “c_name”; + * } “T1”; + * H5T_COMPOUND { + * H5T_IEEE_F32LE “f1”; + * H5T_IEEE_F32LE “f2”; + * } “T2”; + * H5T_ARRAY { [10] H5T_STD_I32LE } “T3”; + * H5T_STRING { + * STRSIZE 25; + * STRPAD H5T_STR_NULLTERM; + * CSET H5T_CSET_ASCII; + * CTYPE H5T_C_S1; + * } “T4”; + * } + * \endcode + * + * <table> + * <caption> The storage layout for the four member datatypes</caption> + * <tr> + * <td> + * a) Compound type ‘s1_t’, size 16 bytes. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig20a.gif + * </td> + * </tr> + * <tr> + * <td> + * b) Compound type ‘s2_t’, size 8 bytes. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig20b.gif + * </td> + * </tr> + * <tr> + * <td> + * c) Array type ‘s3_tid’, 40 integers, total size 40 bytes. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig20c.gif + * </td> + * </tr> + * <tr> + * <td> + * d) String type ‘s4_tid’, size 25 bytes. + * </td> + * </tr> + * <tr> + * <td> + * \image html Dtypes_fig20d.gif + * </td> + * </tr> + * </table> + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig21.gif "The storage layout of the combined four members" + * </td> + * </tr> + * </table> + * + * \li A 4 x 3 array of Compound Datatype + * \li Element [1,1] expanded + * <table> + * <tr> + * <td> + * \image html Dtypes_fig22.gif "The layout of the dataset" + * </td> + * </tr> + * </table> + * + * \subsubsection subsubsec_datatype_complex_analyze Analyzing and Navigating a Compound Datatype + * A complicated compound datatype can be analyzed piece by piece to discover the exact storage + * layout. In the example above, the outer datatype is analyzed to discover that it is a compound + * datatype with four members. Each member is analyzed in turn to construct a complete map of the + * storage layout. + * + * The example below shows an example of code that partially analyzes a nested compound + * datatype. The name and overall offset and size of the component datatype is discovered, and then + * its type is analyzed depending on the datatype class. Through this method, the complete storage + * layout can be discovered. + * + * <em> Output from h5dump for the compound datatype</em> + * \code + * s1_tid = H5Dget_type(dataset); + * + * if (H5Tget_class(s1_tid) == H5T_COMPOUND) { + * printf(“COMPOUND DATATYPE {\n”); + * sz = H5Tget_size(s1_tid); + * nmemb = H5Tget_nmembers(s1_tid); + * printf(“ %d bytes\n”,sz); + * printf(“ %d members\n”,nmemb); + * for (i =0; i < nmemb; i++) { + * s2_tid = H5Tget_member_type(s1_tid, i); + * if (H5Tget_class(s2_tid) == H5T_COMPOUND) { + * // recursively analyze the nested type. + * } + * else if (H5Tget_class(s2_tid) == H5T_ARRAY) { + * sz2 = H5Tget_size(s2_tid); + * printf(“ %s: NESTED ARRAY DATATYPE offset %d size %d + * {\n”, H5Tget_member_name(s1_tid, i), H5Tget_member_offset(s1_tid, i), sz2); + * H5Tget_array_dims(s2_tid, dim); + * s3_tid = H5Tget_super(s2_tid); + * // Etc., analyze the base type of the array + * } + * else { + * // analyze a simple type + * printf(“ %s: type code %d offset %d size %d\n”, H5Tget_member_name(s1_tid, i), + * H5Tget_class(s2_tid), H5Tget_member_offset(s1_tid, i), H5Tget_size(s2_tid)); + * } + * // and so on.... + * \endcode + * + * \subsection subsec_datatype_life Life Cycle of the Datatype Object + * Application programs access HDF5 datatypes through identifiers. Identifiers are obtained by + * creating a new datatype or by copying or opening an existing datatype. The identifier can be used + * until it is closed or until the library shuts down. See items a and b in the figure below. By default, + * a datatype is transient, and it disappears when it is closed. + * + * When a dataset or attribute is created (#H5Dcreate or #H5Acreate), its datatype is stored in the + * HDF5 file as part of the dataset or attribute object. See item c in the figure below. Once an object + * created, its datatype cannot be changed or deleted. The datatype can be accessed by calling + * #H5Dget_type, #H5Aget_type, #H5Tget_super, or #H5Tget_member_type. See item d in the figure + * below. These calls return an identifier to a transient copy of the datatype of the dataset or + * attribute unless the datatype is a committed datatype. + * Note that when an object is created, the stored datatype is a copy of the transient datatype. If two + * objects are created with the same datatype, the information is stored in each object with the same + * effect as if two different datatypes were created and used. + * + * A transient datatype can be stored using #H5Tcommit in the HDF5 file as an independent, named + * object, called a committed datatype. Committed datatypes were formerly known as named + * datatypes. See item e in the figure below. Subsequently, when a committed datatype is opened + * with #H5Topen (item f), or is obtained with #H5Tget_member_type or similar call (item k), the return + * is an identifier to a transient copy of the stored datatype. The identifier can be used in the + * same way as other datatype identifiers except that the committed datatype cannot be modified. When a + * committed datatype is copied with #H5Tcopy, the return is a new, modifiable, transient datatype + * object (item f). + * + * When an object is created using a committed datatype (#H5Dcreate, #H5Acreate), the stored + * datatype is used without copying it to the object. See item j in the figure below. In this case, if + * multiple objects are created using the same committed datatype, they all share the exact same + * datatype object. This saves space and makes clear that the datatype is shared. Note that a + * committed datatype can be shared by objects within the same HDF5 file, but not by objects in + * other files. For more information on copying committed datatypes to other HDF5 files, see the + * “Copying Committed Datatypes with H5Ocopy” topic in the “Additional Resources” chapter. + * + * A committed datatype can be deleted from the file by calling #H5Ldelete which replaces + * #H5Gunlink. See item i in the figure below. If one or more objects are still using the datatype, the + * committed datatype cannot be accessed with #H5Topen, but will not be removed from the file + * until it is no longer used. #H5Tget_member_type and similar calls will return a transient copy of the + * datatype. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig23.gif "Life cycle of a datatype" + * </td> + * </tr> + * </table> + * + * Transient datatypes are initially modifiable. Note that when a datatype is copied or when it is + * written to the file (when an object is created) or the datatype is used to create a composite + * datatype, a copy of the current state of the datatype is used. If the datatype is then modified, the + * changes have no effect on datasets, attributes, or datatypes that have already been created. See + * the figure below. + * + * A transient datatype can be made read-only (#H5Tlock). Note that the datatype is still transient, + * and otherwise does not change. A datatype that is immutable is read-only but cannot be closed + * except when the entire library is closed. The predefined types such as #H5T_NATIVE_INT are + * immutable transient types. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig24.gif "Transient datatype states: modifiable, read-only, and immutable" + * </td> + * </tr> + * </table> + * + * To create two or more datasets that share a common datatype, first commit the datatype, and then + * use that datatype to create the datasets. See the example below. + * <em> Create a shareable datatype</em> + * \code + * hid_t t1 = ...some transient type...; + * H5Tcommit (file, “shared_type”, t1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * hid_t dset1 = H5Dcreate (file, “dset1”, t1, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * hid_t dset2 = H5Dcreate (file, “dset2”, t1, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * + * hid_t dset1 = H5Dopen (file, “dset1”, H5P_DEFAULT); + * hid_t t2 = H5Dget_type (dset1); + * hid_t dset3 = H5Dcreate (file, “dset3”, t2, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * hid_t dset4 = H5Dcreate (file, “dset4”, t2, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * <table> + * <caption> Datatype APIs</caption> + * <tr> + * <th>Function</th> + * <th>Description</th> + * </tr> + * <tr> + * <td> + * \code + * hid_t H5Topen (hid_t location, const char *name) + * \endcode + * </td> + * <td> + * A committed datatype can be opened by calling this function, which returns a datatype identifier. + * The identifier should eventually be released by calling #H5Tclose() to release resources. The + * committed datatype returned by this function is read-only or a negative value is returned for failure. + * The location is either a file or group identifier. + * </td> + * </tr> + * <tr> + * <td> + * \code + * herr_t H5Tcommit (hid_t location, const char *name, hid_t type, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) + * \endcode + * </td> + * <td> + * A transient datatype (not immutable) can be written to a file and turned into a committed datatype by + * calling this function. The location is either a file or group identifier and when combined with name + * refers to a new committed datatype. + * </td> + * </tr> + * <tr> + * <td> + * \code + * htri_t H5Tcommitted (hid_t type) + * \endcode + * </td> + * <td> + * A type can be queried to determine if it is a committed type or a transient type. If this function + * returns a positive value then the type is committed. Datasets which return committed datatypes with + * #H5Dget_type() are able to share the datatype with other datasets in the same file. + * </td> + * </tr> + * </table> + * + * \subsection subsec_datatype_transfer Data Transfer: Datatype Conversion and Selection + * When data is transferred (write or read), the storage layout of the data elements may be different. + * For example, an integer might be stored on disk in big-endian byte order and read into memory + * with little-endian byte order. In this case, each data element will be transformed by the HDF5 + * Library during the data transfer. + * + * The conversion of data elements is controlled by specifying the datatype of the source and + * specifying the intended datatype of the destination. The storage format on disk is the datatype + * specified when the dataset is created. The datatype of memory must be specified in the library + * call. + * + * In order to be convertible, the datatype of the source and destination must have the same + * datatype class (with the exception of enumeration type). Thus, integers can be converted to other + * integers, and floats to other floats, but integers cannot (yet) be converted to floats. For each + * atomic datatype class, the possible conversions are defined. An enumeration datatype can be + * converted to an integer or a floating-point number datatype. + * + * Basically, any datatype can be converted to another datatype of the same datatype class. The + * HDF5 Library automatically converts all properties. If the destination is too small to hold the + * source value then an overflow or underflow exception occurs. If a handler is defined with the + * #H5Pset_type_conv_cb function, it will be called. Otherwise, a default action will be performed. + * The table below summarizes the default actions. + * + * <table> + * <caption>Default actions for datatype conversion exceptions</caption> + * <tr> + * <th>Datatype Class</th> + * <th>Possible Exceptions</th> + * <th>Default Action</th> + * </tr> + * <tr> + * <td>Integer</td> + * <td>Size, offset, pad</td> + * <td></td> + * </tr> + * <tr> + * <td>Float</td> + * <td>Size, offset, pad, ebits</td> + * <td></td> + * </tr> + * <tr> + * <td>String</td> + * <td>Size</td> + * <td>Truncates, zero terminate if required.</td> + * </tr> + * <tr> + * <td>Enumeration</td> + * <td>No field</td> + * <td>All bits set</td> + * </tr> + * </table> + * + * For example, when reading data from a dataset, the source datatype is the datatype set when the + * dataset was created, and the destination datatype is the description of the storage layout in + * memory. The destination datatype must be specified in the #H5Dread call. The example below + * shows an example of reading a dataset of 32-bit integers. The figure below the example shows + * the data transformation that is performed. + * <em>Specify the destination datatype with H5Dread</em> + * \code + * // Stored as H5T_STD_BE32 + * // Use the native memory order in the destination + * mem_type_id = H5Tcopy(H5T_NATIVE_INT); + * status = H5Dread(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf); + * \endcode + * + * <table> + * <caption>Layout of a datatype conversion</caption> + * <tr> + * <td> + * \image html Dtypes_fig25a.gif<br /> + * \image html Dtypes_fig25b.gif<br /> + * \image html Dtypes_fig25c.gif + * </td> + * </tr> + * </table> + * + * One thing to note in the example above is the use of the predefined native datatype + * #H5T_NATIVE_INT. Recall that in this example, the data was stored as a 4-bytes in big-endian + * order. The application wants to read this data into an array of integers in memory. Depending on + * the system, the storage layout of memory might be either big or little-endian, so the data may + * need to be transformed on some platforms and not on others. The #H5T_NATIVE_INT type is set + * by the HDF5 Library to be the correct type to describe the storage layout of the memory on the + * system. Thus, the code in the example above will work correctly on any platform, performing a + * transformation when needed. + * + * There are predefined native types for most atomic datatypes, and these can be combined in + * composite datatypes. In general, the predefined native datatypes should always be used for data + * stored in memory. + * Predefined native datatypes describe the storage properties of memory. + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig26.gif "An enum datatype conversion" + * </td> + * </tr> + * </table> + * + * <em>Create an aligned and packed compound datatype</em> + * \code + * // Stored as H5T_STD_BE32 + * // Use the native memory order in the destination + * mem_type_id = H5Tcopy(H5T_NATIVE_INT); + * status = H5Dread(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig27.gif "Alignment of a compound datatype" + * </td> + * </tr> + * </table> + * + * <em>Transfer some fields of a compound datatype</em> + * \code + * // Stored as H5T_STD_BE32 + * // Use the native memory order in the destination + * mem_type_id = H5Tcopy(H5T_NATIVE_INT); + * status = H5Dread(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf); + * \endcode + * + * <table> + * <tr> + * <td> + * \image html Dtypes_fig28.gif "Layout when an element is skipped" + * </td> + * </tr> + * </table> + * + * \subsection subsec_datatype_text Text Descriptions of Datatypes: Conversion to and from + * + * HDF5 provides a means for generating a portable and human-readable text description of a + * datatype and for generating a datatype from such a text description. This capability is particularly + * useful for creating complex datatypes in a single step, for creating a text description of a datatype + * for debugging purposes, and for creating a portable datatype definition that can then be used to + * recreate the datatype on many platforms or in other applications. + * + * These tasks are handled by two functions provided in the HDF5 Lite high-level library: + * \li #H5LTtext_to_dtype Creates an HDF5 datatype in a single step. + * \li #H5LTdtype_to_text Translates an HDF5 datatype into a text description. + * + * Note that this functionality requires that the HDF5 High-Level Library (H5LT) be installed. + * + * While #H5LTtext_to_dtype can be used to generate any sort of datatype, it is particularly useful + * for complex datatypes. + * + * #H5LTdtype_to_text is most likely to be used in two sorts of situations: when a datatype must be + * closely examined for debugging purpose or to create a portable text description of the datatype + * that can then be used to recreate the datatype on other platforms or in other applications. + * + * These two functions work for all valid HDF5 datatypes except time, bitfield, and reference + * datatypes. + * + * The currently supported text format used by #H5LTtext_to_dtype and #H5LTdtype_to_text is the + * data description language (DDL) and conforms to the \ref DDLBNF110. The portion of the + * \ref DDLBNF110 that defines HDF5 datatypes appears below. + * <em>The definition of HDF5 datatypes from the HDF5 DDL</em> + * \code + * <datatype> ::= <atomic_type> | <compound_type> | <variable_length_type> | <array_type> + * + * <atomic_type> ::= <integer> | <float> | <time> | <string> | + * <bitfield> | <opaque> | <reference> | <enum> + * <integer> ::= H5T_STD_I8BE | H5T_STD_I8LE | + * H5T_STD_I16BE | H5T_STD_I16LE | + * H5T_STD_I32BE | H5T_STD_I32LE | + * H5T_STD_I64BE | H5T_STD_I64LE | + * H5T_STD_U8BE | H5T_STD_U8LE | + * H5T_STD_U16BE | H5T_STD_U16LE | + * H5T_STD_U32BE | H5T_STD_U32LE | + * H5T_STD_U64BE | H5T_STD_U64LE | + * H5T_NATIVE_CHAR | H5T_NATIVE_UCHAR | + * H5T_NATIVE_SHORT | H5T_NATIVE_USHORT | + * H5T_NATIVE_INT | H5T_NATIVE_UINT | + * H5T_NATIVE_LONG | H5T_NATIVE_ULONG | + * H5T_NATIVE_LLONG | H5T_NATIVE_ULLONG + * <float> ::= H5T_IEEE_F32BE | H5T_IEEE_F32LE | + * H5T_IEEE_F64BE | H5T_IEEE_F64LE | + * H5T_NATIVE_FLOAT | H5T_NATIVE_DOUBLE | + * H5T_NATIVE_LDOUBLE + * <time> ::= H5T_TIME: not yet implemented + * <string> ::= H5T_STRING { + * STRSIZE <strsize> ; + * STRPAD <strpad> ; + * CSET <cset> ; + * CTYPE <ctype> ; + * } + * <strsize> ::= <int_value> + * <strpad> ::= H5T_STR_NULLTERM | H5T_STR_NULLPAD | H5T_STR_SPACEPAD + * <cset> ::= H5T_CSET_ASCII | H5T_CSET_UTF8 + * <ctype> ::= H5T_C_S1 | H5T_FORTRAN_S1 + * + * <bitfield> ::= H5T_STD_B8BE | H5T_STD_B8LE | + * H5T_STD_B16BE | H5T_STD_B16LE | + * H5T_STD_B32BE | H5T_STD_B32LE | + * H5T_STD_B64BE | H5T_STD_B64LE + * + * <opaque> ::= H5T_OPAQUE { + * OPAQUE_TAG <identifier>; + * OPAQUE_SIZE <int_value>;opt + * } + * + * <reference> ::= H5T_REFERENCE { <ref_type> } + * <ref_type> ::= H5T_STD_REF_OBJECT | H5T_STD_REF_DSETREG + * + * <compound_type> ::= H5T_COMPOUND { + * <member_type_def>+ + * } + * <member_type_def> ::= <datatype> <field_name>; + * <field_name> ::= <identifier> + * + * <variable_length_type> ::= H5T_VLEN { <datatype> } + * + * <array_type> ::= H5T_ARRAY { <dim_sizes> <datatype> } + * <dim_sizes> ::= '['<dimsize>']' | '['<dimsize>']'<dim_sizes> + * <dimsize> ::= <int_value> + * + * <enum> ::= H5T_ENUM { + * <enum_base_type> <enum_def>+ + * } + * <enum_base_type> ::= <integer> + * // Currently enums can only hold integer type data, but they may be expanded + * // in the future to hold any datatype + * <enum_def> ::= <enum_symbol> <enum_val>; + * <enum_symbol> ::= <identifier> + * <enum_val> ::= <int_value> + * \endcode + * + * <em> Old definitions of the opaque and compound datatypes</em> + * \code + * <opaque> ::= H5T_OPAQUE { <identifier> } + * <compound_type> ::= H5T_COMPOUND { <member_type_def>+ } + * <member_type_def> ::= <datatype> <field_name> ; + * <field_name> ::= <identifier> + * \endcode + * + * <h4>Examples</h4> + * The code sample below illustrates the use of #H5LTtext_to_dtype to generate a variable-length + * string datatype. + * + * <em>Creating a variable-length string datatype from a text description</em> + * \code + * hid_t dtype; + * if((dtype = H5LTtext_to_dtype( + * “H5T_STRING { + * STRSIZE H5T_VARIABLE; + * STRPAD H5T_STR_NULLPAD; + * CSET H5T_CSET_ASCII; + * CTYPE H5T_C_S1; + * }”, H5LT_DDL)) < 0) + * goto out; + * \endcode + * + * The code sample below illustrates the use of #H5LTtext_to_dtype to generate a complex array + * datatype. + * + * <em>Creating a complex array datatype from a text description</em> + * \code + * hid_t dtype; + * if((dtype = H5LTtext_to_dtype( + * “H5T_ARRAY { [5][7][13] H5T_ARRAY + * { [17][19] H5T_COMPOUND + * { + * H5T_STD_I8BE \“arr_compound_1\”; + * H5T_STD_I32BE \“arr_compound_2\”; + * } + * } + * }”, H5LT_DDL))<0) + * goto out; + * \endcode + * + * Previous Chapter \ref sec_dataset - Next Chapter \ref sec_dataspace + * + */ + +/** + * \defgroup H5T Datatypes (H5T) * * Use the functions in this module to manage HDF5 datatypes. * diff --git a/src/H5VLmodule.h b/src/H5VLmodule.h index 8fcb961..fa03e85 100644 --- a/src/H5VLmodule.h +++ b/src/H5VLmodule.h @@ -27,7 +27,97 @@ #define H5_MY_PKG_ERR H5E_VOL #define H5_MY_PKG_INIT YES -/**\defgroup H5VL H5VL +/** \page H5VL_UG The HDF5 VOL plugin + * + * \section sec_vol The HDF5 VOL plugin + * + * \section subsec_vol_intro Introduction + * The virtual object layer is an abstraction layer in the HDF5 library that intercepts all API calls + * that could potentially access objects in an HDF5 container and forwards those calls to a VOL connector, + * which implements the storage. The user or application gets the benefit of using the familiar and + * widely-used HDF5 data model and API, but can map the physical storage of the HDF5 file and objects + * to storage that better meets the application's data needs. + * + * \section subsec_vol_abstract_layer The VOL Abstraction Layer + * The VOL lies just under the public API. When a storage-oriented public APIcall is made, the library + * performs a few sanity checks on the input parameters and then immediately invokes a VOL callback, + * which resolves to an implementation in the VOL connector that was selected when opening or creating + * the file. The VOL connector then performs whatever operations are needed before control returns to the + * library, where any final library operations such as assigning IDs for newly created/opened datasets are + * performed before returning. This means that, for calls that utilize the VOL, all of the functionality + * is deferred to the VOL connector and the HDF5 library does very little work. An important consideration + * of this is that most of the HDF5 caching layers (metadata and chunk caches, page buffering, etc.) will + * not be available as those are implemented in the HDF5 native VOL connector and cannot be easily reused + * by external connectors. + * + * <table> + * <tr> + * <td> + * \image html V_fig1.gif "The VOL Architecture" + * </td> + * </tr> + * </table> + * + * Not all public HDF5 API calls pass through the VOL. Only calls which require manipulating storage go + * through the VOL and require a VOL connector authorto implement the appropriate callback. Dataspace, + * property list, error stack, etc. calls have nothing to do with storage manipulation or querying and + * do not use the VOL. This may be confusing when it comes to property list calls, since many of those + * calls set properties for storage. Property lists are just collections of key-value pairs, though, so + * a particular VOL connector is not required to set or get properties. + * + * Another thing to keep in mind is that not every VOL connector will implement the full HDF5 public API. + * In some cases, a particular feature like variable-length types may not have been developed yet or may + * not have an equivalent in the target storage system. Also, many HDF5 public API calls are specific to + * the native HDF5 file format and are unlikely to have any use in other VOL connectors. A + * feature/capabilities flag scheme is being developed to help navigate this. + * + * For more information about which calls go through the VOL and the mechanism by which this is implemented, + * see the connector author and library internals documentation. + * + * \section subsec_vol_connect VOL Connectors + * A VOL connector can be implemented in several ways: + * \li as a shared or static library linked to an application + * \li as a dynamically loaded plugin, implemented as a shared library + * \li and even as an internal connector, built into the HDF5 libraryitself + * + * This section mostly focuses on external connectors, both libraries and plugins, as those are expected + * to be much more common than internal implementations. + * + * A list of VOL connectors can be found here: + * <a href="https://portal.hdfgroup.org/display/support/Registered+VOL+Connectors"> + * Registered VOL Connectors</a> + * + * This list is incomplete and only includes the VOL connectors that have been registered with + * The HDF Group. + * + * Not every connector in this collection is actively maintained by The HDF Group. It simply serves as a + * single location where important VOL connectors can be found. See the documentation in a connector's + * repository to determine its development status and the parties responsible for it. + * + * A VOL template that contains build scripts (Autotools and CMake) and an empty VOL connector "shell" + * which can be copied and used as a starting point for building new connectors is located here: + * <a href="https://github.com/HDFGroup/vol-template">VOL Connector Template</a> + * + * This template VOL connector is for use in constructing terminal VOL connectors that do not forward + * calls to an underlying connector. The external pass-through VOL connector listed on the registered + * connector page can be used as a starting point for pass-through connectors. + * + * The only current (non-test) internal VOL connector distributed with the library is the native file + * format connector (the "native VOL connector") which contains the code that handles native HDF5 (*.h5/hdf5) + * files. In other words, even the canonical HDF5 file format is implemented via the VOL, making it a core + * part of the HDF5 library and not an optional component which could be disabled. + * + * It has not been completely abstracted from the HDF5 library, though, and is treated as a special case. + * For example, it cannot be unloaded and is always present. + * + * \section subsec_vol_use Connector Use + * + * Previous Chapter \ref sec_plist - Next Chapter \ref sec_map + * + */ + +/** + *\defgroup H5VL VOL connector (H5VL) * * \todo Describe the VOL plugin life cycle. * diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index a55c2b98..cb02668 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -328,7 +328,7 @@ H5_DLL herr_t H5VLunregister_connector(hid_t connector_id); * \obj_id * \param[in] subcls VOL subclass * \param[in] opt_type Option type - * \param[out] flags Operation flags + * \param[out] supported Operation flags * \return \herr_t * * \since 1.12.0 diff --git a/src/H5Zmodule.h b/src/H5Zmodule.h index 9312b72..b3a52fd 100644 --- a/src/H5Zmodule.h +++ b/src/H5Zmodule.h @@ -29,7 +29,8 @@ #define H5_MY_PKG_ERR H5E_PLINE #define H5_MY_PKG_INIT YES -/**\defgroup H5Z H5Z +/** + * \defgroup H5Z Filters (H5Z) * * Use the functions in this module to manage HDF5 filters. * diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h index c2f616f..c7d9b3a 100644 --- a/src/H5Zpublic.h +++ b/src/H5Zpublic.h @@ -445,7 +445,7 @@ typedef struct H5Z_class2_t { * H5Z_class2_t, depending on the needs of the application. To affect * only this macro, H5Z_class_t_vers may be defined to either 1 or 2. * Otherwise, it will behave in the same manner as other API - * compatibility macros. See API Compatibility Macros in HDF5 for more + * compatibility macros. \see \ref api-compat-macros for more * information. H5Z_class1_t matches the #H5Z_class_t structure that is * used in the 1.6.x versions of the HDF5 library. * diff --git a/src/H5module.h b/src/H5module.h index f7d3cd6..466c0fa 100644 --- a/src/H5module.h +++ b/src/H5module.h @@ -26,7 +26,1409 @@ #define H5_MY_PKG_ERR H5E_LIB #define H5_MY_PKG_INIT YES -/**\defgroup H5 H5 +/** \page H5DM_UG The HDF5 Data Model and File Structure + * + * \section sec_data_model The HDF5 Data Model and File Structure + * \subsection subsec_data_model_intro Introduction + * The Hierarchical Data Format (HDF) implements a model for managing and storing data. The + * model includes an abstract data model and an abstract storage model (the data format), and + * libraries to implement the abstract model and to map the storage model to different storage + * mechanisms. The HDF5 library provides a programming interface to a concrete implementation + * of the abstract models. The library also implements a model of data transfer, an efficient + * movement of data from one stored representation to another stored representation. The figure + * below illustrates the relationships between the models and implementations. This chapter + * explains these models in detail. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig1.gif "HDF5 models and implementations" + * </td> + * </tr> + * </table> + * + * The <em>Abstract Data Model</em> is a conceptual model of data, data types, and data organization. The + * abstract data model is independent of storage medium or programming environment. The + * <em>Storage Model</em> is a standard representation for the objects of the abstract data model. The + * <a href="https://docs.hdfgroup.org/hdf5/develop/_s_p_e_c.html">HDF5 File Format Specification</a> + * defines the storage model. + * + * The <em>Programming Model</em> is a model of the computing environment and includes platforms from + * small single systems to large multiprocessors and clusters. The programming model manipulates + * (instantiates, populates, and retrieves) objects from the abstract data model. + * + * The <em>Library</em> is the concrete implementation of the programming model. The library exports the + * HDF5 APIs as its interface. In addition to implementing the objects of the abstract data model, + * the library manages data transfers from one stored form to another. Data transfer examples + * include reading from disk to memory and writing from memory to disk. + * + * <em>Stored Data</em> is the concrete implementation of the storage model. The <em>Storage Model</em> + * is mapped to several storage mechanisms including single disk files, multiple files (family of files), + * and memory representations. + * + * The HDF5 library is a C module that implements the programming model and abstract data + * model. The HDF5 library calls the operating system or other storage management software (for + * example, the MPI/IO Library) to store and retrieve persistent data. The HDF5 library may also + * link to other software such as filters for compression. The HDF5 library is linked to an + * application program which may be written in C, C++, Fortran, or Java. The application program + * implements problem specific algorithms and data structures and calls the HDF5 library to store + * and retrieve data. The figure below shows the dependencies of these modules. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig2.gif "The library, the application program, and other modules" + * </td> + * </tr> + * </table> + * + * It is important to realize that each of the software components manages data using models and + * data structures that are appropriate to the component. When data is passed between layers + * (during storage or retrieval), it is transformed from one representation to another. The figure + * below suggests some of the kinds of data structures used in the different layers. + * + * The <em>Application Program</em> uses data structures that represent the problem and algorithms + * including variables, tables, arrays, and meshes among other data structures. Depending on its + * design and function, an application may have quite a few different kinds of data structures and + * different numbers and sizes of objects. + * + * The <em>HDF5 Library</em> implements the objects of the HDF5 abstract data model. Some of these + * objects include groups, datasets, and attributes. The application program maps the application + * data structures to a hierarchy of HDF5 objects. Each application will create a mapping best + * suited to its purposes. + * + * The objects of the HDF5 abstract data model are mapped to the objects of the HDF5 storage + * model, and stored in a storage medium. The stored objects include header blocks, free lists, data + * blocks, B-trees, and other objects. Each group or dataset is stored as one or more header and data + * blocks. + * @see <a href="https://docs.hdfgroup.org/hdf5/develop/_s_p_e_c.html">HDF5 File Format Specification</a> + * for more information on how these objects are organized. The HDF5 library can also use other + * libraries and modules such as compression. + * + * <table> + * <caption>Data structures in different layers</caption> + * <tr> + * <td> + * \image html Dmodel_fig3_a.gif + * </td> + * <td> + * \image html Dmodel_fig2.gif + * </td> + * <td> + * \image html Dmodel_fig3_c.gif + * </td> + * </tr> + * </table> + * + * The important point to note is that there is not necessarily any simple correspondence between + * the objects of the application program, the abstract data model, and those of the Format + * Specification. The organization of the data of application program, and how it is mapped to the + * HDF5 abstract data model is up to the application developer. The application program only + * needs to deal with the library and the abstract data model. Most applications need not consider + * any details of the + * <a href="https://docs.hdfgroup.org/hdf5/develop/_s_p_e_c.html">HDF5 File Format Specification</a> + * or the details of how objects of abstract data model are translated to and from storage. + * + * \subsection subsec_data_model_abstract The Abstract Data Model + * The abstract data model (ADM) defines concepts for defining and describing complex data + * stored in files. The ADM is a very general model which is designed to conceptually cover many + * specific models. Many different kinds of data can be mapped to objects of the ADM, and + * therefore stored and retrieved using HDF5. The ADM is not, however, a model of any particular + * problem or application domain. Users need to map their data to the concepts of the ADM. + * + * The key concepts include: + * <ul><li>@ref subsubsec_data_model_abstract_file - a contiguous string of bytes in a computer + * store (memory, disk, etc.), and the bytes represent zero or more objects of the model</li> + * <li>@ref subsubsec_data_model_abstract_group - a collection of objects (including groups)</li> + * <li>@ref subsubsec_data_model_abstract_dataset - a multidimensional array of data elements with + * attributes and other metadata</li> + * <li>@ref subsubsec_data_model_abstract_space - a description of the dimensions of a multidimensional + * array</li> + * <li>@ref subsubsec_data_model_abstract_type - a description of a specific class of data element + * including its storage layout as a pattern of bits</li> + * <li>@ref subsubsec_data_model_abstract_attr - a named data value associated with a group, + * dataset, or named datatype</li> + * <li>@ref subsubsec_data_model_abstract_plist - a collection of parameters (some permanent and + * some transient) controlling options in the library</li> + * <li>@ref subsubsec_data_model_abstract_link - the way objects are connected</li></ul> + * + * These key concepts are described in more detail below. + * + * \subsubsection subsubsec_data_model_abstract_file File + * Abstractly, an HDF5 file is a container for an organized collection of objects. The objects are + * groups, datasets, and other objects as defined below. The objects are organized as a rooted, + * directed graph. Every HDF5 file has at least one object, the root group. See the figure below. All + * objects are members of the root group or descendants of the root group. + * + * <table> + * <caption>The HDF5 file</caption> + * <tr> + * <td> + * \image html Dmodel_fig4_b.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Dmodel_fig4_a.gif + * </td> + * </tr> + * </table> + * + * HDF5 objects have a unique identity within a single HDF5 file and can be accessed only by their + * names within the hierarchy of the file. HDF5 objects in different files do not necessarily have + * unique identities, and it is not possible to access a permanent HDF5 object except through a file. + * For more information, see \ref subsec_data_model_structure. + * + * When the file is created, the file creation properties specify settings for the file. The file creation + * properties include version information and parameters of global data structures. When the file is + * opened, the file access properties specify settings for the current access to the file. File access + * properties include parameters for storage drivers and parameters for caching and garbage + * collection. The file creation properties are set permanently for the life of the file, and the file + * access properties can be changed by closing and reopening the file. + * + * An HDF5 file can be “mounted” as part of another HDF5 file. This is analogous to Unix file + * system mounts. The root of the mounted file is attached to a group in the mounting file, and all + * the contents can be accessed as if the mounted file were part of the mounting file. + * + * @see @ref sec_file. + * + * \subsubsection subsubsec_data_model_abstract_group Group + * An HDF5 group is analogous to a file system directory. Abstractly, a group contains zero or + * more objects, and every object must be a member of at least one group. The root group is a + * special case; it may not be a member of any group. + * + * Group membership is actually implemented via link objects. See the figure below. A link object + * is owned by a group and points to a named object. Each link has a name, and each link points to + * exactly one object. Each named object has at least one and possibly many links to it. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig5.gif "Group membership via link objects" + * </td> + * </tr> + * </table> + * + * There are three classes of named objects: group, dataset, and committed (named) datatype. See + * the figure below. Each of these objects is the member of at least one group, and this means there + * is at least one link to it. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig6.gif "Classes of named objects" + * </td> + * </tr> + * </table> + * + * @see @ref sec_group. + * + * \subsubsection subsubsec_data_model_abstract_dataset Dataset + * An HDF5 dataset is a multidimensional (rectangular) array of data elements. See the figure + * below. The shape of the array (number of dimensions, size of each dimension) is described by + * the dataspace object (described in the next section below). + * + * A data element is a single unit of data which may be a number, a character, an array of numbers + * or characters, or a record of heterogeneous data elements. A data element is a set of bits. The + * layout of the bits is described by the datatype (see below). + * + * The dataspace and datatype are set when the dataset is created, and they cannot be changed for + * the life of the dataset. The dataset creation properties are set when the dataset is created. The + * dataset creation properties include the fill value and storage properties such as chunking and + * compression. These properties cannot be changed after the dataset is created. + * + * The dataset object manages the storage and access to the data. While the data is conceptually a + * contiguous rectangular array, it is physically stored and transferred in different ways depending + * on the storage properties and the storage mechanism used. The actual storage may be a set of + * compressed chunks, and the access may be through different storage mechanisms and caches. + * The dataset maps between the conceptual array of elements and the actual stored data. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig7_b.gif "The dataset" + * </td> + * </tr> + * </table> + * + * @see @ref sec_dataset. + * + * \subsubsection subsubsec_data_model_abstract_space Dataspace + * The HDF5 dataspace describes the layout of the elements of a multidimensional array. + * Conceptually, the array is a hyper-rectangle with one to 32 dimensions. HDF5 dataspaces can be + * extendable. Therefore, each dimension has a current size and a maximum size, and the maximum + * may be unlimited. The dataspace describes this hyper-rectangle: it is a list of dimensions with + * the current and maximum (or unlimited) sizes. See the figure below. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig8.gif "The dataspace" + * </td> + * </tr> + * </table> + * + * Dataspace objects are also used to describe hyperslab selections from a dataset. Any subset of the + * elements of a dataset can be selected for read or write by specifying a set of hyperslabs. A + * non-rectangular region can be selected by the union of several (rectangular) dataspaces. + * + * @see @ref sec_dataspace. + * + * \subsubsection subsubsec_data_model_abstract_type Datatype + * The HDF5 datatype object describes the layout of a single data element. A data element is a + * single element of the array; it may be a single number, a character, an array of numbers or + * carriers, or other data. The datatype object describes the storage layout of this data. + * + * Data types are categorized into 11 classes of datatype. Each class is interpreted according to a set + * of rules and has a specific set of properties to describe its storage. For instance, floating point + * numbers have exponent position and sizes which are interpreted according to appropriate + * standards for number representation. Thus, the datatype class tells what the element means, and + * the datatype describes how it is stored. + * + * The figure below shows the classification of datatypes. Atomic datatypes are indivisible. Each + * may be a single object such as a number or a string. Composite datatypes are composed of + * multiple elements of atomic datatypes. In addition to the standard types, users can define + * additional datatypes such as a 24-bit integer or a 16-bit float. + * A dataset or attribute has a single datatype object associated with it. See Figure 7 above. The + * datatype object may be used in the definition of several objects, but by default, a copy of the + * datatype object will be private to the dataset. + * + * Optionally, a datatype object can be stored in the HDF5 file. The datatype is linked into a group, + * and therefore given a name. A committed datatype (formerly called a named datatype) can be + * opened and used in any way that a datatype object can be used. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig9.gif "Datatype classifications" + * </td> + * </tr> + * </table> + * + * @see @ref sec_datatype. + * + * \subsubsection subsubsec_data_model_abstract_attr Attribute + * Any HDF5 named data object (group, dataset, or named datatype) may have zero or more user + * defined attributes. Attributes are used to document the object. The attributes of an object are + * stored with the object. + * + * An HDF5 attribute has a name and data. The data portion is similar in structure to a dataset: a + * dataspace defines the layout of an array of data elements, and a datatype defines the storage + * layout and interpretation of the elements See the figure below. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig10.gif "Attribute data elements" + * </td> + * </tr> + * </table> + * + * In fact, an attribute is very similar to a dataset with the following limitations: + * <ul><li>An attribute can only be accessed via the object</li> + * <li>Attribute names are significant only within the object</li> + * <li>An attribute should be a small object</li> + * <li>The data of an attribute must be read or written in a single access (partial reading or + * writing is not allowed)</li> + * <li>Attributes do not have attributes</li></ul> + * + * Note that the value of an attribute can be an object reference. A shared attribute or an attribute + * that is a large array can be implemented as a reference to a dataset. + * + * The name, dataspace, and datatype of an attribute are specified when it is created and cannot be + * changed over the life of the attribute. An attribute can be opened by name, by index, or by + * iterating through all the attributes of the object. + * + * @see @ref sec_attribute. + * + * \subsubsection subsubsec_data_model_abstract_plist Property List + * HDF5 has a generic property list object. Each list is a collection of name-value pairs. Each class + * of property list has a specific set of properties. Each property has an implicit name, a datatype, + * and a value. See the figure below. A property list object is created and used in ways similar to + * the other objects of the HDF5 library. + * + * Property Lists are attached to the object in the library, and they can be used by any part of the + * library. Some properties are permanent (for example, the chunking strategy for a dataset), others + * are transient (for example, buffer sizes for data transfer). A common use of a Property List is to + * pass parameters from the calling program to a VFL driver or a module of the pipeline. + * + * Property lists are conceptually similar to attributes. Property lists are information relevant to the + * behavior of the library while attributes are relevant to the user’s data and application. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig11_b.gif "The property list" + * </td> + * </tr> + * </table> + * + * Property lists are used to control optional behavior for file creation, file access, dataset creation, + * dataset transfer (read, write), and file mounting. Some property list classes are shown in the table + * below. Details of the different property lists are explained in the relevant sections of this + * document. + * + * <table> + * <caption>Property list classes and their usage</caption> + * <tr> + * <th>Property List Class</th> + * <th>Used</th> + * <th>Examples</th> + * </tr> + * <tr> + * <td>#H5P_FILE_CREATE</td> + * <td>Properties for file creation.</td> + * <td>Set size of user block.</td> + * </tr> + * <tr> + * <td>#H5P_FILE_ACCESS</td> + * <td>Properties for file access.</td> + * <td>Set parameters for VFL driver. An example is MPI I/O. </td> + * </tr> + * <tr> + * <td>#H5P_DATASET_CREATE</td> + * <td>Properties for dataset creation.</td> + * <td>Set chunking, compression, or fill value.</td> + * </tr> + * <tr> + * <td>#H5P_DATASET_XFER</td> + * <td>Properties for raw data transfer (read and write).</td> + * <td>Tune buffer sizes or memory management.</td> + * </tr> + * <tr> + * <td>#H5P_FILE_MOUNT</td> + * <td>Properties for file mounting.</td> + * <td></td> + * </tr> + * </table> + * + * @see @ref sec_plist. + * + * \subsubsection subsubsec_data_model_abstract_link Link + * This section is under construction. + * + * \subsection subsec_data_model_storage The HDF5 Storage Model + * \subsubsection subsubsec_data_model_storage_spec The Abstract Storage Model: the HDF5 Format Specification + * The <a href="https://docs.hdfgroup.org/hdf5/develop/_s_p_e_c.html">HDF5 File Format Specification</a> + * defines how HDF5 objects and data are mapped to a linear + * address space. The address space is assumed to be a contiguous array of bytes stored on some + * random access medium. The format defines the standard for how the objects of the abstract data + * model are mapped to linear addresses. The stored representation is self-describing in the sense + * that the format defines all the information necessary to read and reconstruct the original objects + * of the abstract data model. + * + * The HDF5 File Format Specification is organized in three parts: + * <ul><li>Level 0: File signature and super block</li> + * <li>Level 1: File infrastructure</li> + * <ul><li>Level 1A: B-link trees and B-tree nodes</li> + * <li>Level 1B: Group</li> + * <li>Level 1C: Group entry</li> + * <li>Level 1D: Local heaps</li> + * <li>Level 1E: Global heap</li> + * <li>Level 1F: Free-space index</li></ul> + * <li>Level 2: Data object</li> + * <ul><li>Level 2A: Data object headers</li> + * <li>Level 2B: Shared data object headers</li> + * <li>Level 2C: Data object data storage</li></ul></ul> + * + * The Level 0 specification defines the header block for the file. Header block elements include a + * signature, version information, key parameters of the file layout (such as which VFL file drivers + * are needed), and pointers to the rest of the file. Level 1 defines the data structures used + * throughout the file: the B-trees, heaps, and groups. Level 2 defines the data structure for storing + * the data objects and data. In all cases, the data structures are completely specified so that every + * bit in the file can be faithfully interpreted. + * + * It is important to realize that the structures defined in the HDF5 file format are not the same as + * the abstract data model: the object headers, heaps, and B-trees of the file specification are not + * represented in the abstract data model. The format defines a number of objects for managing the + * storage including header blocks, B-trees, and heaps. The HDF5 File Format Specification defines + * how the abstract objects (for example, groups and datasets) are represented as headers, B-tree + * blocks, and other elements. + * + * The HDF5 library implements operations to write HDF5 objects to the linear format and to read + * from the linear format to create HDF5 objects. It is important to realize that a single HDF5 + * abstract object is usually stored as several objects. A dataset, for example, might be stored in a + * header and in one or more data blocks, and these objects might not be contiguous on the hard + * disk. + * + * \subsubsection subsubsec_data_model_storage_imple Concrete Storage Model + * The HDF5 file format defines an abstract linear address space. This can be implemented in + * different storage media such as a single file or multiple files on disk or in memory. The HDF5 + * Library defines an open interface called the Virtual File Layer (VFL). The VFL allows different + * concrete storage models to be selected. + * + * The VFL defines an abstract model, an API for random access storage, and an API to plug in + * alternative VFL driver modules. The model defines the operations that the VFL driver must and + * may support, and the plug-in API enables the HDF5 library to recognize the driver and pass it + * control and data. + * + * A number of VFL drivers have been defined in the HDF5 library. Some work with a single file, + * and some work with multiple files split in various ways. Some work in serial computing + * environments, and some work in parallel computing environments. Most work with disk copies + * of HDF5 files, but one works with a memory copy. These drivers are listed in the + * \ref table_file_drivers "Supported file drivers" table. + * + * @see @ref subsec_file_alternate_drivers. + * + * Each driver isolates the details of reading and writing storage so that the rest of the HDF5 library + * and user program can be almost the same for different storage methods. The exception to this + * rule is that some VFL drivers need information from the calling application. This information is + * passed using property lists. For example, the Parallel driver requires certain control information + * that must be provided by the application. + * + * \subsection subsec_data_model_structure The Structure of an HDF5 File + * \subsubsection subsubsec_data_model_structure_file Overall File Structure + * An HDF5 file is organized as a rooted, directed graph. Named data objects are the nodes of the + * graph, and links are the directed arcs. Each arc of the graph has a name, and the root group has + * the name “/”. Objects are created and then inserted into the graph with the link operation which + * creates a named link from a group to the object. For example, the figure below illustrates the + * structure of an HDF5 file when one dataset is created. An object can be the target of more than + * one link. The names on the links must be unique within each group, but there may be many links + * with the same name in different groups. Link names are unambiguous: some ancestor will have a + * different name, or they are the same object. The graph is navigated with path names similar to + * Unix file systems. An object can be opened with a full path starting at the root group or with a + * relative path and a starting node (group). Note that all paths are relative to a single HDF5 file. In + * this sense, an HDF5 file is analogous to a single Unix file system. + * + * <table> + * <caption>An HDF5 file with one dataset</caption> + * <tr> + * <td> + * \image html Dmodel_fig12_a.gif + * </td> + * <td> + * \image html Dmodel_fig12_b.gif + * </td> + * </tr> + * </table> + * + * Note: In the figure above are two figures. The top figure represents a newly created file with one + * group, /. In the bottom figure, a dataset called /dset1 has been created. + * + * It is important to note that, just like the Unix file system, HDF5 objects do not have names. The + * names are associated with paths. An object has a unique (within the file) object identifier, but a + * single object may have many names because there may be many paths to the same object. An + * object can be renamed (moved to another group) by adding and deleting links. In this case, the + * object itself never moves. For that matter, membership in a group has no implication for the + * physical location of the stored object. + * + * Deleting a link to an object does not necessarily delete the object. The object remains available + * as long as there is at least one link to it. After all the links to an object are deleted, it can no + * longer be opened although the storage may or may not be reclaimed. + * + * It is important to realize that the linking mechanism can be used to construct very complex + * graphs of objects. For example, it is possible for an object to be shared between several groups + * and even to have more than one name in the same group. It is also possible for a group to be a + * member of itself or to be in a “cycle” in the graph. An example of a cycle is where a child is the + * parent of one of its own ancestors. + * + * \subsubsection subsubsec_data_model_structure_path HDF5 Path Names and Navigation + * The structure of the file constitutes the name space for the objects in the file. A path name is a + * string of components separated by ‘/’. Each component is the name of a link or the special + * character “.” for the current group. Link names (components) can be any string of ASCII + * characters not containing ‘/’ (except the string “.” which is reserved). However, users are advised + * to avoid the use of punctuation and non-printing characters because they may create problems for + * other software. The figure below gives a BNF grammar for HDF5 path names. + * + * <em>A BNF grammar for path names</em> + * \code + * PathName ::= AbsolutePathName | RelativePathName + * Separator ::= "/" ["/"]* + * AbsolutePathName ::= Separator [ RelativePathName ] + * RelativePathName ::= Component [ Separator RelativePathName ]* + * Component ::= "." | Name + * Name ::= Character+ - {"."} + * Character ::= {c: c in {{ legal ASCII characters } - {'/'}} + * \endcode + * + * An object can always be addressed by a full or absolute path which would start at the root group. + * As already noted, a given object can have more than one full path name. An object can also be + * addressed by a relative path which would start at a group and include the path to the object. + * + * The structure of an HDF5 file is “self-describing.” This means that it is possible to navigate the + * file to discover all the objects in the file. Basically, the structure is traversed as a graph starting at + * one node and recursively visiting the nodes of the graph. + * + * \subsubsection subsubsec_data_model_structure_example Examples of HDF5 File Structures + * The figures below show some possible HDF5 file structures with groups and datasets. The first + * figure shows the structure of a file with three groups. The second shows a dataset created in + * “/group1”. The third figure shows the structure after a dataset called dset2 has been added to the + * root group. The fourth figure shows the structure after another group and dataset have been + * added. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig14_a.gif "An HDF5 file structure with groups" + * </td> + * </tr> + * </table> + * + * Note: The figure above shows three groups; /group1 and /group2 are members of the root group. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig14_b.gif "An HDF5 file structure with groups and a dataset" + * </td> + * </tr> + * </table> + * + * Note: The figure above shows that a dataset has been created in /group1: /group1/dset1. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig14_c.gif " An HDF5 file structure with groups and datasets" + * </td> + * </tr> + * </table> + * + * Note: In the figure above, another dataset has been added as a member of the root group: /dset2. + * + * <table> + * <tr> + * <td> + * \image html Dmodel_fig14_c.gif " Another HDF5 file structure with groups and datasets" + * </td> + * </tr> + * </table> + * + * Note: In the figure above, another group and dataset have been added reusing object names: + * <em>/group2/group2/dset2</em>. + * <ol><li>HDF5 requires random access to the linear address space. For this reason it is not + * well suited for some data media such as streams.</li> + * <li>It could be said that HDF5 extends the organizing concepts of a file system to the internal + * structure of a single file.</li> + * <li>As of HDF5-1.4, the storage used for an object is reclaimed, even if all links are + * deleted.</li></ol> + * + * Next Chapter \ref sec_program + * + */ + +/** \page H5_UG The HDF5 Library and Programming Model + * + * \section sec_program The HDF5 Library and Programming Model + * \subsection subsec_program_intro Introduction + * The HDF5 library implements the HDF5 abstract data model and storage model. These models + * were described in the preceding chapter. + * + * Two major objectives of the HDF5 products are to provide tools that can be used on as many + * computational platforms as possible (portability), and to provide a reasonably object-oriented + * data model and programming interface. + * + * To be as portable as possible, the HDF5 library is implemented in portable C. C is not an + * object-oriented language, but the library uses several mechanisms and conventions to implement an + * object model. + * + * One mechanism the HDF5 library uses is to implement the objects as data structures. To refer to + * an object, the HDF5 library implements its own pointers. These pointers are called identifiers. + * An identifier is then used to invoke operations on a specific instance of an object. For example, + * when a group is opened, the API returns a group identifier. This identifier is a reference to that + * specific group and will be used to invoke future operations on that group. The identifier is valid + * only within the context it is created and remains valid until it is closed or the file is closed. This + * mechanism is essentially the same as the mechanism that C++ or other object-oriented languages + * use to refer to objects except that the syntax is C. + * + * Similarly, object-oriented languages collect all the methods for an object in a single name space. + * An example is the methods of a C++ class. The C language does not have any such mechanism, + * but the HDF5 library simulates this through its API naming convention. API function names + * begin with a common prefix that is related to the class of objects that the function operates on. + * The table below lists the HDF5 objects and the standard prefixes used by the corresponding + * HDF5 APIs. For example, functions that operate on datatype objects all have names beginning + * with H5T. + * + * <table> + * <caption>Access flags and modes</caption> + * <tr> + * <th>Prefix</th> + * <th>Operates on</th> + * </tr> + * <tr> + * <td>@ref H5A</td> + * <td>Attributes</td> + * </tr> + * <tr> + * <td>@ref H5D</td> + * <td>Datasets</td> + * </tr> + * <tr> + * <td>@ref H5E</td> + * <td>Error reports</td> + * </tr> + * <tr> + * <td>@ref H5F</td> + * <td>Files</td> + * </tr> + * <tr> + * <td>@ref H5G</td> + * <td>Groups</td> + * </tr> + * <tr> + * <td>@ref H5I</td> + * <td>Identifiers</td> + * </tr> + * <tr> + * <td>@ref H5L</td> + * <td>Links</td> + * </tr> + * <tr> + * <td>@ref H5O</td> + * <td>Objects</td> + * </tr> + * <tr> + * <td>@ref H5P</td> + * <td>Property lists</td> + * </tr> + * <tr> + * <td>@ref H5R</td> + * <td>References</td> + * </tr> + * <tr> + * <td>@ref H5S</td> + * <td>Dataspaces</td> + * </tr> + * <tr> + * <td>@ref H5T</td> + * <td>Datatypes</td> + * </tr> + * <tr> + * <td>@ref H5Z</td> + * <td>Filters</td> + * </tr> + * </table> + * + * \subsection subsec_program_model The HDF5 Programming Model + * In this section we introduce the HDF5 programming model by means of a series of short code + * samples. These samples illustrate a broad selection of common HDF5 tasks. More details are + * provided in the following chapters and in the HDF5 Reference Manual. + * + * \subsubsection subsubsec_program_model_create Creating an HDF5 File + * Before an HDF5 file can be used or referred to in any manner, it must be explicitly created or + * opened. When the need for access to a file ends, the file must be closed. The example below + * provides a C code fragment illustrating these steps. In this example, the values for the file + * creation property list and the file access property list are set to the defaults #H5P_DEFAULT. + * + * <em>Creating and closing an HDF5 file</em> + * \code + * hid_t file; // declare file identifier + * + * // Create a new file using H5F_ACC_TRUNC to truncate and overwrite + * // any file of the same name, default file creation properties, and + * // default file access properties. Then close the file. + * file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + * status = H5Fclose(file); + * \endcode + * + * Note: If there is a possibility that a file of the declared name already exists and you wish to open + * a new file regardless of that possibility, the flag #H5F_ACC_TRUNC will cause the operation to + * overwrite the previous file. If the operation should fail in such a circumstance, use the flag + * #H5F_ACC_EXCL instead. + * + * \subsubsection subsubsec_program_model_dset Creating and Initializing a Dataset + * The essential objects within a dataset are datatype and dataspace. These are independent objects + * and are created separately from any dataset to which they may be attached. Hence, creating a + * dataset requires, at a minimum, the following steps: + * <ol><li>Create and initialize a dataspace for the dataset</li> + * <li>Define a datatype for the dataset</li> + * <li>Create and initialize the dataset</li></ol> + * + * The code in the example below illustrates the execution of these steps. + * + * <em>Create a dataset</em> + * \code + * hid_t dataset, datatype, dataspace; // declare identifiers + * + * // Create a dataspace: Describe the size of the array and + * // create the dataspace for a fixed-size dataset. + * dimsf[0] = NX; + * dimsf[1] = NY; + * dataspace = H5Screate_simple(RANK, dimsf, NULL); + * + * // Define a datatype for the data in the dataset. + * // We will store little endian integers. + * datatype = H5Tcopy(H5T_NATIVE_INT); + * status = H5Tset_order(datatype, H5T_ORDER_LE); + * + * // Create a new dataset within the file using the defined + * // dataspace and datatype and default dataset creation + * // properties. + * // NOTE: H5T_NATIVE_INT can be used as the datatype if + * // conversion to little endian is not needed. + * dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * \subsubsection subsubsec_program_model_close Closing an Object + * An application should close an object such as a datatype, dataspace, or dataset once the object is + * no longer needed. Since each is an independent object, each must be released (or closed) + * separately. This action is frequently referred to as releasing the object’s identifier. The code in + * the example below closes the datatype, dataspace, and dataset that were created in the preceding + * section. + * + * <em>Close an object</em> + * \code + * H5Tclose(datatype); + * H5Dclose(dataset); + * H5Sclose(dataspace); + * \endcode + * + * There is a long list of HDF5 library items that return a unique identifier when the item is created + * or opened. Each time that one of these items is opened, a unique identifier is returned. Closing a + * file does not mean that the groups, datasets, or other open items are also closed. Each opened + * item must be closed separately. + * + * For more information, + * @see <a href="http://www.hdfgroup.org/HDF5/doc/Advanced/UsingIdentifiers/index.html">Using Identifiers</a> + * in the HDF5 Application Developer’s Guide under General Topics in HDF5. + * + * <h4>How Closing a File Effects Other Open Structural Elements</h4> + * Every structural element in an HDF5 file can be opened, and these elements can be opened more + * than once. Elements range in size from the entire file down to attributes. When an element is + * opened, the HDF5 library returns a unique identifier to the application. Every element that is + * opened must be closed. If an element was opened more than once, each identifier that was + * returned to the application must be closed. For example, if a dataset was opened twice, both + * dataset identifiers must be released (closed) before the dataset can be considered closed. Suppose + * an application has opened a file, a group in the file, and two datasets in the group. In order for + * the file to be totally closed, the file, group, and datasets must each be closed. Closing the file + * before the group or the datasets will not affect the state of the group or datasets: the group and + * datasets will still be open. + * + * There are several exceptions to the above general rule. One is when the #H5close function is used. + * #H5close causes a general shutdown of the library: all data is written to disk, all identifiers are + * closed, and all memory used by the library is cleaned up. Another exception occurs on parallel + * processing systems. Suppose on a parallel system an application has opened a file, a group in the + * file, and two datasets in the group. If the application uses the #H5Fclose function to close the file, + * the call will fail with an error. The open group and datasets must be closed before the file can be + * closed. A third exception is when the file access property list includes the property + * #H5F_CLOSE_STRONG. This property closes any open elements when the file is closed with + * #H5Fclose. For more information, see the #H5Pset_fclose_degree function in the HDF5 Reference + * Manual. + * + * \subsubsection subsubsec_program_model_data Writing or Reading a Dataset to or from a File + * Having created the dataset, the actual data can be written with a call to #H5Dwrite. See the + * example below. + * + * <em>Writing a dataset</em> + * \code + * // Write the data to the dataset using default transfer properties. + * status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); + * \endcode + * + * Note that the third and fourth #H5Dwrite parameters in the above example describe the + * dataspaces in memory and in the file, respectively. For now, these are both set to + * #H5S_ALL which indicates that the entire dataset is to be written. The selection of partial datasets + * and the use of differing dataspaces in memory and in storage will be discussed later in this + * chapter and in more detail elsewhere in this guide. + * + * Reading the dataset from storage is similar to writing the dataset to storage. To read an entire + * dataset, substitute #H5Dread for #H5Dwrite in the above example. + * + * \subsubsection subsubsec_program_model_partial Reading and Writing a Portion of a Dataset + * The previous section described writing or reading an entire dataset. HDF5 also supports access to + * portions of a dataset. These parts of datasets are known as selections. + * + * The simplest type of selection is a simple hyperslab. This is an n-dimensional rectangular sub-set + * of a dataset where n is equal to the dataset’s rank. Other available selections include a more + * complex hyperslab with user-defined stride and block size, a list of independent points, or the + * union of any of these. + * + * The figure below shows several sample selections. + * + * <table> + * <caption align=top>Dataset selections</caption> + * <tr> + * <td> + * \image html Pmodel_fig5_a.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Pmodel_fig5_b.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Pmodel_fig5_c.gif + * </td> + * </tr> + * <tr> + * <td> + * \image html Pmodel_fig5_d.gif<br /> + * \image html Pmodel_fig5_e.gif + * </td> + * </tr> + * </table> + * + * Note: In the figure above, selections can take the form of a simple hyperslab, a hyperslab with + * user-defined stride and block, a selection of points, or a union of any of these forms. + * + * Selections and hyperslabs are portions of a dataset. As described above, a simple hyperslab is a + * rectangular array of data elements with the same rank as the dataset’s dataspace. Thus, a simple + * hyperslab is a logically contiguous collection of points within the dataset. + * + * The more general case of a hyperslab can also be a regular pattern of points or blocks within the + * dataspace. Four parameters are required to describe a general hyperslab: the starting coordinates, + * the block size, the stride or space between blocks, and the number of blocks. These parameters + * are each expressed as a one-dimensional array with length equal to the rank of the dataspace and + * are described in the table below. + * + * <table> + * <caption></caption> + * <tr> + * <th>Parameter</th> + * <th>Definition</th> + * </tr> + * <tr> + * <td>start</td> + * <td>The coordinates of the starting location of the hyperslab in the dataset’s dataspace.</td> + * </tr> + * <tr> + * <td>block</td> + * <td>The size of each block to be selected from the dataspace. If the block parameter + * is set to NULL, the block size defaults to a single element in each dimension, as + * if the block array was set to all 1s (all ones). This will result in the selection of a + * uniformly spaced set of count points starting at start and on the interval defined + * by stride.</td> + * </tr> + * <tr> + * <td>stride</td> + * <td>The number of elements separating the starting point of each element or block to + * be selected. If the stride parameter is set to NULL, the stride size defaults to 1 + * (one) in each dimension and no elements are skipped.</td> + * </tr> + * <tr> + * <td>count</td> + * <td>The number of elements or blocks to select along each dimension.</td> + * </tr> + * </table> + * + * <h4>Reading Data into a Differently Shaped Memory Block</h4> + * For maximum flexibility in user applications, a selection in storage can be mapped into a + * differently-shaped selection in memory. All that is required is that the two selections contain the + * same number of data elements. In this example, we will first define the selection to be read from + * the dataset in storage, and then we will define the selection as it will appear in application + * memory. + * + * Suppose we want to read a 3 x 4 hyperslab from a two-dimensional dataset in a file beginning at + * the dataset element <1,2>. The first task is to create the dataspace that describes the overall rank + * and dimensions of the dataset in the file and to specify the position and size of the in-file + * hyperslab that we are extracting from that dataset. See the code below. + * + * <em>Define the selection to be read from storage</em> + * \code + * // Define dataset dataspace in file. + * dataspace = H5Dget_space(dataset); // dataspace identifier + * rank = H5Sget_simple_extent_ndims(dataspace); + * + * status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL); + * + * // Define hyperslab in the dataset. + * offset[0] = 1; + * offset[1] = 2; + * count[0] = 3; + * count[1] = 4; + * status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, count, NULL); + * \endcode + * + * The next task is to define a dataspace in memory. Suppose that we have in memory a + * three-dimensional 7 x 7 x 3 array into which we wish to read the two-dimensional 3 x 4 hyperslab + * described above and that we want the memory selection to begin at the element <3,0,0> and + * reside in the plane of the first two dimensions of the array. Since the in-memory dataspace is + * three-dimensional, we have to describe the in-memory selection as three-dimensional. Since we + * are keeping the selection in the plane of the first two dimensions of the in-memory dataset, the + * in-memory selection will be a 3 x 4 x 1 array defined as <3,4,1>. + * + * Notice that we must describe two things: the dimensions of the in-memory array, and the size + * and position of the hyperslab that we wish to read in. The code below illustrates how this would + * be done. + * + * <em>Define the memory dataspace and selection</em> + * \code + * // Define memory dataspace. + * dimsm[0] = 7; + * dimsm[1] = 7; + * dimsm[2] = 3; + * memspace = H5Screate_simple(RANK_OUT,dimsm,NULL); + * + * // Define memory hyperslab. + * offset_out[0] = 3; + * offset_out[1] = 0; + * offset_out[2] = 0; + * count_out[0] = 3; + * count_out[1] = 4; + * count_out[2] = 1; + * status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, count_out, NULL); + * \endcode + * + * The hyperslab defined in the code above has the following parameters: start=(3,0,0), + * count=(3,4,1), stride and block size are NULL. + * + * <h4>Writing Data into a Differently Shaped Disk Storage Block</h4> + * Now let’s consider the opposite process of writing a selection from memory to a selection in a + * dataset in a file. Suppose that the source dataspace in memory is a 50-element, one-dimensional + * array called vector and that the source selection is a 48-element simple hyperslab that starts at the + * second element of vector. See the figure below. + * + * <table> + * <tr> + * <td> + * \image html Pmodel_fig2.gif "A one-dimensional array" + * </td> + * </tr> + * </table> + * + * Further suppose that we wish to write this data to the file as a series of 3 x 2-element blocks in a + * two-dimensional dataset, skipping one row and one column between blocks. Since the source + * selection contains 48 data elements and each block in the destination selection contains 6 data + * elements, we must define the destination selection with 8 blocks. We will write 2 blocks in the + * first dimension and 4 in the second. The code below shows how to achieve this objective. + * + * <em>The destination selection</em> + * \code + * // Select the hyperslab for the dataset in the file, using + * // 3 x 2 blocks, a (4,3) stride, a (2,4) count, and starting + * // at the position (0,1). + * start[0] = 0; start[1] = 1; + * stride[0] = 4; stride[1] = 3; + * count[0] = 2; count[1] = 4; + * block[0] = 3; block[1] = 2; + * ret = H5Sselect_hyperslab(fid, H5S_SELECT_SET, start, stride, count, block); + * + * // Create dataspace for the first dataset. + * mid1 = H5Screate_simple(MSPACE1_RANK, dim1, NULL); + * + * // Select hyperslab. + * // We will use 48 elements of the vector buffer starting at the + * // second element. Selected elements are 1 2 3 . . . 48 + * start[0] = 1; + * stride[0] = 1; + * count[0] = 48; + * block[0] = 1; + * ret = H5Sselect_hyperslab(mid1, H5S_SELECT_SET, start, stride, count, block); + * + * // Write selection from the vector buffer to the dataset in the file. + * ret = H5Dwrite(dataset, H5T_NATIVE_INT, mid1, fid, H5P_DEFAULT, vector); + * \endcode + * + * \subsubsection subsubsec_program_model_info Getting Information about a Dataset + * Although reading is analogous to writing, it is often first necessary to query a file to obtain + * information about the dataset to be read. For instance, we often need to determine the datatype + * associated with a dataset, or its dataspace (in other words, rank and dimensions). As illustrated in + * the code example below, there are several get routines for obtaining this information. + * + * <em>Routines to get dataset parameters</em> + * \code + * // Get datatype and dataspace identifiers, + * // then query datatype class, order, and size, and + * // then query dataspace rank and dimensions. + * datatype = H5Dget_type (dataset); // datatype identifier + * class = H5Tget_class (datatype); + * if (class == H5T_INTEGER) + * printf("Dataset has INTEGER type \n"); + * + * order = H5Tget_order (datatype); + * if (order == H5T_ORDER_LE) + * printf("Little endian order \n"); + * + * size = H5Tget_size (datatype); + * printf ("Size is %d \n", size); + * + * dataspace = H5Dget_space (dataset); // dataspace identifier + * + * // Find rank and retrieve current and maximum dimension sizes. + * rank = H5Sget_simple_extent_dims (dataspace, dims, max_dims); + * \endcode + * + * \subsubsection subsubsec_program_model_compound Creating and Defining Compound Datatypes + * A compound datatype is a collection of one or more data elements. Each element might be an + * atomic type, a small array, or another compound datatype. + * + * The provision for nested compound datatypes allows these structures to become quite complex. + * An HDF5 compound datatype has some similarities to a C struct or a Fortran common block. + * Though not originally designed with databases in mind, HDF5 compound datatypes are + * sometimes used in a way that is similar to a database record. Compound datatypes can become + * either a powerful tool or a complex and difficult-to-debug construct. Reasonable caution is + * advised. + * + * To create and use a compound datatype, you need to create a datatype with class compound + * (#H5T_COMPOUND) and specify the total size of the data element in bytes. A compound + * datatype consists of zero or more uniquely named members. Members can be defined in any + * order but must occupy non-overlapping regions within the datum. The table below lists the + * properties of compound datatype members. + * + * <table> + * <caption></caption> + * <tr> + * <th>Parameter</th> + * <th>Definition</th> + * </tr> + * <tr> + * <td>Index</td> + * <td>An index number between zero and N-1, where N is the number of + * members in the compound. The elements are indexed in the order of their + * location in the array of bytes.</td> + * </tr> + * <tr> + * <td>Name</td> + * <td>A string that must be unique within the members of the same datatype.</td> + * </tr> + * <tr> + * <td>Datatype</td> + * <td>An HDF5 datatype.</td> + * </tr> + * <tr> + * <td>Offset</td> + * <td>A fixed byte offset which defines the location of the first byte of that + * member in the compound datatype.</td> + * </tr> + * </table> + * + * Properties of the members of a compound datatype are defined when the member is added to the + * compound type. These properties cannot be modified later. + * + * <h4>Defining Compound Datatypes</h4> + * Compound datatypes must be built out of other datatypes. To do this, you first create an empty + * compound datatype and specify its total size. Members are then added to the compound datatype + * in any order. + * + * Each member must have a descriptive name. This is the key used to uniquely identify the + * member within the compound datatype. A member name in an HDF5 datatype does not + * necessarily have to be the same as the name of the corresponding member in the C struct in + * memory although this is often the case. You also do not need to define all the members of the C + * struct in the HDF5 compound datatype (or vice versa). + * + * Usually a C struct will be defined to hold a data point in memory, and the offsets of the members + * in memory will be the offsets of the struct members from the beginning of an instance of the + * struct. The library defines the macro that computes the offset of member m within a struct + * variable s: + * \code + * HOFFSET(s,m) + * \endcode + * + * The code below shows an example in which a compound datatype is created to describe complex + * numbers whose type is defined by the complex_t struct. + * + * <em>A compound datatype for complex numbers</em> + * \code + * Typedef struct { + * double re; //real part + * double im; //imaginary part + * } complex_t; + * + * complex_t tmp; //used only to compute offsets + * hid_t complex_id = H5Tcreate (H5T_COMPOUND, sizeof tmp); + * H5Tinsert (complex_id, "real", HOFFSET(tmp,re), H5T_NATIVE_DOUBLE); + * H5Tinsert (complex_id, "imaginary", HOFFSET(tmp,im), H5T_NATIVE_DOUBLE); + * \endcode + * + * \subsubsection subsubsec_program_model_extend Creating and Writing Extendable Datasets + * An extendable dataset is one whose dimensions can grow. One can define an HDF5 dataset to + * have certain initial dimensions with the capacity to later increase the size of any of the initial + * dimensions. For example, the figure below shows a 3 x 3 dataset (a) which is later extended to + * be a 10 x 3 dataset by adding 7 rows (b), and further extended to be a 10 x 5 dataset by adding + * two columns (c). + * + * <table> + * <tr> + * <td> + * \image html Pmodel_fig3.gif "Extending a dataset" + * </td> + * </tr> + * </table> + * + * HDF5 requires the use of chunking when defining extendable datasets. Chunking makes it + * possible to extend datasets efficiently without having to reorganize contiguous storage + * excessively. + * + * To summarize, an extendable dataset requires two conditions: + * <ol><li>Define the dataspace of the dataset as unlimited in all dimensions that might eventually be + * extended</li> + * <li>Enable chunking in the dataset creation properties</li></ol> + * + * For example, suppose we wish to create a dataset similar to the one shown in the figure above. + * We want to start with a 3 x 3 dataset, and then later we will extend it. To do this, go through the + * steps below. + * + * First, declare the dataspace to have unlimited dimensions. See the code shown below. Note the + * use of the predefined constant #H5S_UNLIMITED to specify that a dimension is unlimited. + * + * <em>Declaring a dataspace with unlimited dimensions</em> + * \code + * // dataset dimensions at creation time + * hsize_t dims[2] = {3, 3}; + * hsize_t maxdims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; + * + * // Create the data space with unlimited dimensions. + * dataspace = H5Screate_simple(RANK, dims, maxdims); + * \endcode + * + * Next, set the dataset creation property list to enable chunking. See the code below. + * + * <em>Enable chunking</em> + * \code + * hid_t cparms; + * hsize_t chunk_dims[2] ={2, 5}; + * + * // Modify dataset creation properties to enable chunking. + * cparms = H5Pcreate (H5P_DATASET_CREATE); + * status = H5Pset_chunk(cparms, RANK, chunk_dims); + * \endcode + * + * The next step is to create the dataset. See the code below. + * + * <em>Create a dataset</em> + * \code + * // Create a new dataset within the file using cparms creation properties. + * dataset = H5Dcreate(file, DATASETNAME, H5T_NATIVE_INT, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + * \endcode + * + * Finally, when the time comes to extend the size of the dataset, invoke #H5Dextend. Extending the + * dataset along the first dimension by seven rows leaves the dataset with new dimensions of + * <10,3>. See the code below. + * + * <em>Extend the dataset by seven rows</em> + * \code + * // Extend the dataset. Dataset becomes 10 x 3. + * dims[0] = dims[0] + 7; + * size[0] = dims[0]; + * size[1] = dims[1]; + * + * status = H5Dextend (dataset, size); + * \endcode + * + * \subsubsection subsubsec_program_model_group Creating and Working with Groups + * Groups provide a mechanism for organizing meaningful and extendable sets of datasets within + * an HDF5 file. The @ref H5G API provides several routines for working with groups. + * + * <h4>Creating a Group</h4> + * With no datatype, dataspace, or storage layout to define, creating a group is considerably simpler + * than creating a dataset. For example, the following code creates a group called Data in the root + * group of file. + * + * <em> Create a group</em> + * \code + * // Create a group in the file. + * grp = H5Gcreate(file, "/Data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * A group may be created within another group by providing the absolute name of the group to the + * #H5Gcreate function or by specifying its location. For example, to create the group Data_new in + * the group Data, you might use the sequence of calls shown below. + * + * <em>Create a group within a group</em> + * \code + * // Create group "Data_new" in the group "Data" by specifying + * // absolute name of the group. + * grp_new = H5Gcreate(file, "/Data/Data_new", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * + * // or + * + * // Create group "Data_new" in the "Data" group. + * grp_new = H5Gcreate(grp, "Data_new", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * This first parameter of #H5Gcreate is a location identifier. file in the first example specifies only + * the file. \em grp in the second example specifies a particular group in a particular file. Note that in + * this instance, the group identifier \em grp is used as the first parameter in the #H5Gcreate call so that + * the relative name of Data_new can be used. + * + * The third parameter of #H5Gcreate optionally specifies how much file space to reserve to store + * the names of objects that will be created in this group. If a non-positive value is supplied, the + * library provides a default size. + * + * Use #H5Gclose to close the group and release the group identifier. + * + * <h4>Creating a Dataset within a Group</h4> + * As with groups, a dataset can be created in a particular group by specifying either its absolute + * name in the file or its relative name with respect to that group. The next code excerpt uses the + * absolute name. + * + * <em>Create a dataset within a group using a relative name</em> + * \code + * // Create the dataset "Compressed_Data" in the group Data using + * // the absolute name. The dataset creation property list is + * // modified to use GZIP compression with the compression + * // effort set to 6. Note that compression can be used only when + * // the dataset is chunked. + * dims[0] = 1000; + * dims[1] = 20; + * cdims[0] = 20; + * cdims[1] = 20; + * dataspace = H5Screate_simple(RANK, dims, NULL); + * + * plist = H5Pcreate(H5P_DATASET_CREATE); + * H5Pset_chunk(plist, 2, cdims); + * H5Pset_deflate(plist, 6); + * + * dataset = H5Dcreate(file, "/Data/Compressed_Data", H5T_NATIVE_INT, dataspace, H5P_DEFAULT, + * plist, H5P_DEFAULT); + * \endcode + * + * Alternatively, you can first obtain an identifier for the group in which the dataset is to be + * created, and then create the dataset with a relative name. + * + * <em>Create a dataset within a group using a relative name</em> + * \code + * // Open the group. + * grp = H5Gopen(file, "Data", H5P_DEFAULT); + * + * // Create the dataset "Compressed_Data" in the "Data" group + * // by providing a group identifier and a relative dataset + * // name as parameters to the H5Dcreate function. + * dataset = H5Dcreate(grp, "Compressed_Data", H5T_NATIVE_INT, dataspace, H5P_DEFAULT, plist, H5P_DEFAULT); + * \endcode + * + * <h4>Accessing an Object in a Group</h4> + * Any object in a group can be accessed by its absolute or relative name. The first code snippet + * below illustrates the use of the absolute name to access the dataset <em>Compressed_Data</em> in the + * group <em>Data</em> created in the examples above. The second code snippet illustrates the use of the + * relative name. + * + * <em>Accessing a group using its relative name</em> + * \code + * // Open the dataset "Compressed_Data" in the "Data" group. + * dataset = H5Dopen(file, "/Data/Compressed_Data", H5P_DEFAULT); + * + * // Open the group "data" in the file. + * grp = H5Gopen(file, "Data", H5P_DEFAULT); + * + * // Access the "Compressed_Data" dataset in the group. + * dataset = H5Dopen(grp, "Compressed_Data", H5P_DEFAULT); + * \endcode + * + * \subsubsection subsubsec_program_model_attr Working with Attributes + * An attribute is a small dataset that is attached to a normal dataset or group. Attributes share many + * of the characteristics of datasets, so the programming model for working with attributes is + * similar in many ways to the model for working with datasets. The primary differences are that an + * attribute must be attached to a dataset or a group and sub-setting operations cannot be performed + * on attributes. + * + * To create an attribute belonging to a particular dataset or group, first create a dataspace for the + * attribute with the call to #H5Screate, and then create the attribute using #H5Acreate. For example, + * the code shown below creates an attribute called “Integer attribute” that is a member of a dataset + * whose identifier is dataset. The attribute identifier is attr2. #H5Awrite then sets the value of the + * attribute of that of the integer variable point. #H5Aclose then releases the attribute identifier. + * + * <em>Create an attribute</em> + * \code + * int point = 1; // Value of the scalar attribute + * + * // Create scalar attribute. + * aid2 = H5Screate(H5S_SCALAR); + * attr2 = H5Acreate(dataset, "Integer attribute", H5T_NATIVE_INT, aid2, H5P_DEFAULT, H5P_DEFAULT); + * + * // Write scalar attribute. + * ret = H5Awrite(attr2, H5T_NATIVE_INT, &point); + * + * // Close attribute dataspace. + * ret = H5Sclose(aid2); + * + * // Close attribute. + * ret = H5Aclose(attr2); + * \endcode + * + * <em>Read a known attribute</em> + * \code + * // Attach to the scalar attribute using attribute name, then + * // read and display its value. + * attr = H5Aopen_by_name(file_id, dataset_name, "Integer attribute", H5P_DEFAULT, H5P_DEFAULT); + * ret = H5Aread(attr, H5T_NATIVE_INT, &point_out); + * printf("The value of the attribute \"Integer attribute\" is %d \n", point_out); + * ret = H5Aclose(attr); + * \endcode + * + * To read a scalar attribute whose name and datatype are known, first open the attribute using + * #H5Aopen_by_name, and then use #H5Aread to get its value. For example, the code shown below + * reads a scalar attribute called “Integer attribute” whose datatype is a native integer and whose + * parent dataset has the identifier dataset. + * + * To read an attribute whose characteristics are not known, go through these steps. First, query the + * file to obtain information about the attribute such as its name, datatype, rank, and dimensions, + * and then read the attribute. The following code opens an attribute by its index value using + * #H5Aopen_by_idx, and then it reads in information about the datatype with #H5Aread. + * + * <em>Read an unknown attribute</em> + * \code + * // Attach to the string attribute using its index, then read and + * // display the value. + * attr = H5Aopen_by_idx(file_id, dataset_name, index_type, iter_order, 2, H5P_DEFAULT, H5P_DEFAULT); + * + * atype = H5Tcopy(H5T_C_S1); + * H5Tset_size(atype, 4); + * + * ret = H5Aread(attr, atype, string_out); + * printf("The value of the attribute with the index 2 is %s \n", string_out); + * \endcode + * + * In practice, if the characteristics of attributes are not known, the code involved in accessing and + * processing the attribute can be quite complex. For this reason, HDF5 includes a function called + * #H5Aiterate. This function applies a user-supplied function to each of a set of attributes. The + * user-supplied function can contain the code that interprets, accesses, and processes each attribute. + * + * \subsection subsec_program_transfer_pipeline The Data Transfer Pipeline + * The HDF5 library implements data transfers between different storage locations. At the lowest + * levels, the HDF5 Library reads and writes blocks of bytes to and from storage using calls to the + * virtual file layer (VFL) drivers. In addition to this, the HDF5 library manages caches of metadata + * and a data I/O pipeline. The data I/O pipeline applies compression to data blocks, transforms + * data elements, and implements selections. + * + * A substantial portion of the HDF5 library’s work is in transferring data from one environment or + * media to another. This most often involves a transfer between system memory and a storage + * medium. Data transfers are affected by compression, encryption, machine-dependent differences + * in numerical representation, and other features. So, the bit-by-bit arrangement of a given dataset + * is often substantially different in the two environments. + * + * Consider the representation on disk of a compressed and encrypted little-endian array as + * compared to the same array after it has been read from disk, decrypted, decompressed, and + * loaded into memory on a big-endian system. HDF5 performs all of the operations necessary to + * make that transition during the I/O process with many of the operations being handled by the + * VFL and the data transfer pipeline. + * + * The figure below provides a simplified view of a sample data transfer with four stages. Note that + * the modules are used only when needed. For example, if the data is not compressed, the + * compression stage is omitted. + * + * <table> + * <tr> + * <td> + * \image html Pmodel_fig6.gif "A data transfer from storage to memory" + * </td> + * </tr> + * </table> + * + * For a given I/O request, different combinations of actions may be performed by the pipeline. The + * library automatically sets up the pipeline and passes data through the processing steps. For + * example, for a read request (from disk to memory), the library must determine which logical + * blocks contain the requested data elements and fetch each block into the library’s cache. If the + * data needs to be decompressed, then the compression algorithm is applied to the block after it is + * read from disk. If the data is a selection, the selected elements are extracted from the data block + * after it is decompressed. If the data needs to be transformed (for example, byte swapped), then + * the data elements are transformed after decompression and selection. + * + * While an application must sometimes set up some elements of the pipeline, use of the pipeline is + * normally transparent to the user program. The library determines what must be done based on the + * metadata for the file, the object, and the specific request. An example of when an application + * might be required to set up some elements in the pipeline is if the application used a custom + * error-checking algorithm. + * + * In some cases, it is necessary to pass parameters to and from modules in the pipeline or among + * other parts of the library that are not directly called through the programming API. This is + * accomplished through the use of dataset transfer and data access property lists. + * + * The VFL provides an interface whereby user applications can add custom modules to the data + * transfer pipeline. For example, a custom compression algorithm can be used with the HDF5 + * Library by linking an appropriate module into the pipeline through the VFL. This requires + * creating an appropriate wrapper for the compression module and registering it with the library + * with #H5Zregister. The algorithm can then be applied to a dataset with an #H5Pset_filter call which + * will add the algorithm to the selected dataset’s transfer property list. + * + * Previous Chapter \ref sec_data_model - Next Chapter \ref sec_file + * + */ + +/** + * \defgroup H5 Library General (H5) * * Use the functions in this module to manage the life cycle of HDF5 library * instances. diff --git a/src/H5private.h b/src/H5private.h index c3d16e5..b5c9d3a 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -2041,7 +2041,7 @@ typedef struct H5_api_struct { #define H5_FIRST_THREAD_INIT pthread_once(&H5TS_first_init_g, H5TS_pthread_first_thread_init); #endif -/* Macros for threadsafe HDF-5 Phase I locks */ +/* Macros for threadsafe HDF5 Phase I locks */ #ifdef H5_USE_RECURSIVE_WRITER_LOCKS #define H5_API_LOCK H5TS_rw_wrlock(&H5_g.init_rw_lock); #define H5_API_UNLOCK H5TS_rw_unlock(&H5_g.init_rw_lock); |