| 234 | |
| 235 | template <typename Reader> |
| 236 | std::string ExtractString(Reader & reader, size_t stringIx) |
| 237 | { |
| 238 | InitializeIfNeeded(reader); |
| 239 | |
| 240 | auto const blockIx = m_index.GetBlockIx(stringIx); |
| 241 | CHECK_LESS(blockIx, m_index.GetNumBlockInfos(), ()); |
| 242 | |
| 243 | auto const & bi = m_index.GetBlockInfo(blockIx); |
| 244 | |
| 245 | bool found; |
| 246 | auto & entry = m_cache.Find(blockIx, found); |
| 247 | if (!found) |
| 248 | { |
| 249 | NonOwningReaderSource source(reader); |
| 250 | source.Skip(bi.m_offset); |
| 251 | |
| 252 | entry.m_value.clear(); |
| 253 | entry.m_subs.resize(static_cast<size_t>(bi.m_subs)); |
| 254 | |
| 255 | uint64_t offset = 0; |
| 256 | for (size_t i = 0; i < entry.m_subs.size(); ++i) |
| 257 | { |
| 258 | auto & sub = entry.m_subs[i]; |
| 259 | sub.m_offset = offset; |
| 260 | sub.m_length = ReadVarUint<uint64_t>(source); |
| 261 | CHECK_GREATER_OR_EQUAL(sub.m_offset + sub.m_length, sub.m_offset, ()); |
| 262 | offset += sub.m_length; |
| 263 | } |
| 264 | entry.m_value = BWTCoder::ReadAndDecodeBlock(source); |
| 265 | } |
| 266 | |
| 267 | ASSERT_GREATER_OR_EQUAL(stringIx, bi.From(), ()); |
| 268 | ASSERT_LESS(stringIx, bi.To(), ()); |
| 269 | |
| 270 | stringIx -= bi.From(); |
| 271 | ASSERT_LESS(stringIx, entry.m_subs.size(), ()); |
| 272 | |
| 273 | auto const & si = entry.m_subs[stringIx]; |
| 274 | auto const & value = entry.m_value; |
| 275 | ASSERT_LESS_OR_EQUAL(si.m_offset + si.m_length, value.size(), ()); |
| 276 | auto const beg = value.begin() + si.m_offset; |
| 277 | return std::string(beg, beg + si.m_length); |
| 278 | } |
| 279 | |
| 280 | private: |
| 281 | struct StringInfo |
nothing calls this directly
no test coverage detected