summaryrefslogtreecommitdiffstats
path: root/c++/src/H5DataType.cpp
blob: 5463722f19863c9555af5a5516bb00a62e692710 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
#include <string>

#include "H5Include.h"
#include "H5RefCounter.h"
#include "H5Exception.h"
#include "H5IdComponent.h"
#include "H5Idtemplates.h"
#include "H5PropList.h"
#include "H5Object.h"
#include "H5DataType.h"
#include "H5AtomType.h"
#include "H5PredType.h"
#include "H5private.h"

#ifndef H5_NO_NAMESPACE
namespace H5 {
#endif

// Constructor creates a copy of an existing DataType using its id.
// 'predefined' is default to false; when a default datatype is 
// created, this argument is set to true so H5Tclose will not be 
// called on it later.
DataType::DataType( const hid_t existing_id, bool predefined ) : H5Object( existing_id ), is_predtype( predefined ) {
}

// Creates a datatype given its class and size
DataType::DataType( const H5T_class_t type_class, size_t size ) : H5Object(), is_predtype( false )
{
   // Call C routine to create the new datatype
   id = H5Tcreate( type_class, size );
   if( id <= 0 )
   {
      throw DataTypeIException("DataType constructor", "H5Tcreate failed");
   }
}

// Default constructor
DataType::DataType() : H5Object(), is_predtype( false )
{
}

// Copy constructor: makes a copy of this DataType object.
DataType::DataType( const DataType& original ) : H5Object( original  )
{
   is_predtype = original.is_predtype; // copy data member from original
}

// Copies an existing datatype to this datatype object
void DataType::copy( const DataType& like_type )
{
   // reset the identifier of this instance, H5Tclose will be called 
   // if needed 
    try {
        resetIdComponent( this ); }
    catch (Exception close_error) { // thrown by p_close
        throw DataTypeIException("DataType::copy", close_error.getDetailMsg());
    }

   // call C routine to copy the datatype
   id = H5Tcopy( like_type.getId() );

   // new reference counter for this id
   ref_count = new RefCounter;

   if( id <= 0 )
   {
      throw DataTypeIException("DataType::copy", "H5Tcopy failed");
   }
}

// Makes a copy of the type on the right hand side and stores the new
// id in the left hand side object.  
DataType& DataType::operator=( const DataType& rhs )
{
   copy(rhs);
   return(*this);
}

// Determines whether two datatypes refer to the same actual datatype.
bool DataType::operator==(const DataType& compared_type ) const
{
   // Call C routine H5Tequal to determines whether two datatype 
   // identifiers refer to the same datatype
   htri_t ret_value = H5Tequal( id, compared_type.getId() );
   if( ret_value > 0 )
      return true;
   else if( ret_value == 0 )
      return false;
   else
   {
      throw DataTypeIException("DataType::operator==", 
		"H5Tequal returns negative value");
   }
}

// Operates a user's function on each attribute of an object - commented
// out because it should use the one from H5Object; need to check 
// the parameter list???  - work in progress
//int DataType::iterate( unsigned * idx, H5A_operator_t op, void *op_data )
//{
//}

// Creates a new variable-length datatype - Note: should use inheritance -
// work in progress
//DataType DataType::vlenCreate( const DataType& base_type )
//{
//}

// Commits a transient datatype to a file, creating a new named datatype
void DataType::commit( H5Object& loc, const string& name ) const
{
   commit( loc, name.c_str() );
}
void DataType::commit( H5Object& loc, const char* name ) const
{
   hid_t loc_id = loc.getId(); // get location id for C API

   // Call C routine to commit the transient datatype 
   herr_t ret_value = H5Tcommit( loc_id, name, id );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::commit", "H5Tcommit failed");
   }
}

// Determines whether a datatype is a named type or a transient type. 
bool DataType::committed() const
{
   // Call C function to determine if a datatype is a named one
   htri_t committed = H5Tcommitted( id );
   if( committed > 0 )
      return true;
   else if( committed == 0 )
      return false;
   else
   {
      throw DataTypeIException("DataType::committed", "H5Tcommitted return negative value");
   }
}

// Finds a conversion function.
H5T_conv_t DataType::find( const DataType& dest, H5T_cdata_t **pcdata ) const
{
   // Call C routine to find the conversion function
   H5T_conv_t func = H5Tfind( id, dest.getId(), pcdata );
   if( func == NULL )
   {
      throw DataTypeIException("DataType::find", "H5Tfind returns a NULL function");
   }
   return( func );
}

// Converts data from between specified datatypes. 
void DataType::convert( const DataType& dest, hsize_t nelmts, void *buf, void *background, PropList& plist ) const
{
   // Get identifiers for C API
   hid_t dest_id = dest.getId();
   hid_t plist_id = plist.getId();

   // Call C routine H5Tconvert to convert the data
   herr_t ret_value;
   ret_value = H5Tconvert( id, dest_id, nelmts, buf, background, plist_id );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::convert", "H5Tconvert failed");
   }
}

// Sets the overflow handler to a specified function. 
void DataType::setOverflow( H5T_overflow_t func ) const
{
   // Call C routine H5Tset_overflow to set the overflow handler
   herr_t ret_value = H5Tset_overflow( func );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::setOverflow", "H5Tset_overflow failed");
   }
}

// Returns a pointer to the current global overflow function. 
H5T_overflow_t DataType::getOverflow(void) const
{
   return( H5Tget_overflow());  // C routine
   // NULL can be returned as well
}

// Locks a datatype. 
void DataType::lock() const
{
   // Call C routine to lock the datatype
   herr_t ret_value = H5Tlock( id );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::lock", "H5Tlock failed");
   }
}

// Returns the datatype class identifier. 
H5T_class_t DataType::getClass() const
{
   H5T_class_t type_class = H5Tget_class( id );

   // Return datatype class identifier if successful
   if( type_class == H5T_NO_CLASS )
   {
      throw DataTypeIException("DataType::getClass", 
		"H5Tget_class returns H5T_NO_CLASS");
   }
   return( type_class );
}

// Returns the size of a datatype. 
size_t DataType::getSize() const
{
   // Call C routine to get the datatype size
   size_t type_size = H5Tget_size( id );
   if( type_size <= 0 ) // valid data types are never zero size
   {
      throw DataTypeIException("DataType::getSize", 
		"H5Tget_size returns invalid datatype size");
   }
   return( type_size );
}

// Returns the base datatype from which a datatype is derived. 
// - just for DataType?
DataType DataType::getSuper() const
{
   // Call C routine to get the base datatype from which the specified
   // datatype is derived. 
   hid_t base_type_id = H5Tget_super( id );

   // If H5Tget_super returns a valid datatype id, create and return
   // the base type, otherwise, raise exception
   if( base_type_id > 0 )
   {
      DataType base_type( base_type_id );
      return( base_type );
   }
   else
   {
      throw DataTypeIException("DataType::getSuper", "H5Tget_super failed");
   }
}

// Registers the specified conversion function. 
void DataType::registerFunc( H5T_pers_t pers, const string& name, const DataType& dest, H5T_conv_t func ) const
{
   registerFunc( pers, name.c_str(), dest, func );
}
void DataType::registerFunc( H5T_pers_t pers, const char* name, const DataType& dest, H5T_conv_t func ) const
{
   hid_t dest_id = dest.getId();  // get id of the destination datatype

   // Call C routine H5Tregister to register the conversion function
   herr_t ret_value = H5Tregister( pers, name, id, dest_id, func );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::registerFunc", "H5Tregister failed");
   }
}

// Removes a conversion function from all conversion paths. 
void DataType::unregister( H5T_pers_t pers, const string& name, const DataType& dest, H5T_conv_t func ) const
{
   unregister( pers, name.c_str(), dest, func );
}
void DataType::unregister( H5T_pers_t pers, const char* name, const DataType& dest, H5T_conv_t func ) const
{
   hid_t dest_id = dest.getId();  // get id of the dest datatype for C API

   // Call C routine H5Tunregister to remove the conversion function 
   herr_t ret_value = H5Tunregister( pers, name, id, dest_id, func );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::unregister", "H5Tunregister failed");
   }
}

// Tags an opaque datatype. 
void DataType::setTag( const string& tag ) const
{
   setTag( tag.c_str());
}
void DataType::setTag( const char* tag ) const
{
   // Call C routine H5Tset_tag to tag an opaque datatype. 
   herr_t ret_value = H5Tset_tag( id, tag );
   if( ret_value < 0 )
   {
      throw DataTypeIException("DataType::setTag", "H5Tset_tag failed");
   }
}

// Gets the tag associated with an opaque datatype. 
string DataType::getTag() const
{
   char* tag_Cstr = H5Tget_tag( id );

   // if the tag C-string returned is not NULL, convert it to C++ string
   // and return it, otherwise, raise an exception
   if( tag_Cstr != NULL )
   {
      string tag = string(tag_Cstr); // convert C string to string object
	HDfree(tag_Cstr); // free the C string 
      return (tag); // return the tag 
   }
   else
   {
      throw DataTypeIException("DataType::getTag", 
		"H5Tget_tag returns NULL for tag");
   }
}

// This private function calls the C API H5Tclose to close this datatype.
// Used by H5Object::p_reset.
void DataType::p_close() const
{
   // If this datatype is not a predefined type, call H5Tclose on it.
   if( is_predtype == false )
   {
      herr_t ret_value = H5Tclose( id );
      if( ret_value < 0 )
      {
         throw DataTypeIException(0, "H5Tclose failed");
      }
   }
}

// The destructor of this instance calls IdComponent::reset to
// reset its identifier - no longer true
// Older compilers (baldric) don't support template member functions
// and IdComponent::reset is one; so at this time, the resetId is not
// a member function so it can be template to work around that problem.
DataType::~DataType()
{  
   // The datatype id will be closed properly
    try {
        resetIdComponent( this ); }
    catch (Exception close_error) { // thrown by p_close
        throw DataTypeIException("DataType::~DataType", close_error.getDetailMsg());
    }
}  

#ifndef H5_NO_NAMESPACE
} // end namespace
#endif