diff --git a/coding/bit_streams.hpp b/coding/bit_streams.hpp index 46656b37af..5bc00a9419 100644 --- a/coding/bit_streams.hpp +++ b/coding/bit_streams.hpp @@ -66,7 +66,6 @@ public: } m_buf = bits; } - m_flushed = false; } private: @@ -82,7 +81,6 @@ private: TWriter & m_writer; uint8_t m_buf; uint64_t m_bitsWritten; - bool m_flushed; }; template diff --git a/coding/coding_tests/succinct_trie_test.cpp b/coding/coding_tests/succinct_trie_test.cpp index 0d1bc347b1..ed8ae3cf27 100644 --- a/coding/coding_tests/succinct_trie_test.cpp +++ b/coding/coding_tests/succinct_trie_test.cpp @@ -21,12 +21,12 @@ namespace struct StringsFileEntryMock { StringsFileEntryMock() = default; - StringsFileEntryMock(string const & key, uint8_t value) : m_value(value) + StringsFileEntryMock(string const & key, uint8_t value) + : m_key(key.begin(), key.end()), m_value(value) { - m_key.insert(m_key.end(), key.begin(), key.end()); } - trie::TrieChar const * GetKeyData() { return &m_key[0]; } + trie::TrieChar const * GetKeyData() { return m_key.data(); } size_t GetKeySize() const { return m_key.size(); } @@ -34,7 +34,11 @@ struct StringsFileEntryMock void * value_data() const { return nullptr; } size_t value_size() const { return 0; } - void Swap(StringsFileEntryMock const & o) {} + void Swap(StringsFileEntryMock & o) + { + swap(m_key, o.m_key); + swap(m_value, o.m_value); + } bool operator==(const StringsFileEntryMock & o) const { @@ -56,7 +60,7 @@ template struct EmptyValueList { size_t size() const { return 0; } - void Dump(TWriter & writer) const {} + void Dump(TWriter &) const {} void Append(int) {} }; @@ -96,30 +100,25 @@ struct SimpleValueList vector m_valueList; }; -vector ReadAllValues( - trie::SuccinctTrieIterator * root) +void ReadAllValues(unique_ptr> const & root, + vector & values) { - vector values; for (size_t i = 0; i < root->NumValues(); ++i) values.push_back(root->GetValue(i)); - return values; } -void CollectInSubtree( - trie::SuccinctTrieIterator * root, - vector & collectedValues) +void CollectInSubtree(unique_ptr> const & root, + vector & collectedValues) { - auto valuesHere = ReadAllValues(root); - collectedValues.insert(collectedValues.end(), valuesHere.begin(), valuesHere.end()); + ReadAllValues(root, collectedValues); - auto * l = root->GoToEdge(0); - auto * r = root->GoToEdge(1); - if (l) + if (auto l = root->GoToEdge(0)) CollectInSubtree(l, collectedValues); - if (r) + if (auto r = root->GoToEdge(1)) CollectInSubtree(r, collectedValues); } - } // namespace namespace trie @@ -137,8 +136,7 @@ UNIT_TEST(SuccinctTrie_Serialization_Smoke1) using TWriter = MemWriter>; TWriter memWriter(buf); - vector data; - data.push_back(StringsFileEntryMock("abacaba", 1)); + vector data = {StringsFileEntryMock("abacaba", 1)}; trie::BuildSuccinctTrie::iterator, trie::EmptyEdgeBuilder, EmptyValueList>(memWriter, data.begin(), data.end(), @@ -146,11 +144,11 @@ UNIT_TEST(SuccinctTrie_Serialization_Smoke1) MemReader memReader(buf.data(), buf.size()); - using EmptyValueType = trie::EmptyValueReader::ValueType; + using TEmptyValue = trie::EmptyValueReader::ValueType; - unique_ptr> - trieRoot( - trie::ReadSuccinctTrie(memReader, trie::EmptyValueReader(), trie::EmptyValueReader())); + auto trieRoot = + trie::ReadSuccinctTrie(memReader, trie::EmptyValueReader(), trie::EmptyValueReader()); + TEST(trieRoot, ()); } UNIT_TEST(SuccinctTrie_Serialization_Smoke2) @@ -160,8 +158,7 @@ UNIT_TEST(SuccinctTrie_Serialization_Smoke2) using TWriter = MemWriter>; TWriter memWriter(buf); - vector data; - data.push_back(StringsFileEntryMock("abacaba", 1)); + vector data = {StringsFileEntryMock("abacaba", 1)}; trie::BuildSuccinctTrie::iterator, trie::EmptyEdgeBuilder, SimpleValueList>(memWriter, data.begin(), data.end(), @@ -169,10 +166,10 @@ UNIT_TEST(SuccinctTrie_Serialization_Smoke2) MemReader memReader(buf.data(), buf.size()); - using EmptyValueType = trie::EmptyValueReader::ValueType; + using TEmptyValue = trie::EmptyValueReader::ValueType; - unique_ptr> - trieRoot(trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader())); + auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader()); + TEST(trieRoot, ()); } UNIT_TEST(SuccinctTrie_Iterator) @@ -182,12 +179,9 @@ UNIT_TEST(SuccinctTrie_Iterator) using TWriter = MemWriter>; TWriter memWriter(buf); - vector data; - data.push_back(StringsFileEntryMock("a", 1)); - data.push_back(StringsFileEntryMock("b", 2)); - data.push_back(StringsFileEntryMock("ab", 3)); - data.push_back(StringsFileEntryMock("ba", 4)); - data.push_back(StringsFileEntryMock("abc", 5)); + vector data = {StringsFileEntryMock("a", 1), StringsFileEntryMock("b", 2), + StringsFileEntryMock("ab", 3), StringsFileEntryMock("ba", 4), + StringsFileEntryMock("abc", 5)}; sort(data.begin(), data.end()); trie::BuildSuccinctTrie::iterator, trie::EmptyEdgeBuilder, @@ -196,13 +190,12 @@ UNIT_TEST(SuccinctTrie_Iterator) MemReader memReader(buf.data(), buf.size()); - using EmptyValueType = trie::EmptyValueReader::ValueType; + using TEmptyValue = trie::EmptyValueReader::ValueType; - unique_ptr> - trieRoot(trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader())); + auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader()); vector collectedValues; - CollectInSubtree(trieRoot.get(), collectedValues); + CollectInSubtree(trieRoot, collectedValues); sort(collectedValues.begin(), collectedValues.end()); TEST_EQUAL(collectedValues.size(), 5, ()); for (size_t i = 0; i < collectedValues.size(); ++i) @@ -216,11 +209,9 @@ UNIT_TEST(SuccinctTrie_MoveToString) using TWriter = MemWriter>; TWriter memWriter(buf); - vector data; - data.push_back(StringsFileEntryMock("abcde", 1)); - data.push_back(StringsFileEntryMock("aaaaa", 2)); - data.push_back(StringsFileEntryMock("aaa", 3)); - data.push_back(StringsFileEntryMock("aaa", 4)); + vector data = { + StringsFileEntryMock("abcde", 1), StringsFileEntryMock("aaaaa", 2), + StringsFileEntryMock("aaa", 3), StringsFileEntryMock("aaa", 4)}; sort(data.begin(), data.end()); trie::BuildSuccinctTrie::iterator, trie::EmptyEdgeBuilder, @@ -228,48 +219,55 @@ UNIT_TEST(SuccinctTrie_MoveToString) trie::EmptyEdgeBuilder()); MemReader memReader(buf.data(), buf.size()); - using EmptyValueType = trie::EmptyValueReader::ValueType; + using TEmptyValue = trie::EmptyValueReader::ValueType; - unique_ptr> - trieRoot(trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader())); + auto trieRoot = trie::ReadSuccinctTrie(memReader, SimpleValueReader(), trie::EmptyValueReader()); { - auto * it = trieRoot->GoToString(strings::MakeUniString("a")); + auto it = trieRoot->GoToString(strings::MakeUniString("a")); TEST(it != nullptr, ()); vector expectedValues; - TEST_EQUAL(ReadAllValues(it), expectedValues, ()); + vector receivedValues; + ReadAllValues(it, receivedValues); + TEST_EQUAL(expectedValues, receivedValues, ()); } { - auto * it = trieRoot->GoToString(strings::MakeUniString("abcde")); + auto it = trieRoot->GoToString(strings::MakeUniString("abcde")); TEST(it != nullptr, ()); vector expectedValues{1}; - TEST_EQUAL(ReadAllValues(it), expectedValues, ()); + vector receivedValues; + ReadAllValues(it, receivedValues); + TEST_EQUAL(expectedValues, receivedValues, ()); } { - auto * it = trieRoot->GoToString(strings::MakeUniString("aaaaa")); + auto it = trieRoot->GoToString(strings::MakeUniString("aaaaa")); TEST(it != nullptr, ()); vector expectedValues{2}; - TEST_EQUAL(ReadAllValues(it), expectedValues, ()); + vector receivedValues; + ReadAllValues(it, receivedValues); + TEST_EQUAL(expectedValues, receivedValues, ()); } { - auto * it = trieRoot->GoToString(strings::MakeUniString("aaa")); + auto it = trieRoot->GoToString(strings::MakeUniString("aaa")); TEST(it != nullptr, ()); vector expectedValues{3, 4}; - TEST_EQUAL(ReadAllValues(it), expectedValues, ()); + vector receivedValues; + ReadAllValues(it, receivedValues); + TEST_EQUAL(expectedValues, receivedValues, ()); } { - auto * it = trieRoot->GoToString(strings::MakeUniString("b")); + auto it = trieRoot->GoToString(strings::MakeUniString("b")); TEST(it == nullptr, ()); } { - auto * it = trieRoot->GoToString(strings::MakeUniString("bbbbb")); + auto it = trieRoot->GoToString(strings::MakeUniString("bbbbb")); TEST(it == nullptr, ()); } } -} // namespace trie \ No newline at end of file +} // namespace trie diff --git a/coding/succinct_trie_builder.hpp b/coding/succinct_trie_builder.hpp index 216de1acc2..8ef97956e4 100644 --- a/coding/succinct_trie_builder.hpp +++ b/coding/succinct_trie_builder.hpp @@ -8,9 +8,19 @@ #include "coding/writer.hpp" #include "base/buffer_vector.hpp" +#include "base/scope_guard.hpp" #include "base/string_utils.hpp" #include "std/algorithm.hpp" +#include "std/bind.hpp" + +// Trie format: +// -- Serialized Huffman encoding. +// -- Topology of the trie built on Huffman-encoded input strings [2 bits per node, level-order representation]. +// -- List of pairs (node id, offset). One pair per final node (i.e. a node where a string ends). +// The lists of node ids and offsets are both non-decreasing and are delta-encoded with varuints. +// -- Values of final nodes in level-order. The values for final node |id| start at offset |offset| +// if there is a pair (id, offset) in the list above. namespace trie { @@ -41,7 +51,7 @@ struct Node }; template -TNode * AddToTrie(TNode * root, TReader bitEncoding, uint32_t numBits) +TNode * AddToTrie(TNode * root, TReader & bitEncoding, uint32_t numBits) { ReaderSource src(bitEncoding); // String size. @@ -51,19 +61,10 @@ TNode * AddToTrie(TNode * root, TReader bitEncoding, uint32_t numBits) auto cur = root; for (uint32_t i = 0; i < numBits; ++i) { - uint8_t bit = bitReader.Read(1); - if (bit == 0) - { - if (!cur->l) - cur->l = new TNode(); - cur = cur->l; - } - else - { - if (!cur->r) - cur->r = new TNode(); - cur = cur->r; - } + auto nxt = bitReader.Read(1) == 0 ? &cur->l : &cur->r; + if (!*nxt) + *nxt = new TNode(); + cur = *nxt; } return cur; } @@ -79,20 +80,19 @@ void DeleteTrie(TNode * root) } template -vector WriteInLevelOrder(TNode * root) +void WriteInLevelOrder(TNode * root, vector & levelOrder) { - vector q; - q.push_back(root); - size_t qt = 0; - while (qt < q.size()) + ASSERT(root, ()); + levelOrder.push_back(root); + size_t i = 0; + while (i < levelOrder.size()) { - TNode * cur = q[qt++]; + TNode * cur = levelOrder[i++]; if (cur->l) - q.push_back(cur->l); + levelOrder.push_back(cur->l); if (cur->r) - q.push_back(cur->r); + levelOrder.push_back(cur->r); } - return q; } template @@ -105,23 +105,25 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, using TEntry = typename TIter::value_type; TNode * root = new TNode(); + MY_SCOPE_GUARD(cleanup, bind(&DeleteTrie, root)); TTrieString prevKey; - TEntry prevE; + TEntry prevEntry; vector entries; vector entryStrings; for (TIter it = beg; it != end; ++it) { - TEntry e = *it; - if (it != beg && e == prevE) + TEntry entry = *it; + if (it != beg && entry == prevEntry) continue; - TrieChar const * const keyData = e.GetKeyData(); - TTrieString key(keyData, keyData + e.GetKeySize()); - CHECK(!(key < prevKey), (key, prevKey)); - entries.push_back(e); - entryStrings.push_back(strings::UniString(keyData, keyData + e.GetKeySize())); + TrieChar const * const keyData = entry.GetKeyData(); + TTrieString key(keyData, keyData + entry.GetKeySize()); + using namespace std::rel_ops; // ">=" for keys. + CHECK_GREATER_OR_EQUAL(key, prevKey, (key, prevKey)); + entries.push_back(entry); + entryStrings.push_back(strings::UniString(keyData, keyData + entry.GetKeySize())); prevKey.swap(key); - prevE.Swap(e); + prevEntry.Swap(entry); } coding::HuffmanCoder huffman; @@ -130,7 +132,7 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, for (size_t i = 0; i < entries.size(); ++i) { - TEntry const & e = entries[i]; + TEntry const & entry = entries[i]; auto const & key = entryStrings[i]; vector buf; @@ -141,27 +143,23 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, TNode * cur = AddToTrie(root, bitEncoding, numBits); cur->m_isFinal = true; - cur->m_valueList.Append(e.GetValue()); - cur->m_edgeBuilder.AddValue(e.value_data(), e.value_size()); + cur->m_valueList.Append(entry.GetValue()); + cur->m_edgeBuilder.AddValue(entry.value_data(), entry.value_size()); } - vector levelOrder = WriteInLevelOrder(root); - - vector trieTopology(2 * levelOrder.size()); - for (size_t i = 0; i < levelOrder.size(); ++i) - { - auto const & cur = levelOrder[i]; - if (cur->l) - trieTopology[2 * i] = true; - if (cur->r) - trieTopology[2 * i + 1] = true; - } + vector levelOrder; + WriteInLevelOrder(root, levelOrder); { + // Trie topology. BitWriter bitWriter(writer); WriteVarUint(writer, levelOrder.size()); - for (size_t i = 0; i < 2 * levelOrder.size(); ++i) - bitWriter.Write(trieTopology[i] ? 1 : 0, 1 /* numBits */); + for (size_t i = 0; i < levelOrder.size(); ++i) + { + auto const & cur = levelOrder[i]; + bitWriter.Write(cur->l ? 1 : 0, 1 /* numBits */); + bitWriter.Write(cur->r ? 1 : 0, 1 /* numBits */); + } } vector finalNodeIds; @@ -170,12 +168,12 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, MemWriter> valueWriter(valueBuf); for (size_t i = 0; i < levelOrder.size(); ++i) { - TNode const * nd = levelOrder[i]; - if (!nd->m_isFinal) + TNode const * node = levelOrder[i]; + if (!node->m_isFinal) continue; finalNodeIds.push_back(static_cast(i)); offsetTable.push_back(valueWriter.Pos()); - nd->m_valueList.Dump(valueWriter); + node->m_valueList.Dump(valueWriter); } WriteVarUint(writer, finalNodeIds.size()); @@ -193,8 +191,7 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, } } - for (uint8_t const b : valueBuf) - writer.Write(&b, 1 /* numBytes */); + writer.Write(valueBuf.data(), valueBuf.size()); // todo(@pimenov): // 1. Investigate the possibility of path compression (short edges + lcp table). @@ -204,8 +201,6 @@ void BuildSuccinctTrie(TWriter & writer, TIter const beg, TIter const end, // Alternatively (and probably better), we can append a special symbol to all those // strings that have non-empty value lists. We can then get the leaf number // of a final node by doing rank0. - - DeleteTrie(root); } } // namespace trie diff --git a/coding/succinct_trie_reader.hpp b/coding/succinct_trie_reader.hpp index 9eef07ec09..8fbf649bc2 100644 --- a/coding/succinct_trie_reader.hpp +++ b/coding/succinct_trie_reader.hpp @@ -1,27 +1,32 @@ #pragma once -#include "coding/reader.hpp" -#include "coding/varint.hpp" -#include "coding/huffman.hpp" #include "coding/bit_streams.hpp" +#include "coding/huffman.hpp" +#include "coding/reader.hpp" #include "coding/trie.hpp" +#include "coding/varint.hpp" #include "base/assert.hpp" #include "base/bits.hpp" #include "base/macros.hpp" #include "base/string_utils.hpp" +#include "std/utility.hpp" #include "std/vector.hpp" #include "3party/succinct/rs_bit_vector.hpp" namespace trie { +// This class is used to read the data that is common to every node +// of the trie: the trie topology and the offsets into the data buffer. +// The topology can then be used to navigate the trie and the offsets +// can be used to extract the values associated with the key strings. template class TopologyAndOffsets { public: - using ValueType = typename TValueReader::ValueType; - using EdgeValueType = typename TEdgeValueReader::ValueType; + using TValue = typename TValueReader::ValueType; + using TEdgeValue = typename TEdgeValueReader::ValueType; TopologyAndOffsets(TReader const & reader, TValueReader const & valueReader, TEdgeValueReader const & edgeValueReader) @@ -30,17 +35,45 @@ public: Parse(); } + // Returns the topology of the trie in the external node representation. + // Arrange the nodes in the level order and write two bits for every + // node: the first bit for its left child and the second bit for its right child. + // Write '1' if the child is present and '0' if it is not. + // Prepend the resulting bit string with '1' (for a super-root) and you will get + // the external node representaiton. succinct::rs_bit_vector const & GetTopology() const { return m_trieTopology; } + + // Returns the number of trie nodes. uint32_t NumNodes() const { return m_numNodes; } + + // Returns the Huffman encoding that was used to encode the strings + // before adding them to this trie. coding::HuffmanCoder const & GetEncoding() const { return m_huffman; } + + // Returns true if and only if the node is the last node of a string + // that was used as a key when building this trie. bool NodeIsFinal(uint32_t id) const { return m_finalNodeIndex[id] >= 0; } - uint32_t Offset(uint32_t id) const { return m_offsetTable[m_finalNodeIndex[id]]; } + + // Returns the offset relative to the beginning of the start of the + // value buffer where the data for node number |id| starts. + uint32_t Offset(uint32_t id) const + { + CHECK(NodeIsFinal(id), ()); + return m_offsetTable[m_finalNodeIndex[id]]; + } + + // Returns the number of values associated with a final node |id|. uint32_t ValueListSize(uint32_t id) { + CHECK(NodeIsFinal(id), ()); int finalId = m_finalNodeIndex[id]; return m_offsetTable[finalId + 1] - m_offsetTable[finalId]; } + + // Returns the reader from which the value buffer can be read. TValueReader const & GetValueReader() const { return m_valueReader; } + + // Returns the reader from which the trie can be read. TReader const & GetReader() const { return m_reader; } private: @@ -98,26 +131,24 @@ template class SuccinctTrieIterator { public: - using ValueType = typename TValueReader::ValueType; - using EdgeValueType = typename TEdgeValueReader::ValueType; + using TValue = typename TValueReader::ValueType; + using TEdgeValue = typename TEdgeValueReader::ValueType; using TCommonData = TopologyAndOffsets; - SuccinctTrieIterator(TReader const & reader, TCommonData * common, uint32_t nodeBitPosition) - : m_reader(reader), m_nodeBitPosition(nodeBitPosition), m_valuesRead(false) + SuccinctTrieIterator(TReader const & reader, shared_ptr common, + uint32_t nodeBitPosition) + : m_reader(reader), m_common(common), m_nodeBitPosition(nodeBitPosition), m_valuesRead(false) { - m_common = shared_ptr(common); } - SuccinctTrieIterator * Clone() const + unique_ptr Clone() const { - auto * ret = new SuccinctTrieIterator( - m_reader, m_common.get(), m_nodeBitPosition); - return ret; + return make_unique(m_reader, m_common, m_nodeBitPosition); } - SuccinctTrieIterator * GoToEdge(size_t i) const + unique_ptr GoToEdge(size_t i) const { - ASSERT(i < 2, ("Bad edge id of a binary trie.")); + ASSERT_LESS(i, 2, ("Bad edge id of a binary trie.")); ASSERT_EQUAL(m_common->GetTopology()[m_nodeBitPosition - 1], 1, (m_nodeBitPosition)); // rank(x) returns the number of ones in [0, x) but we count bit positions from 1 @@ -126,15 +157,14 @@ public: ++childBitPosition; if (childBitPosition > 2 * m_common->NumNodes() || m_common->GetTopology()[childBitPosition - 1] == 0) + { return nullptr; - auto * ret = new SuccinctTrieIterator( - m_reader, m_common.get(), childBitPosition); - return ret; + } + return make_unique(m_reader, m_common, childBitPosition); } template - SuccinctTrieIterator * GoToString( - TEncodingReader bitEncoding, uint32_t numBits) + unique_ptr GoToString(TEncodingReader & bitEncoding, uint32_t numBits) { ReaderSource src(bitEncoding); @@ -144,19 +174,19 @@ public: BitReader> bitReader(src); - auto * ret = Clone(); + auto ret = Clone(); for (uint32_t i = 0; i < numBits; ++i) { uint8_t bit = bitReader.Read(1); - ret = ret->GoToEdge(bit); - if (!ret) + auto nxt = ret->GoToEdge(bit); + if (!nxt) return nullptr; + ret = move(nxt); } return ret; } - SuccinctTrieIterator * GoToString( - strings::UniString const & s) + unique_ptr GoToString(strings::UniString const & s) { vector buf; uint32_t numBits; @@ -175,11 +205,11 @@ public: return m_values.size(); } - ValueType GetValue(size_t i) + TValue GetValue(size_t i) { if (!m_valuesRead) ReadValues(); - ASSERT(i < m_values.size(), ()); + ASSERT_LESS(i, m_values.size(), ()); return m_values[i]; } @@ -199,7 +229,7 @@ private: ReaderSource> src(subReaderPtr); while (src.Size() > 0) { - ValueType val; + TValue val; m_common->GetValueReader()(src, val); m_values.push_back(val); } @@ -212,19 +242,20 @@ private: // in the external node representation of binary trie. uint32_t m_nodeBitPosition; - vector m_values; + vector m_values; bool m_valuesRead; }; template -SuccinctTrieIterator * ReadSuccinctTrie( +unique_ptr> ReadSuccinctTrie( TReader const & reader, TValueReader valueReader = TValueReader(), TEdgeValueReader edgeValueReader = TEdgeValueReader()) { - auto * common = new TopologyAndOffsets( - reader, valueReader, edgeValueReader); - return new SuccinctTrieIterator( - common->GetReader(), common, 1 /* bitPosition */); + using TCommonData = TopologyAndOffsets; + using TIter = SuccinctTrieIterator; + + shared_ptr common(new TCommonData(reader, valueReader, edgeValueReader)); + return make_unique(common->GetReader(), common, 1 /* bitPosition */); } } // namespace trie diff --git a/indexer/search_index_builder.cpp b/indexer/search_index_builder.cpp index 15dadceeaa..81f4d01803 100644 --- a/indexer/search_index_builder.cpp +++ b/indexer/search_index_builder.cpp @@ -19,7 +19,6 @@ #include "platform/platform.hpp" #include "coding/reader_writer_ops.hpp" -#include "coding/succinct_trie_builder.hpp" #include "coding/trie_builder.hpp" #include "coding/writer.hpp" @@ -410,11 +409,6 @@ void BuildSearchIndex(FilesContainerR const & cont, CategoriesHolder const & cat trie::Build::IteratorT, trie::EmptyEdgeBuilder, ValueList>( writer, names.Begin(), names.End(), trie::EmptyEdgeBuilder()); - /* - trie::BuildSuccinctTrie::IteratorT, - trie::EmptyEdgeBuilder, ValueList>( - writer, names.Begin(), names.End(), trie::EmptyEdgeBuilder()); - */ // at this point all readers of StringsFile should be dead }