| 198 | } |
| 199 | |
| 200 | void ParseODirectHeader(HeaderData &parsed_header, InputStream *src, size_t o_direct_alignm, |
| 201 | size_t o_direct_read_len_alignm) { |
| 202 | const size_t token_len = 6 + 1 + 1 + 2; |
| 203 | size_t token_read_len = align_up(token_len + 1, o_direct_read_len_alignm); |
| 204 | auto token_mem = |
| 205 | mm::alloc_raw_shared<char, mm::memory_kind::host>(token_read_len, o_direct_alignm); |
| 206 | char *token = token_mem.get(); |
| 207 | auto file = dynamic_cast<ODirectFileStream *>(src); |
| 208 | DALI_ENFORCE( |
| 209 | file, |
| 210 | "Could not read the numpy file header: expected file stream opened with O_DIRECT flag."); |
| 211 | int64_t nread = file->ReadAt(token, token_read_len, 0); |
| 212 | DALI_ENFORCE(nread <= static_cast<Index>(token_read_len) && |
| 213 | nread >= static_cast<Index>(std::min(src->Size(), token_read_len)), |
| 214 | make_string("Can not read header: ", |
| 215 | static_cast<Index>(std::min(src->Size(), token_read_len)), " <= ", nread, |
| 216 | " <= ", token_read_len)); |
| 217 | auto char_tmp = token[token_len]; |
| 218 | token[token_len] = '\0'; |
| 219 | |
| 220 | CheckNpyVersion(token); |
| 221 | auto header_len = GetHeaderLen(token); |
| 222 | |
| 223 | // The header_len can have up to 2**16 - 1 bytes. We do not support V2 headers |
| 224 | // (with up to 4GB - 4 byte header len), as those are used by numpy to save structured |
| 225 | // arrays (where dtype can be different for each column and the columns have arbitrary names). |
| 226 | // Parsing such a dtype in the header will fail. |
| 227 | // https://numpy.org/neps/nep-0001-npy-format.html |
| 228 | size_t aligned_token_header_len = |
| 229 | align_up(token_len + header_len + 1, std::max(o_direct_alignm, o_direct_read_len_alignm)); |
| 230 | // if header_len goes beyond the previously allocated and read memory reallocate and read again |
| 231 | // otherwise reuse |
| 232 | if (token_read_len != aligned_token_header_len) { |
| 233 | token_mem = mm::alloc_raw_shared<char, mm::memory_kind::host>(aligned_token_header_len, |
| 234 | o_direct_alignm); |
| 235 | nread = file->ReadAt(token_mem.get(), aligned_token_header_len, 0); |
| 236 | DALI_ENFORCE(nread <= static_cast<Index>(aligned_token_header_len) && |
| 237 | nread >= static_cast<Index>(std::min(src->Size(), aligned_token_header_len)), |
| 238 | make_string("Can not read header: ", |
| 239 | static_cast<Index>(std::min(src->Size(), aligned_token_header_len)), |
| 240 | " <= ", nread, " <= ", aligned_token_header_len)); |
| 241 | } else { |
| 242 | // restore overriden character |
| 243 | token[token_len] = char_tmp; |
| 244 | } |
| 245 | char *header = token_mem.get() + token_len; |
| 246 | header[header_len] = '\0'; |
| 247 | ParseHeaderItself(parsed_header, header, header_len); |
| 248 | } |
| 249 | |
| 250 | void ParseHeader(HeaderData &parsed_header, InputStream *src) { |
| 251 | // check if the file is actually a numpy file |
no test coverage detected