@@ -18,61 +18,66 @@ class CheckpointsTrie::Implementation {
1818 MetadataMap metadataMap_;
1919 TrieNodes trieNodes_;
2020 Suffixes reverseSuffixes_; // suffixes are written in reverse order to optimize trie nodes extension
21+ std::vector<int > values_; // each suffix corresponds to one value, even if empty
2122
2223 public:
23- void insert (const ChunkedState& state ) {
24- const uint16_t lastChunkSizePhaseIndex = 256 * state .lastChunkSize + state .phase ;
24+ bool insert (const ChunkedState& key, const int value ) {
25+ const uint16_t lastChunkSizePhaseIndex = 256 * key .lastChunkSize + key .phase ;
2526
26- const auto fixedChunkCountIt = metadataMap_.find (state .chunks .size ());
27+ const auto fixedChunkCountIt = metadataMap_.find (key .chunks .size ());
2728 if (fixedChunkCountIt == metadataMap_.end ()) {
28- reverseSuffixes_.push_back (std::vector<uint8_t >(state.chunks .rbegin (), state.chunks .rend ()));
29+ reverseSuffixes_.push_back (std::vector<uint8_t >(key.chunks .rbegin (), key.chunks .rend ()));
30+ values_.push_back (value);
2931 metadataMap_.insert (
30- {state .chunks .size (), {{lastChunkSizePhaseIndex, fromReverseSuffixesIndex (reverseSuffixes_.size () - 1 )}}});
31- return ;
32+ {key .chunks .size (), {{lastChunkSizePhaseIndex, fromReverseSuffixesIndex (reverseSuffixes_.size () - 1 )}}});
33+ return true ;
3234 }
3335
3436 const auto fixedMetadataIt = fixedChunkCountIt->second .find (lastChunkSizePhaseIndex);
3537 if (fixedMetadataIt == fixedChunkCountIt->second .end ()) {
36- reverseSuffixes_.push_back (std::vector<uint8_t >(state.chunks .rbegin (), state.chunks .rend ()));
38+ reverseSuffixes_.push_back (std::vector<uint8_t >(key.chunks .rbegin (), key.chunks .rend ()));
39+ values_.push_back (value);
3740 fixedChunkCountIt->second .insert (
3841 {lastChunkSizePhaseIndex, fromReverseSuffixesIndex (reverseSuffixes_.size () - 1 )});
39- return ;
42+ return true ;
4043 }
4144
42- insertChunks (&fixedMetadataIt->second , state .chunks .begin (), state .chunks .end ());
45+ return insertChunks (&fixedMetadataIt->second , key .chunks .begin (), key .chunks .end (), value );
4346 }
4447
45- bool contains (const ChunkedState& state) const {
48+ std::optional< int > findValue (const ChunkedState& state) const {
4649 const auto fixedChunkCountIt = metadataMap_.find (state.chunks .size ());
47- if (fixedChunkCountIt == metadataMap_.end ()) return false ;
50+ if (fixedChunkCountIt == metadataMap_.end ()) return std:: nullopt ;
4851 const auto fixedMetadataIt = fixedChunkCountIt->second .find (256 * state.lastChunkSize + state.phase );
49- if (fixedMetadataIt == fixedChunkCountIt->second .end ()) return false ;
50- return containsChunks (fixedMetadataIt->second , state.chunks .begin (), state.chunks .end ());
52+ if (fixedMetadataIt == fixedChunkCountIt->second .end ()) return std:: nullopt ;
53+ return findValueInChunks (fixedMetadataIt->second , state.chunks .begin (), state.chunks .end ());
5154 }
5255
5356 private:
5457 using ChunksIterator = std::deque<uint8_t >::const_iterator;
55- void insertChunks (int64_t * index, ChunksIterator chunksBegin, ChunksIterator chunksEnd) {
56- if (chunksBegin == chunksEnd) return ;
58+ bool insertChunks (int64_t * index, ChunksIterator chunksBegin, ChunksIterator chunksEnd, const int value ) {
59+ if (chunksBegin == chunksEnd) return false ; // it's a total match, don't insert a value
5760
5861 if (*index >= 0 ) {
59- const auto nextChunkIt = trieNodes_[ *index] .find (*chunksBegin);
60- if (nextChunkIt == trieNodes_[ *index] .end ()) {
62+ const auto nextChunkIt = trieNodes_. at ( *index) .find (*chunksBegin);
63+ if (nextChunkIt == trieNodes_. at ( *index) .end ()) {
6164 reverseSuffixes_.push_back (std::vector<uint8_t >(std::reverse_iterator<ChunksIterator>(chunksEnd),
6265 std::reverse_iterator<ChunksIterator>(chunksBegin) - 1 ));
63- trieNodes_[*index].insert ({*chunksBegin, fromReverseSuffixesIndex (reverseSuffixes_.size () - 1 )});
66+ values_.push_back (value);
67+ trieNodes_.at (*index).insert ({*chunksBegin, fromReverseSuffixesIndex (reverseSuffixes_.size () - 1 )});
6468 } else {
65- insertChunks (&nextChunkIt->second , chunksBegin + 1 , chunksEnd);
69+ insertChunks (&nextChunkIt->second , chunksBegin + 1 , chunksEnd, value );
6670 }
6771 } else {
6872 *index = pushChunk (*index);
69- insertChunks (index, chunksBegin, chunksEnd);
73+ insertChunks (index, chunksBegin, chunksEnd, value );
7074 }
75+ return true ;
7176 }
7277
7378 int64_t pushChunk (int64_t negativeIndex) {
74- const auto firstValue = reverseSuffixes_[ toReverseSuffixesIndex (negativeIndex)] .back ();
75- reverseSuffixes_[ toReverseSuffixesIndex (negativeIndex)] .pop_back ();
79+ const auto firstValue = reverseSuffixes_. at ( toReverseSuffixesIndex (negativeIndex)) .back ();
80+ reverseSuffixes_. at ( toReverseSuffixesIndex (negativeIndex)) .pop_back ();
7681 trieNodes_.push_back ({{firstValue, negativeIndex}});
7782 return trieNodes_.size () - 1 ;
7883 }
@@ -81,30 +86,38 @@ class CheckpointsTrie::Implementation {
8186
8287 static inline int64_t fromReverseSuffixesIndex (int64_t positiveIndex) { return -(positiveIndex + 1 ); }
8388
84- bool containsChunks (int64_t index, ChunksIterator chunksBegin, ChunksIterator chunksEnd) const {
85- if (chunksBegin == chunksEnd) return true ;
89+ std::optional<int > findValueInChunks (int64_t index, ChunksIterator chunksBegin, ChunksIterator chunksEnd) const {
90+ if (chunksBegin == chunksEnd) {
91+ return values_.at (toReverseSuffixesIndex (index));
92+ }
8693
8794 if (index >= 0 ) {
88- const auto nextChunkIt = trieNodes_[ index] .find (*chunksBegin);
89- if (nextChunkIt == trieNodes_[ index] .end ()) {
90- return false ;
95+ const auto nextChunkIt = trieNodes_. at ( index) .find (*chunksBegin);
96+ if (nextChunkIt == trieNodes_. at ( index) .end ()) {
97+ return std:: nullopt ;
9198 } else {
92- return containsChunks (nextChunkIt->second , chunksBegin + 1 , chunksEnd);
99+ return findValueInChunks (nextChunkIt->second , chunksBegin + 1 , chunksEnd);
93100 }
94101 } else {
95102 const auto firstMismatch = std::mismatch (chunksBegin,
96103 chunksEnd,
97- reverseSuffixes_[toReverseSuffixesIndex (index)].rbegin (),
98- reverseSuffixes_[toReverseSuffixesIndex (index)].rend ());
99- return firstMismatch.first == chunksEnd;
104+ reverseSuffixes_.at (toReverseSuffixesIndex (index)).rbegin (),
105+ reverseSuffixes_.at (toReverseSuffixesIndex (index)).rend ());
106+ if (firstMismatch.first == chunksEnd) {
107+ return values_.at (fromReverseSuffixesIndex (index));
108+ } else {
109+ return std::nullopt ;
110+ }
100111 }
101112 }
102113};
103114
104115CheckpointsTrie::CheckpointsTrie () { implementation_ = std::make_shared<Implementation>(); }
105116
106- void CheckpointsTrie::insert (const ChunkedState& state ) { implementation_->insert (state ); }
117+ bool CheckpointsTrie::insert (const ChunkedState& key, const int value ) { return implementation_->insert (key, value ); }
107118
108- bool CheckpointsTrie::contains (const ChunkedState& state) const { return implementation_->contains (state); }
119+ std::optional<int > CheckpointsTrie::findValue (const ChunkedState& state) const {
120+ return implementation_->findValue (state);
121+ }
109122
110123} // namespace PostTagSystem
0 commit comments