File: load_attribute.hpp

package info (click to toggle)
r-bioc-alabaster.base 1.6.1%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,652 kB
  • sloc: cpp: 11,377; sh: 29; makefile: 2
file content (144 lines) | stat: -rw-r--r-- 5,294 bytes parent folder | download | duplicates (2)
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
#ifndef RITSUKO_HDF5_LOAD_ATTRIBUTE_HPP
#define RITSUKO_HDF5_LOAD_ATTRIBUTE_HPP

#include "H5Cpp.h"

#include <vector>
#include <string>

#include "get_1d_length.hpp"
#include "as_numeric_datatype.hpp"
#include "_strings.hpp"

/**
 * @file load_attribute.hpp
 * @brief Load HDF5 attributes.
 */

namespace ritsuko {

namespace hdf5 {

/**
 * @param attr Handle to a scalar string attribute.
 * Callers are responsible for checking that `attr` contains a string datatype class.
 * @return The attribute as a string.
 */
inline std::string load_scalar_string_attribute(const H5::Attribute& attr) {
    auto dtype = attr.getDataType();

    // Unfortunately, we can't just do 'std::string output; attr.read(dtype, output);', 
    // as we need to catch NULL pointers in the variable case.

    if (dtype.isVariableStr()) {
        auto mspace = attr.getSpace();
        char* buffer;
        attr.read(dtype, &buffer);
        [[maybe_unused]] VariableStringCleaner deletor(dtype.getId(), mspace.getId(), &buffer);
        if (buffer == NULL) {
            throw std::runtime_error("detected a NULL pointer for a variable length string attribute");
        }
        return std::string(buffer);

    } else {
        size_t len = dtype.getSize();
        std::vector<char> buffer(len);
        attr.read(dtype, buffer.data());
        auto ptr = buffer.data();
        return std::string(ptr, ptr + find_string_length(ptr, len));
    }
}

/**
 * @tparam check_ Whether to check that `attr` is a 1-dimensional string attribute.
 * @param attr Handle to a 1-dimensional string attribute.
 * Callers are responsible for checking that `attr` contains a string datatype class.
 * @param full_length Length of the attribute in `attr`, usually obtained by `get_1d_length()`.
 * @return Vector of strings.
 */
inline std::vector<std::string> load_1d_string_attribute(const H5::Attribute& attr, hsize_t full_length) {
    auto dtype = attr.getDataType();
    auto mspace = attr.getSpace();
    std::vector<std::string> output;
    output.reserve(full_length);

    if (dtype.isVariableStr()) {
        std::vector<char*> buffer(full_length);
        attr.read(dtype, buffer.data());
        [[maybe_unused]] VariableStringCleaner deletor(dtype.getId(), mspace.getId(), buffer.data());
        for (hsize_t i = 0; i < full_length; ++i) {
            if (buffer[i] == NULL) {
                throw std::runtime_error("detected a NULL pointer for a variable length string attribute");
            }
            output.emplace_back(buffer[i]);
        }

    } else {
        size_t len = dtype.getSize();
        std::vector<char> buffer(len * full_length);
        attr.read(dtype, buffer.data());
        auto ptr = buffer.data();
        for (size_t i = 0; i < full_length; ++i, ptr += len) {
            output.emplace_back(ptr, ptr + find_string_length(ptr, len));
        }
    }

    return output;
}

/**
 * Overload of `load_1d_string_attribute()` that determines the length of the attribute via `get_1d_length()`.
 * @param attr Handle to a 1-dimensional string attribute.
 * Callers are responsible for checking that `attr` contains a string datatype class.
 * @return Vector of strings.
 */
inline std::vector<std::string> load_1d_string_attribute(const H5::Attribute& attr) {
    return load_1d_string_attribute(attr, get_1d_length(attr.getSpace(), false));
}

/**
 * @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
 * @param attr Handle to a scalar numeric attribute.
 * Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
 * @return The value of the attribute.
 */
template<typename Type_>
Type_ load_scalar_numeric_attribute(const H5::Attribute& attr) {
    Type_ val;
    const auto& mtype = as_numeric_datatype<Type_>();
    attr.read(mtype, &val);
    return val;
}

/**
 * @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
 * @param attr Handle to a numeric attribute.
 * Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
 * @param full_length Length of the attribute in `attr`, usually obtained by `get_1d_length()`.
 * @return Vector containing the contents of the attribute.
 */
template<typename Type_>
std::vector<Type_> load_1d_numeric_attribute(const H5::Attribute& attr, hsize_t full_length) {
    const auto& mtype = as_numeric_datatype<Type_>();
    std::vector<Type_> buffer(full_length);
    attr.read(mtype, buffer.data());
    return buffer;
}

/**
 * Overload of `load_1d_numeric_attribute()` that determines the length of the attribute via `get_1d_length()`.
 * @tparam Type_ Type for holding the data in memory, see `as_numeric_datatype()` for supported types.
 * @param attr Handle to a numeric attribute.
 * Callers are responsible for checking that the datatype of `attr` is appropriate for `Type_`, e.g., with `exceeds_integer_limit()`.
 * @return Vector containing the contents of the attribute.
 */
template<typename Type_>
std::vector<Type_> load_1d_numeric_attribute(const H5::Attribute& attr) {
    return load_1d_numeric_attribute<Type_>(attr, get_1d_length(attr.getSpace(), false));
}

}

}

#endif