| 30 | } |
| 31 | |
| 32 | blink::msf_reader::msf_reader(const std::string &path) : |
| 33 | _file_stream(path, std::ios::in | std::ios::binary) |
| 34 | { |
| 35 | if (!_file_stream.is_open()) |
| 36 | return; |
| 37 | |
| 38 | // Read and verify MSF header from file |
| 39 | msf_file_header header; |
| 40 | _file_stream.read(reinterpret_cast<char *>(&header), sizeof(header)); |
| 41 | |
| 42 | static constexpr char signature[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"; |
| 43 | |
| 44 | if (_file_stream.bad() || std::memcmp(header.signature, signature, sizeof(signature)) != 0) |
| 45 | return; |
| 46 | |
| 47 | // Read root directory |
| 48 | const auto num_root_pages = calc_page_count(header.directory_size, header.page_size); |
| 49 | const auto num_root_index_pages = calc_page_count(num_root_pages * 4, header.page_size); |
| 50 | std::vector<uint32_t> root_pages(num_root_pages); |
| 51 | std::vector<uint32_t> root_index_pages(num_root_index_pages); |
| 52 | |
| 53 | if (num_root_index_pages == 0) |
| 54 | return; |
| 55 | |
| 56 | _page_size = header.page_size; |
| 57 | |
| 58 | _file_stream.read(reinterpret_cast<char *>(root_index_pages.data()), num_root_index_pages * 4); |
| 59 | |
| 60 | for (uint32_t i = 0, k = 0, len; i < num_root_index_pages; i++, k += len) |
| 61 | { |
| 62 | len = std::min(_page_size / 4, num_root_pages - k); |
| 63 | |
| 64 | _file_stream.seekg(root_index_pages[i] * _page_size); |
| 65 | _file_stream.read(reinterpret_cast<char *>(&root_pages[k]), len * 4); |
| 66 | } |
| 67 | |
| 68 | // Read content stream sizes |
| 69 | uint32_t current_root_page = 0; |
| 70 | |
| 71 | for (uint32_t i = 0, j = 0; i < num_root_pages; i++) |
| 72 | { |
| 73 | _file_stream.seekg(root_pages[i] * _page_size); |
| 74 | |
| 75 | if (i == 0) |
| 76 | { |
| 77 | _file_stream.read(reinterpret_cast<char *>(&j), sizeof(j)); |
| 78 | _streams.reserve(j); |
| 79 | } |
| 80 | |
| 81 | for (uint32_t k = i == 0, size; j > 0 && k < _page_size / 4; k++, j--) |
| 82 | { |
| 83 | _file_stream.read(reinterpret_cast<char *>(&size), sizeof(size)); |
| 84 | if (0xFFFFFFFF == size) |
| 85 | size = 0; |
| 86 | _streams.push_back({ size }); |
| 87 | } |
| 88 | |
| 89 | if (j == 0) |
nothing calls this directly
no test coverage detected