1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 #ifdef OLD_HEADER_FILENAME
15 #include <iostream.h>
16 #else
17 #include <iostream>
18 #endif
19 #include <string>
20 
21 #include "H5private.h"             // for HDfree
22 #include "H5Include.h"
23 #include "H5Exception.h"
24 #include "H5IdComponent.h"
25 #include "H5PropList.h"
26 #include "H5FaccProp.h"
27 #include "H5FcreatProp.h"
28 #include "H5OcreatProp.h"
29 #include "H5DxferProp.h"
30 #include "H5DcreatProp.h"
31 #include "H5LcreatProp.h"
32 #include "H5LaccProp.h"
33 #include "H5DaccProp.h"
34 #include "H5Location.h"
35 #include "H5Object.h"
36 #include "H5DataType.h"
37 #include "H5DataSpace.h"
38 #include "H5AbstractDs.h"
39 #include "H5Attribute.h"
40 #include "H5DataSet.h"
41 
42 namespace H5 {
43 using std::cerr;
44 using std::endl;
45 
46 //--------------------------------------------------------------------------
47 // Function:    DataSet default constructor
48 ///\brief       Default constructor: creates a stub DataSet.
49 // Programmer   Binh-Minh Ribler - 2000
50 //--------------------------------------------------------------------------
DataSet()51 DataSet::DataSet() : H5Object(), AbstractDs(), id(H5I_INVALID_HID) {}
52 
53 //--------------------------------------------------------------------------
54 // Function:    DataSet overloaded constructor
55 ///\brief       Creates an DataSet object using the id of an existing dataset.
56 ///\param       existing_id - IN: Id of an existing dataset
57 // Programmer   Binh-Minh Ribler - 2000
58 // Description
59 //              incRefCount() is needed here to prevent the id from being closed
60 //              prematurely.  That is, when application uses the id of an
61 //              existing DataSet object to create another DataSet object.  So,
62 //              when one of those objects is deleted, the id will be closed if
63 //              the reference counter is only 1.
64 //--------------------------------------------------------------------------
DataSet(const hid_t existing_id)65 DataSet::DataSet(const hid_t existing_id) : H5Object(), AbstractDs(), id(existing_id)
66 {
67     incRefCount(); // increment number of references to this id
68 }
69 
70 //--------------------------------------------------------------------------
71 // Function:    DataSet copy constructor
72 ///\brief       Copy constructor: same HDF5 object as \a original
73 ///\param       original - IN: DataSet instance to copy
74 // Programmer   Binh-Minh Ribler - 2000
75 //--------------------------------------------------------------------------
DataSet(const DataSet & original)76 DataSet::DataSet(const DataSet& original) : H5Object(), AbstractDs(), id(original.id)
77 {
78     incRefCount(); // increment number of references to this id
79 }
80 
81 //--------------------------------------------------------------------------
82 // Function:    DataSet overload constructor - dereference
83 ///\brief       Given a reference, ref, to an hdf5 location, creates a
84 ///             DataSet object
85 ///\param       loc - IN: Dataset reference object is in or location of
86 ///                       object that the dataset is located within.
87 ///\param       ref - IN: Reference pointer
88 ///\param       ref_type - IN: Reference type - default to H5R_OBJECT
89 ///\param       plist - IN: Property list - default to PropList::DEFAULT
90 ///\exception   H5::DataSetIException
91 ///\par Description
92 ///             \c loc can be DataSet, Group, H5File, or named DataType, that
93 ///             is a datatype that has been named by DataType::commit.
94 // Programmer   Binh-Minh Ribler - Oct, 2006
95 //--------------------------------------------------------------------------
DataSet(const H5Location & loc,const void * ref,H5R_type_t ref_type,const PropList & plist)96 DataSet::DataSet(const H5Location& loc, const void* ref, H5R_type_t ref_type, const PropList& plist) : H5Object(), AbstractDs(), id(H5I_INVALID_HID)
97 {
98     id = H5Location::p_dereference(loc.getId(), ref, ref_type, plist, "constructor - by dereferenced");
99 }
100 
101 //--------------------------------------------------------------------------
102 // Function:    DataSet overload constructor - dereference
103 ///\brief       Given a reference, ref, to an hdf5 attribute, creates a
104 ///             DataSet object
105 ///\param       attr - IN: Specifying location where the referenced object is in
106 ///\param       ref - IN: Reference pointer
107 ///\param       ref_type - IN: Reference type - default to H5R_OBJECT
108 ///\param       plist - IN: Property list - default to PropList::DEFAULT
109 ///\exception   H5::ReferenceException
110 // Programmer   Binh-Minh Ribler - Oct, 2006
111 //--------------------------------------------------------------------------
DataSet(const Attribute & attr,const void * ref,H5R_type_t ref_type,const PropList & plist)112 DataSet::DataSet(const Attribute& attr, const void* ref, H5R_type_t ref_type, const PropList& plist) : H5Object(), AbstractDs(), id(H5I_INVALID_HID)
113 {
114     id = H5Location::p_dereference(attr.getId(), ref, ref_type, plist, "constructor - by dereference");
115 }
116 
117 //--------------------------------------------------------------------------
118 // Function:    DataSet::getSpace
119 ///\brief       Gets a copy of the dataspace of this dataset.
120 ///\return      DataSpace instance
121 ///\exception   H5::DataSetIException
122 // Programmer   Binh-Minh Ribler - 2000
123 //--------------------------------------------------------------------------
getSpace() const124 DataSpace DataSet::getSpace() const
125 {
126     // Calls C function H5Dget_space to get the id of the dataspace
127     hid_t dataspace_id = H5Dget_space(id);
128 
129     // If the dataspace id is invalid, throw an exception
130     if (dataspace_id < 0)
131     {
132         throw DataSetIException("DataSet::getSpace", "H5Dget_space failed");
133     }
134     //create dataspace object using the existing id then return the object
135     DataSpace data_space;
136     f_DataSpace_setId(&data_space, dataspace_id);
137     return(data_space);
138 }
139 
140 // This private member function calls the C API to get the identifier
141 // of the datatype that is used by this dataset.  It is used
142 // by the various AbstractDs functions to get the specific datatype.
p_get_type() const143 hid_t DataSet::p_get_type() const
144 {
145     hid_t type_id = H5Dget_type(id);
146     if (type_id > 0)
147         return(type_id);
148     else
149     {
150         throw DataSetIException("", "H5Dget_type failed");
151     }
152 }
153 
154 //--------------------------------------------------------------------------
155 // Function:    DataSet::getCreatePlist
156 ///\brief       Gets the dataset creation property list.
157 ///\return      DSetCreatPropList instance
158 ///\exception   H5::DataSetIException
159 // Programmer   Binh-Minh Ribler - 2000
160 //--------------------------------------------------------------------------
getCreatePlist() const161 DSetCreatPropList DataSet::getCreatePlist() const
162 {
163     hid_t create_plist_id = H5Dget_create_plist(id);
164     if (create_plist_id < 0)
165     {
166         throw DataSetIException("DataSet::getCreatePlist", "H5Dget_create_plist failed");
167     }
168 
169     // create and return the DSetCreatPropList object
170     DSetCreatPropList create_plist;
171     f_PropList_setId(&create_plist, create_plist_id);
172     return(create_plist);
173 }
174 
175 //--------------------------------------------------------------------------
176 // Function:    DataSet::getAccessPlist
177 ///\brief       Gets the dataset access property list.
178 ///\return      DSetAccPropList instance
179 ///\exception   H5::DataSetIException
180 // July 2018
181 //--------------------------------------------------------------------------
getAccessPlist() const182 DSetAccPropList DataSet::getAccessPlist() const
183 {
184     hid_t access_plist_id = H5Dget_access_plist(id);
185     if (access_plist_id < 0)
186     {
187         throw DataSetIException("DataSet::getAccessPlist", "H5Dget_access_plist failed");
188     }
189 
190     // create and return the DSetCreatPropList object
191     DSetAccPropList access_plist;
192     f_PropList_setId(&access_plist, access_plist_id);
193     return(access_plist);
194 }
195 
196 //--------------------------------------------------------------------------
197 // Function:    DataSet::getStorageSize
198 ///\brief       Returns the amount of storage required for a dataset.
199 ///\return      Size of the storage or 0, for no data
200 ///\exception   H5::DataSetIException
201 // Note:        H5Dget_storage_size returns 0 when there is no data.  This
202 //              function should have no failure. (from SLU)
203 // Programmer   Binh-Minh Ribler - Mar, 2005
204 //--------------------------------------------------------------------------
getStorageSize() const205 hsize_t DataSet::getStorageSize() const
206 {
207     hsize_t storage_size = H5Dget_storage_size(id);
208     return(storage_size);
209 }
210 
211 //--------------------------------------------------------------------------
212 // Function:    DataSet::getInMemDataSize
213 ///\brief       Gets the size in memory of the dataset's data.
214 ///\return      Size of data (in memory)
215 ///\exception   H5::DataSetIException
216 // Programmer   Binh-Minh Ribler - Apr 2009
217 //--------------------------------------------------------------------------
getInMemDataSize() const218 size_t DataSet::getInMemDataSize() const
219 {
220     const char *func = "DataSet::getInMemDataSize";
221 
222     // Get the data type of this dataset
223     hid_t mem_type_id = H5Dget_type(id);
224     if (mem_type_id < 0)
225     {
226         throw DataSetIException(func, "H5Dget_type failed");
227     }
228 
229     // Get the data type's size by first getting its native type then getting
230     // the native type's size.
231     hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
232     if (native_type < 0)
233     {
234         throw DataSetIException(func, "H5Tget_native_type failed");
235     }
236     size_t type_size = H5Tget_size(native_type);
237     if (type_size == 0)
238     {
239         throw DataSetIException(func, "H5Tget_size failed");
240     }
241 
242     // Close the native type and the datatype of this dataset.
243     if (H5Tclose(native_type) < 0)
244     {
245         throw DataSetIException(func, "H5Tclose(native_type) failed");
246     }
247     if (H5Tclose(mem_type_id) < 0)
248     {
249         throw DataSetIException(func, "H5Tclose(mem_type_id) failed");
250     }
251 
252     // Get number of elements of the dataset by first getting its dataspace,
253     // then getting the number of elements in the dataspace
254     hid_t space_id = H5Dget_space(id);
255     if (space_id < 0)
256     {
257         throw DataSetIException(func, "H5Dget_space failed");
258     }
259     hssize_t num_elements = H5Sget_simple_extent_npoints(space_id);
260     if (num_elements < 0)
261     {
262         throw DataSetIException(func, "H5Sget_simple_extent_npoints failed");
263     }
264 
265     // Close the dataspace
266     if (H5Sclose(space_id) < 0)
267     {
268         throw DataSetIException(func, "H5Sclose failed");
269     }
270 
271     // Calculate and return the size of the data
272     size_t data_size = type_size * num_elements;
273     return(data_size);
274 }
275 
276 //--------------------------------------------------------------------------
277 // Function:    DataSet::getOffset
278 ///\brief       Returns the address of this dataset in the file.
279 ///\return      Address of dataset
280 ///\exception   H5::DataSetIException
281 // Programmer   Binh-Minh Ribler - 2000
282 //--------------------------------------------------------------------------
getOffset() const283 haddr_t DataSet::getOffset() const
284 {
285     haddr_t ds_addr; // for address of dataset
286 
287     ds_addr = H5Dget_offset(id);
288     if (ds_addr == HADDR_UNDEF)
289     {
290         throw DataSetIException("DataSet::getOffset", "H5Dget_offset returned HADDR_UNDEF");
291     }
292     return(ds_addr);
293 }
294 
295 //--------------------------------------------------------------------------
296 // Function:    DataSet::getSpaceStatus
297 ///\brief       Determines whether space has been allocated for a dataset.
298 ///\param       status - OUT: Space allocation status
299 ///\exception   H5::DataSetIException
300 // Programmer   Binh-Minh Ribler - 2000
301 //--------------------------------------------------------------------------
getSpaceStatus(H5D_space_status_t & status) const302 void DataSet::getSpaceStatus(H5D_space_status_t& status) const
303 {
304     herr_t ret_value = H5Dget_space_status(id, &status);
305     if (ret_value < 0)
306     {
307         throw DataSetIException("DataSet::getSpaceStatus", "H5Dget_space_status failed");
308     }
309 }
310 
311 //--------------------------------------------------------------------------
312 // Function:    DataSet::getVlenBufSize
313 ///\brief       Returns the number of bytes required to store VL data.
314 ///\param       type - IN: Datatype, which is the datatype for the buffer
315 ///\param       space - IN: Selection for the memory buffer
316 ///\return      Amount of storage
317 ///\exception   H5::DataSetIException
318 // Programmer   Binh-Minh Ribler - 2000
319 //--------------------------------------------------------------------------
getVlenBufSize(const DataType & type,const DataSpace & space) const320 hsize_t DataSet::getVlenBufSize(const DataType& type, const DataSpace& space) const
321 {
322     // Obtain identifiers for C API
323     hid_t type_id = type.getId();
324     hid_t space_id = space.getId();
325 
326     hsize_t size; // for amount of storage
327 
328     herr_t ret_value = H5Dvlen_get_buf_size(id, type_id, space_id, &size);
329     if (ret_value < 0)
330     {
331         throw DataSetIException("DataSet::getVlenBufSize", "H5Dvlen_get_buf_size failed");
332     }
333     return(size);
334 }
335 
336 //--------------------------------------------------------------------------
337 // Function:    DataSet::getVlenBufSize
338 // Purpose      This is an overloaded member function, kept for backward
339 //              compatibility.  It differs from the above function in that it
340 //              misses const's.  This wrapper will be removed in future release.
341 // Return       Amount of storage
342 // Exception    H5::DataSetIException
343 // Programmer   Binh-Minh Ribler - 2000
344 // Modification
345 //              Modified to call its replacement. -BMR, 2014/04/16
346 //              Removed from documentation. -BMR, 2016/03/07 1.8.17 and 1.10.0
347 //              Removed from code. -BMR, 2016/08/11 1.8.18 and 1.10.1
348 //--------------------------------------------------------------------------
349 //hsize_t DataSet::getVlenBufSize(DataType& type, DataSpace& space) const
350 //{
351 //    return(getVlenBufSize(type, space));
352 //}
353 
354 //--------------------------------------------------------------------------
355 // Function:    DataSet::vlenReclaim
356 ///\brief       Reclaims VL datatype memory buffers.
357 ///\param       type - IN: Datatype, which is the datatype stored in the buffer
358 ///\param       space - IN: Selection for the memory buffer to free the
359 ///             VL datatypes within
360 ///\param       xfer_plist - IN: Property list used to create the buffer
361 ///\param       buf - IN: Pointer to the buffer to be reclaimed
362 ///\exception   H5::DataSetIException
363 // Programmer   Binh-Minh Ribler - 2000
364 //--------------------------------------------------------------------------
vlenReclaim(const DataType & type,const DataSpace & space,const DSetMemXferPropList & xfer_plist,void * buf)365 void DataSet::vlenReclaim(const DataType& type, const DataSpace& space, const DSetMemXferPropList& xfer_plist, void* buf)
366 {
367     // Obtain identifiers for C API
368     hid_t type_id = type.getId();
369     hid_t space_id = space.getId();
370     hid_t xfer_plist_id = xfer_plist.getId();
371 
372     herr_t ret_value = H5Dvlen_reclaim(type_id, space_id, xfer_plist_id, buf);
373     if (ret_value < 0)
374     {
375         throw DataSetIException("DataSet::vlenReclaim", "H5Dvlen_reclaim failed");
376     }
377 }
378 
379 //--------------------------------------------------------------------------
380 // Function:    DataSet::vlenReclaim
381 ///\brief       Reclaims VL datatype memory buffers.
382 ///\param       type - IN: Datatype, which is the datatype stored in the buffer
383 ///\param       space - IN: Selection for the memory buffer to free the
384 ///             VL datatypes within
385 ///\param       xfer_plist - IN: Property list used to create the buffer
386 ///\param       buf - IN: Pointer to the buffer to be reclaimed
387 ///\exception   H5::DataSetIException
388 // Programmer   Binh-Minh Ribler - 2000
389 //\parDescription
390 //              This function has better prototype for the users than the
391 //              other, which might be removed at some point. BMR - 2006/12/20
392 //--------------------------------------------------------------------------
vlenReclaim(void * buf,const DataType & type,const DataSpace & space,const DSetMemXferPropList & xfer_plist)393 void DataSet::vlenReclaim(void* buf, const DataType& type, const DataSpace& space, const DSetMemXferPropList& xfer_plist)
394 {
395     // Obtain identifiers for C API
396     hid_t type_id = type.getId();
397     hid_t space_id = space.getId();
398     hid_t xfer_plist_id = xfer_plist.getId();
399 
400     herr_t ret_value = H5Dvlen_reclaim(type_id, space_id, xfer_plist_id, buf);
401     if (ret_value < 0)
402     {
403         throw DataSetIException("DataSet::vlenReclaim", "H5Dvlen_reclaim failed");
404     }
405 }
406 
407 //--------------------------------------------------------------------------
408 // Function:    DataSet::read
409 ///\brief       Reads raw data from the specified dataset.
410 ///\param       buf - IN: Buffer for read data
411 ///\param       mem_type - IN: Memory datatype
412 ///\param       mem_space - IN: Memory dataspace
413 ///\param       file_space - IN: Dataset's dataspace in the file
414 ///\param       xfer_plist - IN: Transfer property list for this I/O operation
415 ///\exception   H5::DataSetIException
416 ///\par Description
417 ///             This function reads raw data from this dataset into the
418 ///             buffer \a buf, converting from file datatype and dataspace
419 ///             to memory datatype \a mem_type and dataspace \a mem_space.
420 // Programmer   Binh-Minh Ribler - 2000
421 //--------------------------------------------------------------------------
read(void * buf,const DataType & mem_type,const DataSpace & mem_space,const DataSpace & file_space,const DSetMemXferPropList & xfer_plist) const422 void DataSet::read(void* buf, const DataType& mem_type, const DataSpace& mem_space, const DataSpace& file_space, const DSetMemXferPropList& xfer_plist) const
423 {
424     // Obtain identifiers for C API
425     hid_t mem_type_id = mem_type.getId();
426     hid_t mem_space_id = mem_space.getId();
427     hid_t file_space_id = file_space.getId();
428     hid_t xfer_plist_id = xfer_plist.getId();
429 
430     herr_t ret_value = H5Dread(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf);
431     if (ret_value < 0)
432     {
433         throw DataSetIException("DataSet::read", "H5Dread failed");
434     }
435 }
436 
437 //--------------------------------------------------------------------------
438 // Function:    DataSet::read
439 ///\brief       This is an overloaded member function, provided for convenience.
440 ///             It takes a reference to a \c H5std_string for the buffer.
441 ///\param       strg - IN: Buffer for read data string
442 ///\param       mem_type - IN: Memory datatype
443 ///\param       mem_space - IN: Memory dataspace
444 ///\param       file_space - IN: Dataset's dataspace in the file
445 ///\param       xfer_plist - IN: Transfer property list for this I/O operation
446 ///\exception   H5::DataSetIException
447 // Programmer   Binh-Minh Ribler - 2000
448 // Modification
449 //      Jul 2009
450 //              Follow the change to Attribute::read and use the following
451 //              private functions to read datasets with fixed- and
452 //              variable-length string:
453 //                  DataSet::p_read_fixed_len and
454 //                  DataSet::p_read_variable_len
455 //--------------------------------------------------------------------------
read(H5std_string & strg,const DataType & mem_type,const DataSpace & mem_space,const DataSpace & file_space,const DSetMemXferPropList & xfer_plist) const456 void DataSet::read(H5std_string& strg, const DataType& mem_type, const DataSpace& mem_space, const DataSpace& file_space, const DSetMemXferPropList& xfer_plist) const
457 {
458     // Check if this dataset has variable-len string or fixed-len string and
459     // proceed appropriately.
460     htri_t is_variable_len = H5Tis_variable_str(mem_type.getId());
461     if (is_variable_len < 0)
462     {
463         throw DataSetIException("DataSet::read", "H5Tis_variable_str failed");
464     }
465 
466     // Obtain identifiers for C API
467     hid_t mem_type_id = mem_type.getId();
468     hid_t mem_space_id = mem_space.getId();
469     hid_t file_space_id = file_space.getId();
470     hid_t xfer_plist_id = xfer_plist.getId();
471 
472     if (!is_variable_len)       // only allocate for fixed-len string
473     {
474         p_read_fixed_len(mem_type_id, mem_space_id, file_space_id, xfer_plist_id, strg);
475     }
476     else
477     {
478         p_read_variable_len(mem_type_id, mem_space_id, file_space_id, xfer_plist_id, strg);
479     }
480 }
481 
482 //--------------------------------------------------------------------------
483 // Function:    DataSet::write
484 ///\brief       Writes raw data from an application buffer to a dataset.
485 ///\param       buf - IN: Buffer containing data to be written
486 ///\param       mem_type - IN: Memory datatype
487 ///\param       mem_space - IN: Memory dataspace
488 ///\param       file_space - IN: Dataset's dataspace in the file
489 ///\param       xfer_plist - IN: Transfer property list for this I/O operation
490 ///\exception   H5::DataSetIException
491 ///\par Description
492 ///             This function writes raw data from an application buffer
493 ///             \a buf to a dataset, converting from memory datatype
494 ///             \a mem_type and dataspace \a mem_space to file datatype
495 ///             and dataspace.
496 // Programmer   Binh-Minh Ribler - 2000
497 //--------------------------------------------------------------------------
write(const void * buf,const DataType & mem_type,const DataSpace & mem_space,const DataSpace & file_space,const DSetMemXferPropList & xfer_plist) const498 void DataSet::write(const void* buf, const DataType& mem_type, const DataSpace& mem_space, const DataSpace& file_space, const DSetMemXferPropList& xfer_plist) const
499 {
500     // Obtain identifiers for C API
501     hid_t mem_type_id = mem_type.getId();
502     hid_t mem_space_id = mem_space.getId();
503     hid_t file_space_id = file_space.getId();
504     hid_t xfer_plist_id = xfer_plist.getId();
505 
506     herr_t ret_value = H5Dwrite(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf);
507     if (ret_value < 0)
508     {
509         throw DataSetIException("DataSet::write", "H5Dwrite failed");
510     }
511 }
512 
513 //--------------------------------------------------------------------------
514 // Function:    DataSet::write
515 ///\brief       This is an overloaded member function, provided for convenience.
516 ///             It takes a reference to a \c H5std_string for the buffer.
517 // Programmer   Binh-Minh Ribler - 2000
518 // Modification
519 //      Jul 2009
520 //              Modified to pass the buffer into H5Dwrite properly depending
521 //              whether the dataset has variable- or fixed-length string.
522 //--------------------------------------------------------------------------
write(const H5std_string & strg,const DataType & mem_type,const DataSpace & mem_space,const DataSpace & file_space,const DSetMemXferPropList & xfer_plist) const523 void DataSet::write(const H5std_string& strg, const DataType& mem_type, const DataSpace& mem_space, const DataSpace& file_space, const DSetMemXferPropList& xfer_plist) const
524 {
525     // Check if this attribute has variable-len string or fixed-len string and
526     // proceed appropriately.
527     htri_t is_variable_len = H5Tis_variable_str(mem_type.getId());
528     if (is_variable_len < 0)
529     {
530         throw DataSetIException("DataSet::write", "H5Tis_variable_str failed");
531     }
532 
533     // Obtain identifiers for C API
534     hid_t mem_type_id = mem_type.getId();
535     hid_t mem_space_id = mem_space.getId();
536     hid_t file_space_id = file_space.getId();
537     hid_t xfer_plist_id = xfer_plist.getId();
538 
539     // Convert string to C-string
540     const char* strg_C;
541     strg_C = strg.c_str();  // strg_C refers to the contents of strg as a C-str
542     herr_t ret_value = 0;
543 
544     // Pass string in differently depends on variable or fixed length
545     if (!is_variable_len)
546     {
547         ret_value = H5Dwrite(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, strg_C);
548     }
549     else
550     {
551         // passing string argument by address
552         ret_value = H5Dwrite(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, &strg_C);
553     }
554     if (ret_value < 0)
555     {
556         throw DataSetIException("DataSet::write", "H5Dwrite failed");
557     }
558 }
559 
560 //--------------------------------------------------------------------------
561 // Function:    DataSet::iterateElems
562 ///\brief       Iterates over all selected elements in a dataspace.
563 ///\param       buf - IN/OUT: Pointer to the buffer in memory containing the
564 ///             elements to iterate over
565 ///\param       type - IN: Datatype for the elements stored in \a buf
566 ///\param       space - IN: Dataspace for \a buf. Also contains the selection
567 ///             to iterate over.
568 ///\param       op - IN: Function pointer to the routine to be called for
569 ///             each element in \a buf iterated over
570 ///\param       op_data - IN/OUT: Pointer to any user-defined data associated
571 ///             with the operation
572 ///\exception   H5::DataSetIException
573 ///\note        This function may not work correctly yet - it's still
574 ///             under development.
575 // Programmer   Binh-Minh Ribler - 2000
576 //--------------------------------------------------------------------------
iterateElems(void * buf,const DataType & type,const DataSpace & space,H5D_operator_t op,void * op_data)577 int DataSet::iterateElems(void* buf, const DataType& type, const DataSpace& space, H5D_operator_t op, void* op_data)
578 {
579     // Obtain identifiers for C API
580     hid_t type_id = type.getId();
581     hid_t space_id = space.getId();
582     herr_t ret_value = H5Diterate(buf, type_id, space_id, op, op_data);
583     if (ret_value >= 0)
584         return(ret_value);
585     else  // raise exception when H5Diterate returns a negative value
586     {
587         throw DataSetIException("DataSet::iterateElems", "H5Diterate failed");
588     }
589 }
590 
591 //--------------------------------------------------------------------------
592 // Function:    DataSet::extend
593 ///\brief       Extends a dataset with unlimited dimension.
594 ///\param       size - IN: Array containing the new magnitude of each dimension
595 ///\exception   H5::DataSetIException
596 ///\par Description
597 ///             For information, please refer to the H5Dset_extent API in
598 ///             the HDF5 C Reference Manual.
599 // Programmer   Binh-Minh Ribler - 2000
600 //--------------------------------------------------------------------------
extend(const hsize_t * size) const601 void DataSet::extend(const hsize_t* size) const
602 {
603     herr_t ret_value = H5Dset_extent(id, size);
604     if (ret_value < 0)  // raise exception when H5Dset_extent returns a neg value
605         throw DataSetIException("DataSet::extend", "H5Dset_extent failed");
606 }
607 
608 //--------------------------------------------------------------------------
609 // Function:    DataSet::fillMemBuf
610 ///\brief       Fills a selection in memory with a value.
611 ///\param       fill - IN: Pointer to fill value to use - default NULL
612 ///\param       fill_type - IN: Datatype of the fill value
613 ///\param       buf - IN/OUT: Memory buffer to fill selection within
614 ///\param       buf_type - IN: Datatype of the elements in buffer
615 ///\param       space - IN: Dataspace describing memory buffer & containing selection to use
616 ///\exception   H5::DataSetIException
617 // Programmer   Binh-Minh Ribler - 2014
618 //--------------------------------------------------------------------------
fillMemBuf(const void * fill,const DataType & fill_type,void * buf,const DataType & buf_type,const DataSpace & space) const619 void DataSet::fillMemBuf(const void *fill, const DataType& fill_type, void *buf, const DataType& buf_type, const DataSpace& space) const
620 {
621     hid_t fill_type_id = fill_type.getId();
622     hid_t buf_type_id = buf_type.getId();
623     hid_t space_id = space.getId();
624     herr_t ret_value = H5Dfill(fill, fill_type_id, buf, buf_type_id, space_id);
625     if (ret_value < 0)
626     {
627         throw DataSetIException("DataSet::fillMemBuf", "H5Dfill failed");
628     }
629 }
630 
631 //--------------------------------------------------------------------------
632 // Function:    DataSet::fillMemBuf
633 // Purpose      This is an overloaded member function, kept for backward
634 //              compatibility.  It differs from the above function in that it
635 //              misses const's.  This wrapper will be removed in future release.
636 // Param        fill - IN: Pointer to fill value to use - default NULL
637 // Param        fill_type - IN: Datatype of the fill value
638 // Param        buf - IN/OUT: Memory buffer to fill selection within
639 // Param        buf_type - IN: Datatype of the elements in buffer
640 // Param        space - IN: Dataspace describing memory buffer & containing selection to use
641 // Exception    H5::DataSetIException
642 // Programmer   Binh-Minh Ribler - 2000
643 // Modification
644 //              Modified to call its replacement. -BMR, 2014/04/16
645 //              Removed from documentation. -BMR, 2016/03/07 1.8.17 and 1.10.0
646 //              Removed from code. -BMR, 2016/08/11 1.8.18 and 1.10.1
647 //--------------------------------------------------------------------------
648 //void DataSet::fillMemBuf(const void *fill, DataType& fill_type, void *buf, DataType& buf_type, DataSpace& space)
649 //{
650 //    fillMemBuf(fill, (const DataType)fill_type, buf, (const DataType)buf_type, (const DataSpace)space);
651 //}
652 
653 //--------------------------------------------------------------------------
654 // Function:    DataSet::fillMemBuf
655 ///\brief       Fills a selection in memory with 0.
656 ///\param       buf - IN/OUT: Memory buffer to fill selection within
657 ///\param       buf_type - IN: Datatype of the elements in buffer
658 ///\param       space - IN: Dataspace describing memory buffer & containing selection to use
659 ///\exception   H5::DataSetIException
660 // Programmer   Binh-Minh Ribler - 2000
661 //--------------------------------------------------------------------------
fillMemBuf(void * buf,const DataType & buf_type,const DataSpace & space) const662 void DataSet::fillMemBuf(void *buf, const DataType& buf_type, const DataSpace& space) const
663 {
664     hid_t buf_type_id = buf_type.getId();
665     hid_t space_id = space.getId();
666     herr_t ret_value = H5Dfill(NULL, buf_type_id, buf, buf_type_id, space_id);
667     if (ret_value < 0)
668     {
669         throw DataSetIException("DataSet::fillMemBuf", "H5Dfill failed");
670     }
671 }
672 
673 //--------------------------------------------------------------------------
674 // Function:    DataSet::fillMemBuf
675 // Purpose      This is an overloaded member function, kept for backward
676 //              compatibility.  It differs from the above function in that it
677 //              misses const's.  This wrapper will be removed in future release.
678 // Param        buf - IN/OUT: Memory buffer to fill selection within
679 // Param        buf_type - IN: Datatype of the elements in buffer
680 // Param        space - IN: Dataspace describing memory buffer & containing selection to use
681 // Exception    H5::DataSetIException
682 // Programmer   Binh-Minh Ribler - 2000
683 // Modification
684 //              Modified to call its replacement. -BMR, 2014/04/16
685 //              Removed from documentation. -BMR, 2016/03/07 1.8.17 and 1.10.0
686 //              Removed from code. -BMR, 2016/08/11 1.8.18 and 1.10.1
687 //--------------------------------------------------------------------------
688 //void DataSet::fillMemBuf(void *buf, DataType& buf_type, DataSpace& space)
689 //{
690 //    fillMemBuf(buf, (const DataType)buf_type, (const DataSpace)space);
691 //}
692 
693 //--------------------------------------------------------------------------
694 // Function:    DataSet::getId
695 ///\brief       Get the id of this dataset.
696 ///\return      DataSet identifier
697 // Description:
698 //              Class hierarchy is revised to address bugzilla 1068.  Class
699 //              AbstractDs and Attribute are moved out of H5Object.  In
700 //              addition, member IdComponent::id is moved into subclasses, and
701 //              IdComponent::getId now becomes pure virtual function.
702 // Programmer   Binh-Minh Ribler - May, 2008
703 //--------------------------------------------------------------------------
getId() const704 hid_t DataSet::getId() const
705 {
706     return(id);
707 }
708 
709 //--------------------------------------------------------------------------
710 // Function:    DataSet::p_read_fixed_len (private)
711 // brief       Reads a fixed length \a H5std_string from a dataset.
712 // param       mem_type  - IN: DataSet datatype (in memory)
713 // param       strg      - IN: Buffer for read string
714 // exception   H5::DataSetIException
715 // Programmer   Binh-Minh Ribler - Jul, 2009
716 // Modification
717 //      Jul 2009
718 //              Added in follow to the change in Attribute::read
719 //--------------------------------------------------------------------------
p_read_fixed_len(const hid_t mem_type_id,const hid_t mem_space_id,const hid_t file_space_id,const hid_t xfer_plist_id,H5std_string & strg) const720 void DataSet::p_read_fixed_len(const hid_t mem_type_id, const hid_t mem_space_id, const hid_t file_space_id, const hid_t xfer_plist_id, H5std_string& strg) const
721 {
722     // Only allocate for fixed-len string.
723 
724     // Get the size of the dataset's data
725     size_t data_size = getInMemDataSize();
726 
727     // If there is data, allocate buffer and read it.
728     if (data_size > 0)
729     {
730         char *strg_C = new char [data_size+1];
731         HDmemset(strg_C, 0, data_size+1); // clear buffer
732 
733         herr_t ret_value = H5Dread(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, strg_C);
734 
735         if (ret_value < 0)
736         {
737             delete []strg_C;    // de-allocate for fixed-len string
738             throw DataSetIException("DataSet::read", "H5Dread failed for fixed length string");
739         }
740 
741         // Get string from the C char* and release resource allocated locally
742         strg = strg_C;
743         delete []strg_C;
744     }
745 }
746 
747 //--------------------------------------------------------------------------
748 // Function:    DataSet::p_read_variable_len (private)
749 // brief       Reads a variable length \a H5std_string from an dataset.
750 // param       mem_type  - IN: DataSet datatype (in memory)
751 // param       strg      - IN: Buffer for read string
752 // exception   H5::DataSetIException
753 // Programmer   Binh-Minh Ribler - Jul, 2009
754 // Modification
755 //      Jul 2009
756 //              Added in follow to the change in Attribute::read
757 //--------------------------------------------------------------------------
p_read_variable_len(const hid_t mem_type_id,const hid_t mem_space_id,const hid_t file_space_id,const hid_t xfer_plist_id,H5std_string & strg) const758 void DataSet::p_read_variable_len(const hid_t mem_type_id, const hid_t mem_space_id, const hid_t file_space_id, const hid_t xfer_plist_id, H5std_string& strg) const
759 {
760     // Prepare and call C API to read dataset.
761     char *strg_C;
762 
763     // Read dataset, no allocation for variable-len string; C library will
764     herr_t ret_value = H5Dread(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, &strg_C);
765 
766     if (ret_value < 0)
767     {
768         throw DataSetIException("DataSet::read", "H5Dread failed for variable length string");
769     }
770 
771     // Get string from the C char* and release resource allocated by C API
772     strg = strg_C;
773     HDfree(strg_C);
774 }
775 
776 #ifndef DOXYGEN_SHOULD_SKIP_THIS
777 //--------------------------------------------------------------------------
778 // Function:    DataSet::p_setId (protected)
779 ///\brief       Sets the identifier of this dataset to a new value.
780 ///
781 ///\exception   H5::IdComponentException when the attempt to close the HDF5
782 ///             object fails
783 // Description:
784 //              The underlaying reference counting in the C library ensures
785 //              that the current valid id of this object is properly closed.
786 //              Then the object's id is reset to the new id.
787 // Programmer   Binh-Minh Ribler - 2000
788 //--------------------------------------------------------------------------
p_setId(const hid_t new_id)789 void DataSet::p_setId(const hid_t new_id)
790 {
791     // handling references to this old id
792     try {
793         close();
794     }
795     catch (Exception& close_error) {
796         throw DataSetIException(inMemFunc("p_setId"), close_error.getDetailMsg());
797     }
798    // reset object's id to the given id
799    id = new_id;
800 }
801 
802 //--------------------------------------------------------------------------
803 // Function:    f_PropList_setId - friend
804 // Purpose:     This function is friend to class H5::PropList so that it
805 //              can set PropList::id in order to work around a problem
806 //              described in the JIRA issue HDFFV-7947.
807 //              Applications shouldn't need to use it.
808 // param        dset   - IN/OUT: DataSet object to be changed
809 // param        new_id - IN: New id to set
810 // Programmer   Binh-Minh Ribler - 2015
811 //--------------------------------------------------------------------------
f_PropList_setId(PropList * plist,hid_t new_id)812 void f_PropList_setId(PropList* plist, hid_t new_id)
813 {
814     plist->p_setId(new_id);
815 }
816 
817 #endif // DOXYGEN_SHOULD_SKIP_THIS
818 
819 //--------------------------------------------------------------------------
820 // Function:    DataSet::close
821 ///\brief       Closes this dataset.
822 ///
823 ///\exception   H5::DataSetIException
824 // Programmer   Binh-Minh Ribler - Mar 9, 2005
825 //--------------------------------------------------------------------------
close()826 void DataSet::close()
827 {
828     if (p_valid_id(id))
829     {
830         herr_t ret_value = H5Dclose(id);
831         if (ret_value < 0)
832         {
833             throw DataSetIException("DataSet::close", "H5Dclose failed");
834         }
835         // reset the id
836         id = H5I_INVALID_HID;
837     }
838 }
839 
840 //--------------------------------------------------------------------------
841 // Function:    DataSet destructor
842 ///\brief       Properly terminates access to this dataset.
843 // Programmer   Binh-Minh Ribler - 2000
844 // Modification
845 //              - Replaced resetIdComponent() with decRefCount() to use C
846 //              library ID reference counting mechanism - BMR, Jun 1, 2004
847 //              - Replaced decRefCount with close() to let the C library
848 //              handle the reference counting - BMR, Jun 1, 2006
849 //--------------------------------------------------------------------------
~DataSet()850 DataSet::~DataSet()
851 {
852     try {
853         close();
854     }
855     catch (Exception& close_error) {
856         cerr << "DataSet::~DataSet - " << close_error.getDetailMsg() << endl;
857     }
858 }
859 
860 } // end namespace
861