summaryrefslogtreecommitdiffstats
path: root/c++/src/H5IdComponent.cpp
blob: 93df34391c066254c73ee58aae2b72b8a2b56c15 (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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * 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.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <string>

#include "H5Include.h"
#include "H5Exception.h"
#include "H5Library.h"
#include "H5IdComponent.h"
#include "H5DataSpace.h"

namespace H5 {

#ifndef DOXYGEN_SHOULD_SKIP_THIS
// This flag indicates whether H5Library::initH5cpp has been called to register
// the terminating functions with atexit()
bool IdComponent::H5cppinit = false;

// This flag is used to decide whether H5dont_atexit should be called.
// Subclasses that have global constants use it.  This is a temporary
// work-around in 1.8.16.  It will be removed after HDFFV-9540 is fixed.
bool IdComponent::H5dontAtexit_called = false;
#endif // DOXYGEN_SHOULD_SKIP_THIS

//--------------------------------------------------------------------------
// Function:    IdComponent::incRefCount
///\brief       Increment reference counter for a given id.
//--------------------------------------------------------------------------
void
IdComponent::incRefCount(const hid_t obj_id) const
{
    if (p_valid_id(obj_id))
        if (H5Iinc_ref(obj_id) < 0)
            throw IdComponentException(inMemFunc("incRefCount"), "incrementing object ref count failed");
}

//--------------------------------------------------------------------------
// Function:    IdComponent::incRefCount
///\brief       Increment reference counter for the id of this object.
//--------------------------------------------------------------------------
void
IdComponent::incRefCount() const
{
    incRefCount(getId());
}

//--------------------------------------------------------------------------
// Function:    IdComponent::decRefCount
///\brief       Decrement reference counter for a given id.
// Modification:
//              Added the check for ref counter to give a little more info
//              on why H5Idec_ref fails in some cases - BMR 5/19/2005
//--------------------------------------------------------------------------
void
IdComponent::decRefCount(const hid_t obj_id) const
{
    if (p_valid_id(obj_id))
        if (H5Idec_ref(obj_id) < 0) {
            if (H5Iget_ref(obj_id) <= 0)
                throw IdComponentException(inMemFunc("decRefCount"), "object ref count is 0 or negative");
            else
                throw IdComponentException(inMemFunc("decRefCount"), "decrementing object ref count failed");
        }
}

//--------------------------------------------------------------------------
// Function:    IdComponent::decRefCount
///\brief       Decrement reference counter for the id of this object.
//--------------------------------------------------------------------------
void
IdComponent::decRefCount() const
{
    decRefCount(getId());
}

//--------------------------------------------------------------------------
// Function:    IdComponent::getCounter
///\brief       Returns the reference counter for a given id.
///\return      Reference count
//--------------------------------------------------------------------------
int
IdComponent::getCounter(const hid_t obj_id) const
{
    int counter = 0;
    if (p_valid_id(obj_id)) {
        counter = H5Iget_ref(obj_id);
        if (counter < 0)
            throw IdComponentException(inMemFunc("incRefCount"),
                                       "getting object ref count failed - negative");
    }
    return (counter);
}

//--------------------------------------------------------------------------
// Function:    IdComponent::getCounter
///\brief       Returns the reference counter for the id of this object.
///\return      Reference count
//--------------------------------------------------------------------------
int
IdComponent::getCounter() const
{
    return (getCounter(getId()));
}

//--------------------------------------------------------------------------
// Function:    getHDFObjType (static)
///\brief       Given an id, returns the type of the object.
///\return      a valid HDF object type, which may be one of the following:
///             \li \c H5I_FILE
///             \li \c H5I_GROUP
///             \li \c H5I_DATATYPE
///             \li \c H5I_DATASPACE
///             \li \c H5I_DATASET
///             \li \c H5I_ATTR
///             \li or \c H5I_BADID, if no valid type can be determined or the
///                         input object id is invalid.
//--------------------------------------------------------------------------
H5I_type_t
IdComponent::getHDFObjType(const hid_t obj_id)
{
    if (obj_id <= 0)
        return H5I_BADID; // invalid
    H5I_type_t id_type = H5Iget_type(obj_id);
    if (id_type <= H5I_BADID || id_type >= H5I_NTYPES)
        return H5I_BADID; // invalid
    else
        return id_type; // valid type
}

//--------------------------------------------------------------------------
// Function:    getHDFObjType
///\brief       Returns the type of the object.  It is an overloaded function
///             of the above function.
///\return      a valid HDF object type, which may be one of the following:
///             \li \c H5I_FILE
///             \li \c H5I_GROUP
///             \li \c H5I_DATATYPE
///             \li \c H5I_DATASPACE
///             \li \c H5I_DATASET
///             \li \c H5I_ATTR
///             \li or \c H5I_BADID, if no valid type can be determined or the
///                         input object id is invalid.
//--------------------------------------------------------------------------
H5I_type_t
IdComponent::getHDFObjType() const
{
    return (getHDFObjType(getId()));
}

//--------------------------------------------------------------------------
// Function:    getNumMembers (static)
///\brief       Returns the number of members of the given type.
///\return      Number of members
///\par Description
///             If there is no member of the given type, getNumMembers will
///             return 0.  Valid types are:
///             \li \c H5I_FILE (= 1)
///             \li \c H5I_GROUP
///             \li \c H5I_DATATYPE
///             \li \c H5I_DATASPACE
///             \li \c H5I_DATASET
///             \li \c H5I_ATTR
///             \li \c H5I_VFL
///             \li \c H5I_VOL
///             \li \c H5I_GENPROP_CLS
///             \li \c H5I_GENPROP_LST
///             \li \c H5I_ERROR_CLASS
///             \li \c H5I_ERROR_MSG
///             \li \c H5I_ERROR_STACK
//--------------------------------------------------------------------------
hsize_t
IdComponent::getNumMembers(H5I_type_t type)
{
    hsize_t nmembers  = 0;
    herr_t  ret_value = H5Inmembers(type, &nmembers);
    if (ret_value < 0)
        throw IdComponentException("getNumMembers", "H5Inmembers failed");
    else
        return (nmembers);
}

//--------------------------------------------------------------------------
// Function:    isValid (static)
///\brief       Checks if the given ID is valid.
///\return      true if the given identifier is valid, and false, otherwise.
///\par Description
///             A valid ID is one that is in use and has an application
///             reference count of at least 1.
//--------------------------------------------------------------------------
bool
IdComponent::isValid(hid_t an_id)
{
    // Call C function
    htri_t ret_value = H5Iis_valid(an_id);
    if (ret_value > 0)
        return true;
    else if (ret_value == 0)
        return false;
    else // Raise exception when H5Iis_valid returns a negative value
        throw IdComponentException("isValid", "H5Iis_valid failed");
}

//--------------------------------------------------------------------------
// Function:    typeExists (static)
///\brief       Queries if a given type is currently registered with the
///             library.
///\return      true if the given type exists, and false, otherwise.
///\par Description
///             Valid types are:
///             \li \c H5I_FILE (= 1)
///             \li \c H5I_GROUP
///             \li \c H5I_DATATYPE
///             \li \c H5I_DATASPACE
///             \li \c H5I_DATASET
///             \li \c H5I_ATTR
///             \li \c H5I_VFL
///             \li \c H5I_VOL
///             \li \c H5I_GENPROP_CLS
///             \li \c H5I_GENPROP_LST
///             \li \c H5I_ERROR_CLASS
///             \li \c H5I_ERROR_MSG
///             \li \c H5I_ERROR_STACK
//--------------------------------------------------------------------------
bool
IdComponent::typeExists(H5I_type_t type)
{
    // Call C function
    htri_t ret_value = H5Itype_exists(type);
    if (ret_value > 0)
        return true;
    else if (ret_value == 0)
        return false;
    else // Raise exception when H5Itype_exists returns a negative value
        throw IdComponentException("typeExists", "H5Itype_exists failed");
}

//--------------------------------------------------------------------------
// Function:    IdComponent::operator=
///\brief       Assignment operator.
///\param       rhs - IN: Reference to the existing object
///\return      Reference to IdComponent instance
///\exception   H5::IdComponentException when attempt to close the HDF5
///             object fails
// Description
//              First, close the current valid id of this object.  Then
//              copy the id from rhs to this object, and increment the
//              reference counter of the id to indicate that another object
//              is referencing that id.
// Modification
//        2010/5/9 - BMR
//              Removed close() and incRefCount() because setId/p_setId takes
//              care of close() and setId takes care incRefCount().
//--------------------------------------------------------------------------
IdComponent &
IdComponent::operator=(const IdComponent &rhs)
{
    if (this != &rhs) {
        // handling references to this id
        try {
            setId(rhs.getId());
            // Note: a = b, so there are two objects with the same hdf5 id
            // that's why incRefCount is needed, and it is called by setId
        }
        catch (Exception &close_error) {
            throw FileIException(inMemFunc("operator="), close_error.getDetailMsg());
        }
    }
    return *this;
}

//--------------------------------------------------------------------------
// Function:    IdComponent::setId
///\brief       Sets the identifier of this object to a new value.
///\param       new_id - IN: New identifier to be set to
///\exception   H5::IdComponentException when the attempt to close the HDF5
///             object fails
// Description:
//              p_setId ensures that the current valid id of this object is
//              properly closed before resetting the object's id to the new id.
// Modification
//        2008/7/23 - BMR
//              Changed all subclasses' setId to p_setId and put back setId
//              here.  p_setId is used in the library where the id provided
//              by a C API passed on to user's application in the form of a
//              C++ API object, which will be destroyed properly, and so
//              p_setId does not call incRefCount.  On the other hand, the
//              public version setId is used by other applications, in which
//              the id passed to setId is that of another C++ API object, so
//              setId must call incRefCount.
//--------------------------------------------------------------------------
void
IdComponent::setId(const hid_t new_id)
{
    // set to new_id
    p_setId(new_id);

    // increment the reference counter of the new id
    incRefCount();
}

//--------------------------------------------------------------------------
// Function:    IdComponent destructor
///\brief       Noop destructor.
//--------------------------------------------------------------------------
IdComponent::~IdComponent()
{
}

//
// Implementation of protected functions for HDF5 Reference Interface
// and miscellaneous helpers.
//

#ifndef DOXYGEN_SHOULD_SKIP_THIS
//--------------------------------------------------------------------------
// Function:    IdComponent::inMemFunc
///\brief       Makes and returns string "<class-name>::<func_name>"
///\param       func_name - Name of the function where failure occurs
// Description
///             Concatenates the class name of this object with the
///             passed-in function name to create a string that indicates
///             where the failure occurs.  The class-name is provided by
///             fromClass().  This string will be used by a base class when
///             an exception is thrown.
//--------------------------------------------------------------------------
H5std_string
IdComponent::inMemFunc(const char *func_name) const
{
    H5std_string full_name = func_name;
    full_name.insert(0, "::");
    full_name.insert(0, fromClass());
    return (full_name);
}

//--------------------------------------------------------------------------
// Function:    IdComponent default constructor - private
///\brief       Default constructor.
//--------------------------------------------------------------------------
IdComponent::IdComponent()
{
    // initH5cpp will register the terminating functions with atexit().
    // This should only be done once.
    if (!H5cppinit) {
        H5Library::initH5cpp();
        H5cppinit = true;
    }
}

//--------------------------------------------------------------------------
// Function:    IdComponent::p_get_file_name (protected)
// Purpose      Gets the name of the file, in which this object belongs.
// Exception:   H5::IdComponentException
// Description:
//              This function is protected so that the user applications can
//              only have access to its code via H5Location subclasses.
//      September 2017
//              This function should be moved to H5Location now that Attribute
//              inherits from H5Location.
//--------------------------------------------------------------------------
H5std_string
IdComponent::p_get_file_name() const
{
    hid_t temp_id = getId();

    // Preliminary call to H5Fget_name to get the length of the file name
    ssize_t name_size = H5Fget_name(temp_id, NULL, 0);

    // If H5Aget_name returns a negative value, raise an exception,
    if (name_size < 0) {
        throw IdComponentException("", "H5Fget_name failed");
    }

    // The actual message size is the cast value + 1 for the terminal ASCII NUL
    // (unfortunate in/out type sign mismatch)
    size_t actual_name_size = static_cast<size_t>(name_size) + 1;

    // Call H5Fget_name again to get the actual file name
    char *name_C = new char[actual_name_size]();

    name_size = H5Fget_name(temp_id, name_C, actual_name_size);

    // Check for failure again
    if (name_size < 0) {
        delete[] name_C;
        throw IdComponentException("", "H5Fget_name failed");
    }

    // Convert the C file name and return
    H5std_string file_name(name_C);
    delete[] name_C;

    return file_name;
}

//
// Local functions used in this class
//

//--------------------------------------------------------------------------
// Function:    p_valid_id
// Purpose      Verifies that the given id is a valid id so it can be passed
//              into an H5I C function.
// Return       true if id is valid, false, otherwise
//--------------------------------------------------------------------------
bool
IdComponent::p_valid_id(const hid_t obj_id)
{
    if (obj_id <= 0)
        return false;

    H5I_type_t id_type = H5Iget_type(obj_id);
    return (id_type > H5I_BADID && id_type < H5I_NTYPES);
}

// Notes about IdComponent::id
//      May 2008 - BMR
//              Class hierarchy is revised to address bugzilla 1068...
//              ...member IdComponent::id is moved into subclasses, and
//              IdComponent::getId now becomes pure virtual function.
//              (reasons: 1. encountered problems when adding H5Location;
//                        2. Scott Meyers, item 33)

#endif // DOXYGEN_SHOULD_SKIP_THIS

} // namespace H5