| 101 | } |
| 102 | |
| 103 | bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMetadata& metadata) { |
| 104 | // Open all three files, writing to meta, reading from spine and toc |
| 105 | if (!Storage.openFileForWrite("BMC", cachePath + bookBinFile, bookFile)) { |
| 106 | return false; |
| 107 | } |
| 108 | |
| 109 | if (!Storage.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) { |
| 110 | // Explicit close() required: member variable persists beyond function scope |
| 111 | bookFile.close(); |
| 112 | return false; |
| 113 | } |
| 114 | |
| 115 | if (!Storage.openFileForRead("BMC", cachePath + tmpTocBinFile, tocFile)) { |
| 116 | // Explicit close() required: member variables persist beyond function scope |
| 117 | bookFile.close(); |
| 118 | spineFile.close(); |
| 119 | return false; |
| 120 | } |
| 121 | |
| 122 | constexpr uint32_t headerASize = |
| 123 | sizeof(BOOK_CACHE_VERSION) + /* LUT Offset */ sizeof(uint32_t) + sizeof(spineCount) + sizeof(tocCount); |
| 124 | const uint32_t metadataSize = metadata.title.size() + metadata.author.size() + metadata.language.size() + |
| 125 | metadata.coverItemHref.size() + metadata.textReferenceHref.size() + |
| 126 | sizeof(uint32_t) * 5; |
| 127 | const uint32_t lutSize = sizeof(uint32_t) * spineCount + sizeof(uint32_t) * tocCount; |
| 128 | const uint32_t lutOffset = headerASize + metadataSize; |
| 129 | |
| 130 | // Header A |
| 131 | serialization::writePod(bookFile, BOOK_CACHE_VERSION); |
| 132 | serialization::writePod(bookFile, lutOffset); |
| 133 | serialization::writePod(bookFile, spineCount); |
| 134 | serialization::writePod(bookFile, tocCount); |
| 135 | // Metadata |
| 136 | serialization::writeString(bookFile, metadata.title); |
| 137 | serialization::writeString(bookFile, metadata.author); |
| 138 | serialization::writeString(bookFile, metadata.language); |
| 139 | serialization::writeString(bookFile, metadata.coverItemHref); |
| 140 | serialization::writeString(bookFile, metadata.textReferenceHref); |
| 141 | |
| 142 | // Loop through spine entries, writing LUT positions |
| 143 | spineFile.seek(0); |
| 144 | for (int i = 0; i < spineCount; i++) { |
| 145 | uint32_t pos = spineFile.position(); |
| 146 | auto spineEntry = readSpineEntry(spineFile); |
| 147 | serialization::writePod(bookFile, pos + lutOffset + lutSize); |
| 148 | } |
| 149 | |
| 150 | // Loop through toc entries, writing LUT positions |
| 151 | tocFile.seek(0); |
| 152 | for (int i = 0; i < tocCount; i++) { |
| 153 | uint32_t pos = tocFile.position(); |
| 154 | auto tocEntry = readTocEntry(tocFile); |
| 155 | serialization::writePod(bookFile, pos + lutOffset + lutSize + static_cast<uint32_t>(spineFile.position())); |
| 156 | } |
| 157 | |
| 158 | // LUTs complete |
| 159 | // Loop through spines from spine file matching up TOC indexes, calculating cumulative size and writing to book.bin |
| 160 |
no test coverage detected