ritsuko
Helper utilities for ArtifactDB C++ code
Loading...
Searching...
No Matches
Stream1dArray.hpp
Go to the documentation of this file.
1#ifndef RITSUKO_CVLS_STREAM_1D_ARRAY_HPP
2#define RITSUKO_CVLS_STREAM_1D_ARRAY_HPP
3
4#include <vector>
5#include <string>
6#include <stdexcept>
7#include <cstdint>
8#include <cassert>
9#include <algorithm>
10
11#include "H5Cpp.h"
13
14#include "../strnlen.hpp"
15#include "../itoa.hpp"
16#include "Pointer.hpp"
17
23namespace ritsuko {
24
25namespace cvls {
26
37
49template<typename Offset_, typename Length_, typename DataSetPointer_ = const H5::DataSet*>
51public:
63 Stream1dArray(DataSetPointer_ pointers_ptr, hsize_t pointers_length, DataSetPointer_ heap_ptr, hsize_t heap_length, const Stream1dArrayOptions& options) :
64 my_pointers_ptr(std::move(pointers_ptr)),
65 my_heap_ptr(std::move(heap_ptr)),
66 my_pointer_full_length(pointers_length),
67 my_heap_full_length(heap_length),
68 my_pointer_block_size([&]{
69 assert(my_pointers_ptr->getSpace().getSimpleExtentNdims() == 1);
70 hsize_t output;
71 const auto& plist = my_pointers_ptr->getCreatePlist();
72 if (plist.getLayout() == H5D_CHUNKED) {
73 plist.getChunk(1, &output);
74 } else {
75 output = std::min(my_pointer_full_length, options.contiguous_chunk_size);
76 }
77 return output;
78 }()),
79 my_pointer_mspace(1, &my_pointer_block_size),
80 my_pointer_dspace(1, &my_pointer_full_length),
81 my_heap_dspace(1, &my_heap_full_length),
83 my_pointer_buffer(sanisizer::cast<I<decltype(my_pointer_buffer.size())> >(my_pointer_block_size))
84 {
85 // Check that maximum allocation is possible, so we don't have to check casts for individual string lengths.
86 sanisizer::cast<I<decltype(my_heap_buffer.size())> >(my_heap_full_length);
87 }
88
89public:
93 hsize_t chunk_size() const {
94 return my_pointer_block_size;
95 }
96
107 hsize_t load(std::string* buffer) {
108 my_last_loaded += my_available;
109 my_available = std::min(my_pointer_full_length - my_last_loaded, my_pointer_block_size);
110 if (my_available == 0) {
111 return 0;
112 }
113
114 constexpr hsize_t zero = 0;
115 my_pointer_mspace.selectHyperslab(H5S_SELECT_SET, &my_available, &zero);
116 my_pointer_dspace.selectHyperslab(H5S_SELECT_SET, &my_available, &my_last_loaded);
117 my_heap_dspace.selectNone();
118 my_pointers_ptr->read(my_pointer_buffer.data(), my_pointer_dtype, my_pointer_mspace, my_pointer_dspace);
119
120 for (I<decltype(my_available)> i = 0; i < my_available; ++i) {
121 const auto& val = my_pointer_buffer[i];
122 if (is_Pointer_out_of_range(val, my_heap_full_length)) {
123 throw std::runtime_error("pointer is out of range of the heap at position " + itoa(i + my_last_loaded));
124 }
125
126 auto& curstr = buffer[i];
127 curstr.clear();
128
129 if (val.length) {
130 // Casts are safe if the pointers are within range.
131 const hsize_t start = val.offset;
132 const hsize_t count = val.length;
133
134 // Don't attempt to batch these reads as we aren't guaranteed
135 // that they are non-overlapping or ordered. Hopefully HDF5 is
136 // keeping enough things in cache for repeated reads.
137 my_heap_mspace.setExtentSimple(1, &count);
138 my_heap_mspace.selectAll();
139 my_heap_dspace.selectHyperslab(H5S_SELECT_SET, &count, &start);
140 my_heap_buffer.resize(count);
141 my_heap_ptr->read(my_heap_buffer.data(), H5::PredType::NATIVE_UINT8, my_heap_mspace, my_heap_dspace);
142 const char* text_ptr = reinterpret_cast<const char*>(my_heap_buffer.data());
143 curstr.insert(curstr.end(), text_ptr, text_ptr + strnlen(text_ptr, count));
144 }
145 }
146
147 return my_available;
148 }
149
157 hsize_t start() const {
158 return my_last_loaded;
159 }
160
161private:
162 DataSetPointer_ my_pointers_ptr;
163 DataSetPointer_ my_heap_ptr;
164 hsize_t my_pointer_full_length, my_heap_full_length;
165 hsize_t my_pointer_block_size;
166 H5::DataSpace my_pointer_mspace, my_pointer_dspace;
167 H5::DataSpace my_heap_mspace, my_heap_dspace;
168
169 H5::DataType my_pointer_dtype;
170 std::vector<Pointer<Offset_, Length_> > my_pointer_buffer;
171 std::vector<std::uint8_t> my_heap_buffer;
172
173 hsize_t my_last_loaded = 0;
174 hsize_t my_available = 0;
175
176 static_assert(std::is_base_of<H5::DataSet, I<decltype(*my_pointers_ptr)> >::value);
177 static_assert(std::is_base_of<H5::DataSet, I<decltype(*my_heap_ptr)> >::value);
178};
179
180}
181
182}
183
184#endif
Compound datatype of the compresed VLS heap pointer.
Stream a 1-dimensional compressed VLS array into memory.
Definition Stream1dArray.hpp:50
Stream1dArray(DataSetPointer_ pointers_ptr, hsize_t pointers_length, DataSetPointer_ heap_ptr, hsize_t heap_length, const Stream1dArrayOptions &options)
Definition Stream1dArray.hpp:63
hsize_t load(std::string *buffer)
Definition Stream1dArray.hpp:107
hsize_t chunk_size() const
Definition Stream1dArray.hpp:93
hsize_t start() const
Definition Stream1dArray.hpp:157
Convert an integer to a string.
H5::CompType define_pointer_datatype()
Definition Pointer.hpp:70
bool is_Pointer_out_of_range(const Pointer< Offset_, Length_ > &ptr, const hsize_t heap_length)
Definition Pointer.hpp:142
Helper functions for ArtifactDB parsing and validation.
Definition Pointer.hpp:22
std::size_t strnlen(const char *ptr, std::size_t max)
Definition strnlen.hpp:23
void itoa(Integer_ x, std::string &output)
Definition itoa.hpp:26
constexpr Dest_ cap(Value_ x)
constexpr Dest_ cast(Value_ x)
Determine the length of a fixed-size string.
Options for Stream1dArray.
Definition Stream1dArray.hpp:30
hsize_t contiguous_chunk_size
Definition Stream1dArray.hpp:35