| 282 | } |
| 283 | |
| 284 | static TOffsetMap FindEquivalentSubtries(const TOpaqueTrie& trie, bool verbose, size_t minMergeSize) { |
| 285 | // Tree nodes, arranged by span length. |
| 286 | // When all nodes of a given size are considered, they pop off the queue. |
| 287 | TPieceIndex subtries; |
| 288 | TOffsetMap merger; |
| 289 | // Start walking the trie from head. |
| 290 | AddPiece(subtries, 0, trie.Length); |
| 291 | |
| 292 | size_t counter = 0; |
| 293 | // Now consider all nodes with sizeable continuations |
| 294 | for (size_t curlen = trie.Length; curlen >= minMergeSize && !subtries.empty(); curlen--) { |
| 295 | TPieceIndex::iterator iit = subtries.find(curlen); |
| 296 | |
| 297 | if (iit == subtries.end()) |
| 298 | continue; // fast forward to the next available length value |
| 299 | |
| 300 | TOffsetList& batch = iit->second; |
| 301 | TPieceComparer comparer(trie.Data, curlen); |
| 302 | Sort(batch.begin(), batch.end(), comparer); |
| 303 | |
| 304 | TOffsetList::iterator it = batch.begin(); |
| 305 | while (it != batch.end()) { |
| 306 | if (verbose) |
| 307 | ShowProgress(++counter); |
| 308 | |
| 309 | size_t offset = *it; |
| 310 | |
| 311 | // Fill the array with the subnodes of the element |
| 312 | TNode node(trie.Data, offset, trie.SkipFunction); |
| 313 | size_t end = offset + curlen; |
| 314 | if (size_t rightOffset = node.GetRightOffset()) { |
| 315 | AddPiece(subtries, rightOffset, end - rightOffset); |
| 316 | end = rightOffset; |
| 317 | } |
| 318 | if (size_t leftOffset = node.GetLeftOffset()) { |
| 319 | AddPiece(subtries, leftOffset, end - leftOffset); |
| 320 | end = leftOffset; |
| 321 | } |
| 322 | if (size_t forwardOffset = node.GetForwardOffset()) { |
| 323 | AddPiece(subtries, forwardOffset, end - forwardOffset); |
| 324 | } |
| 325 | |
| 326 | while (++it != batch.end()) { |
| 327 | // Find next different; until then, just add the offsets to the list of merged nodes. |
| 328 | size_t nextoffset = *it; |
| 329 | |
| 330 | if (memcmp(trie.Data + offset, trie.Data + nextoffset, curlen)) |
| 331 | break; |
| 332 | |
| 333 | merger.Add(nextoffset, offset); |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | subtries.erase(curlen); |
| 338 | } |
| 339 | if (verbose) { |
| 340 | Cerr << counter << Endl; |
| 341 | } |
no test coverage detected