PST File Format SDK v0.4
Loading...
Searching...
No Matches
btree.h
Go to the documentation of this file.
1
12
15
16#ifndef PSTSDK_UTIL_BTREE_H
17#define PSTSDK_UTIL_BTREE_H
18
19#include <iterator>
20#include <vector>
21#include <boost/iterator/iterator_facade.hpp>
22
24#include "pstsdk/util/errors.h"
25
26#ifdef _MSC_VER
27#pragma warning(push)
28#pragma warning(disable:4250)
29#endif
30
31namespace pstsdk
32{
33
34template<typename K, typename V>
35struct btree_iter_impl;
36
37template<typename K, typename V>
38class const_btree_node_iter;
39
40template<typename K, typename V>
41class btree_node_nonleaf;
42
50template<typename K, typename V>
52{
53public:
55
56 virtual ~btree_node() { }
57
64 virtual const V& lookup(const K& key) const = 0;
65
71 virtual const K& get_key(uint pos) const = 0;
72
77 virtual uint num_values() const = 0;
78
86 { return const_iterator(this, false); }
87
94 { return const_iterator(this, true); }
95
99 int binary_search(const K& key) const;
100
101protected:
102
103 // iter support
104 friend class const_btree_node_iter<K,V>;
105 friend class btree_node_nonleaf<K,V>;
108 virtual void first(btree_iter_impl<K,V>& iter) const = 0;
111 virtual void last(btree_iter_impl<K,V>& iter) const = 0;
114 virtual void next(btree_iter_impl<K,V>& iter) const = 0;
117 virtual void prev(btree_iter_impl<K,V>& iter) const = 0;
118};
119
130template<typename K, typename V>
131class btree_node_leaf : public virtual btree_node<K,V>
132{
133public:
134 virtual ~btree_node_leaf() { }
135
140 const V& lookup(const K& key) const;
141
145 virtual const V& get_value(uint pos) const = 0;
146
147protected:
148
149 // iter support
150 friend class const_btree_node_iter<K,V>;
152 { iter.m_leaf = const_cast<btree_node_leaf<K,V>* >(this); iter.m_leaf_pos = 0; }
154 { iter.m_leaf = const_cast<btree_node_leaf<K,V>* >(this); iter.m_leaf_pos = this->num_values()-1; }
157};
158
170template<typename K, typename V>
171class btree_node_nonleaf : public virtual btree_node<K,V>
172{
173public:
175
177 const V& lookup(const K& key) const;
178
179protected:
187 virtual const btree_node<K,V>* get_child(uint i) const = 0;
188
189 // iter support
190 friend class const_btree_node_iter<K,V>;
191 friend class btree_node_leaf<K,V>;
196};
197
207template<typename K, typename V>
209{
212
213 std::vector<std::pair<btree_node_nonleaf<K,V>*, uint> > m_path;
214 typedef typename std::vector<std::pair<btree_node_nonleaf<K,V>*, uint> >::iterator path_iter;
215};
216
227template<typename K, typename V>
228class const_btree_node_iter : public boost::iterator_facade<const_btree_node_iter<K,V>, const V, boost::bidirectional_traversal_tag>
229{
230public:
233
237 const_btree_node_iter(const btree_node<K,V>* root, bool last);
238
239private:
241
243 void increment() { m_impl.m_leaf->next(m_impl); }
244
247 bool equal(const const_btree_node_iter& other) const
248 { return ((m_impl.m_leaf == other.m_impl.m_leaf) && (m_impl.m_leaf_pos == other.m_impl.m_leaf_pos)); }
249
252 const V& dereference() const
253 { return m_impl.m_leaf->get_value(m_impl.m_leaf_pos); }
254
256 void decrement() { m_impl.m_leaf->prev(m_impl); }
257
258 mutable btree_iter_impl<K,V> m_impl;
259};
260
261} // end namespace
262
263template<typename K, typename V>
265{
266 uint end = num_values();
267 uint start = 0;
268 uint mid = (start + end) / 2;
269
270 while(mid < end)
271 {
272 if(get_key(mid) < k)
273 {
274 start = mid + 1;
275 }
276 else if(get_key(mid) == k)
277 {
278 return mid;
279 }
280 else
281 {
282 end = mid;
283 }
284
285 mid = (start + end) / 2;
286 }
287
288 return mid - 1;
289}
290
291template<typename K, typename V>
293{
294 int location = this->binary_search(k);
295
296 if(location == -1)
297 throw key_not_found<K>(k);
298
299 if(this->get_key(location) != k)
300 throw key_not_found<K>(k);
301
302 return get_value(location);
303}
304
305template<typename K, typename V>
307{
308 if(++iter.m_leaf_pos == this->num_values())
309 {
310 if(iter.m_path.size() > 0)
311 {
312 for(typename btree_iter_impl<K,V>::path_iter piter = iter.m_path.begin();
313 piter != iter.m_path.end();
314 ++piter)
315 {
316 if((*piter).second + 1 < (*piter).first->num_values())
317 {
318 // we're done with this leaf
319 iter.m_leaf = NULL;
320
321 iter.m_path.back().first->next(iter);
322 break;
323 }
324 }
325 }
326 }
327}
328
329template<typename K, typename V>
331{
332 if(iter.m_leaf_pos == 0)
333 {
334 if(iter.m_path.size() > 0)
335 {
336 for(typename btree_iter_impl<K,V>::path_iter piter = iter.m_path.begin();
337 piter != iter.m_path.end();
338 ++piter)
339 {
340 // we're done with this leaf
341 iter.m_leaf = NULL;
342
343 if((*piter).second != 0 && (*piter).first->num_values() > 1)
344 {
345 iter.m_path.back().first->prev(iter);
346 break;
347 }
348 }
349 }
350 }
351 else
352 {
353 --iter.m_leaf_pos;
354 }
355}
356
357template<typename K, typename V>
359{
360 int location = this->binary_search(k);
361
362 if(location == -1)
363 throw key_not_found<K>(k);
364
365 return get_child(location)->lookup(k);
366}
367
368template<typename K, typename V>
370{
371 iter.m_path.push_back(std::make_pair(const_cast<btree_node_nonleaf<K,V>*>(this), 0));
372 get_child(0)->first(iter);
373}
374
375template<typename K, typename V>
377{
378 iter.m_path.push_back(std::make_pair(const_cast<btree_node_nonleaf<K,V>*>(this), this->num_values()-1));
379 get_child(this->num_values()-1)->last(iter);
380}
381
382template<typename K, typename V>
384{
385 std::pair<btree_node_nonleaf<K,V>*, uint>& me = iter.m_path.back();
386
387 if(++me.second == this->num_values())
388 {
389 // we're done, pop us off the path and call up
390 if(iter.m_path.size() > 1)
391 {
392 iter.m_path.pop_back();
393 iter.m_path.back().first->next(iter);
394 }
395 }
396 else
397 {
398 // call into the next leaf
399 get_child(me.second)->first(iter);
400 }
401}
402
403template<typename K, typename V>
405{
406 std::pair<btree_node_nonleaf<K,V>*, uint>& me = iter.m_path.back();
407
408 if(me.second == 0)
409 {
410 // we're done, pop us off the path and call up
411 if(iter.m_path.size() > 1)
412 {
413 iter.m_path.pop_back();
414 iter.m_path.back().first->prev(iter);
415 }
416 }
417 else
418 {
419 // call into the next child
420 get_child(--me.second)->last(iter);
421 }
422}
423
424template<typename K, typename V>
426{
427 m_impl.m_leaf_pos = 0;
428 m_impl.m_leaf = NULL;
429}
430
431template<typename K, typename V>
433{
434 if(last)
435 {
436 root->last(m_impl);
437 ++m_impl.m_leaf_pos;
438 }
439 else
440 {
441 root->first(m_impl);
442 }
443}
444
445#ifdef _MSC_VER
446#pragma warning(pop)
447#endif
448
449#endif
Contains references to other bth_node allocations.
Definition heap.h:364
const K & get_key(uint pos) const
Returns the key at the specified position.
Definition heap.h:379
uint num_values() const
Returns the number of entries in this btree_node.
Definition heap.h:382
Represents a leaf node in a BTree structure.
Definition btree.h:132
virtual const V & get_value(uint pos) const =0
Returns the value at the associated position on this leaf node.
void first(btree_iter_impl< K, V > &iter) const
Positions the iterator at the first element on this tree.
Definition btree.h:151
void last(btree_iter_impl< K, V > &iter) const
Positions the iterator at the "end" element.
Definition btree.h:153
void next(btree_iter_impl< K, V > &iter) const
Moves the iterator to the next element.
Definition btree.h:306
virtual ~btree_node_leaf()
Definition btree.h:134
void prev(btree_iter_impl< K, V > &iter) const
Moves the iterator to the previous element.
Definition btree.h:330
const V & lookup(const K &key) const
Looks up the associated value for a given key.
Definition btree.h:292
Represents a non-leaf node in a BTree structure.
Definition btree.h:172
virtual btree_node< K, V > * get_child(uint i)=0
Returns the child btree_node at the requested location.
const V & lookup(const K &key) const
Looks up the associated value for a given key.
Definition btree.h:358
virtual ~btree_node_nonleaf()
Definition btree.h:174
void next(btree_iter_impl< K, V > &iter) const
Moves the iterator to the next element.
Definition btree.h:383
void prev(btree_iter_impl< K, V > &iter) const
Moves the iterator to the previous element.
Definition btree.h:404
void first(btree_iter_impl< K, V > &iter) const
Positions the iterator at the first element on this tree.
Definition btree.h:369
void last(btree_iter_impl< K, V > &iter) const
Positions the iterator at the "end" element.
Definition btree.h:376
A BTree Node.
Definition btree.h:52
virtual void next(btree_iter_impl< K, V > &iter) const =0
Moves the iterator to the next element.
virtual void last(btree_iter_impl< K, V > &iter) const =0
Positions the iterator at the "end" element.
virtual uint num_values() const =0
Returns the number of entries in this btree_node.
const_iterator end() const
Returns a STL style iterator positioned at the "end" entry.
Definition btree.h:93
const_btree_node_iter< K, V > const_iterator
Definition btree.h:54
virtual void first(btree_iter_impl< K, V > &iter) const =0
Positions the iterator at the first element on this tree.
const_iterator begin() const
Returns a STL style iterator positioned at the first entry.
Definition btree.h:85
virtual ~btree_node()
Definition btree.h:56
virtual void prev(btree_iter_impl< K, V > &iter) const =0
Moves the iterator to the previous element.
virtual const K & get_key(uint pos) const =0
Returns the key at the specified position.
virtual const V & lookup(const K &key) const =0
Looks up the associated value for a given key.
int binary_search(const K &key) const
Performs a binary search over the keys of this btree_node.
Definition btree.h:264
The actual iterator type used by the btree_node class hierarchy.
Definition btree.h:229
friend class boost::iterator_core_access
Definition btree.h:240
const_btree_node_iter()
Default constructor.
Definition btree.h:425
The exceptions used by pstsdk.
boost::uint32_t uint
Definition primitives.h:67
Contains the definition of all in memory representations of disk structures.
Definition disk.h:19
Primitive structures defined by MS-PST and MAPI.
BTree iterator helper class.
Definition btree.h:209
btree_node_leaf< K, V > * m_leaf
The current leaf btree node this iterator is pointing to.
Definition btree.h:210
uint m_leaf_pos
The current position on that leaf.
Definition btree.h:211
std::vector< std::pair< btree_node_nonleaf< K, V > *, uint > > m_path
The "path" to this leaf, starting at the root of the btree.
Definition btree.h:213
std::vector< std::pair< btree_node_nonleaf< K, V > *, uint > >::iterator path_iter
Definition btree.h:214