Add Anton Fedoruk's B+ Tree implementation, intended to be used for for audio display caching among other things.

Originally committed to SVN as r3410.
This commit is contained in:
Niels Martin Hansen 2009-08-15 04:20:25 +00:00
parent 3b1a722e5c
commit 60e2cf3790
7 changed files with 1909 additions and 0 deletions

162
aegisub/src/btree/BTree.h Normal file
View file

@ -0,0 +1,162 @@
//////////////////////////////////////////////////////////////////
///
/// (C) 2007: ScalingWeb.com
///
/// Author: Anton Fedoruk <afedoruk@scalingweb.com>
///
//////////////////////////////////////////////////////////////////
#ifndef __BTree_h__
#define __BTree_h__
#include "BTreeElement.h"
#include <memory>
///
/// BTree auxiliary structures
///
// BTree pair element container
template< typename KeyT, typename DataT >
struct BTreePair
{
BTreePair() {}
BTreePair( const KeyT &setkey, const DataT &setdata )
: key( setkey ),
data( setdata )
{}
BTreePair( const BTreeElement< KeyT, DataT > &elem )
: key( elem.key_ ),
data( elem.data_ )
{}
KeyT key;
DataT data;
};
// BTree key element container
template< typename KeyT, typename DataT >
struct BTreeKey
{
BTreeKey() {}
BTreeKey( const KeyT &setkey )
: key( setkey )
{}
BTreeKey( const KeyT &setkey, const DataT & )
: key( setkey )
{}
BTreeKey( const BTreeElement< KeyT, DataT > &elem )
: key( elem.key_ )
{}
KeyT key;
};
// BTree data element container
template< typename KeyT, typename DataT >
struct BTreeData
{
BTreeData( const DataT &setdata )
: data( setdata )
{}
BTreeData( const KeyT &, const DataT &dat )
: data( dat )
{}
BTreeData( const BTreeElement< KeyT, DataT > &elem )
: data( elem.data_ )
{}
DataT data;
};
///
/// BTree iterators support. TSuper class must implement
/// push_back( ElemType &elem ) method.
///
template
<
typename KeyT,
typename DataT,
class TSuper,
template < typename, typename > class TElement
>
class BTreeIterator : public TSuper
{
public:
///
/// Type of container element
typedef TElement< KeyT, DataT > ElemType;
};
///
/// Template container for BTree search results
///
template
<
typename KeyT,
typename DataT,
template < typename > class TSuper,
template < typename, typename > class TElement
>
class BTreeContainer : public TSuper< TElement< KeyT, DataT > >
{
public:
///
/// Type of container element
typedef TElement< KeyT, DataT > ElemType;
};
///
/// Template container for BTree search results using 2-arg templates
///
template
<
typename KeyT,
typename DataT,
template < typename, typename > class TSuper,
template < typename, typename > class TElement,
template < typename > class TSuperAllocator = std::allocator
>
class BTreeContainerStd : public TSuper< TElement< KeyT, DataT >,
TSuperAllocator< TElement< KeyT, DataT > > >
{
public:
///
/// Type of container element
typedef TElement< KeyT, DataT > ElemType;
};
///
/// Represents BTree condition for search
///
template< class TChecker >
class BTreeCondition : public TChecker
{
public:
///
/// This method returns true if passed param is valid and
/// node search have to keep going.
/// TChecker must implement: bool satisfy( const KeyT & ) method
using TChecker::satisfy;
};
#include "BTreeAlgorithms.h"
#endif // __BTree_h__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////
///
/// (C) 2007: ScalingWeb.com
///
/// Author: Anton Fedoruk <afedoruk@scalingweb.com>
///
//////////////////////////////////////////////////////////////////
#ifndef __BTreeElement_h__
#define __BTreeElement_h__
///
/// Class BTreeElement
///
template< typename KeyT, typename DataT >
class BTreeElement
{
public:
BTreeElement();
BTreeElement( const KeyT &key, const DataT &data );
BTreeElement( const KeyT &key, const DataT &data, int link );
BTreeElement( const BTreeElement< KeyT, DataT > &copy );
~BTreeElement();
// Data
KeyT key_;
DataT data_;
int link_;
};
// ===================================================================
// BTreeElement< KeyT, DataT >::BTreeElement
template< typename KeyT, typename DataT >
BTreeElement< KeyT, DataT >::BTreeElement() :
link_( 0 )
{}
// ===================================================================
// BTreeElement< KeyT, DataT >::BTreeElement
template< typename KeyT, typename DataT >
BTreeElement< KeyT, DataT >::BTreeElement( const KeyT &key, const DataT &data ) :
key_( key ),
data_( data ),
link_( 0 )
{}
// ===================================================================
// BTreeElement< KeyT, DataT >::BTreeElement
template< typename KeyT, typename DataT >
BTreeElement< KeyT, DataT >::BTreeElement( const KeyT &key, const DataT &data, int link )
: key_( key ),
data_( data ),
link_( link )
{}
// ===================================================================
// BTreeElement< KeyT, DataT >::BTreeElement
template< typename KeyT, typename DataT >
BTreeElement< KeyT, DataT >::BTreeElement(
const BTreeElement< KeyT, DataT > &copy )
: key_( copy.key_ ),
data_( copy.data_ ),
link_( copy.link_ )
{}
// ===================================================================
// BTreeElement< KeyT, DataT >::~BTreeElement
template< typename KeyT, typename DataT >
BTreeElement< KeyT, DataT >::~BTreeElement()
{}
#endif // __BTreeElement_h__

View file

@ -0,0 +1,253 @@
//////////////////////////////////////////////////////////////////
///
/// (C) 2007: ScalingWeb.com
///
/// Author: Anton Fedoruk <afedoruk@scalingweb.com>
///
//////////////////////////////////////////////////////////////////
#ifndef __BTreeNode_h__
#define __BTreeNode_h__
#include "BTreeElement.h"
///
/// Represents one BTree node in a storage
///
#pragma pack( 1 )
template< int NodeSize, typename KeyT, typename DataT >
class BTreeNode
{
public:
enum Flags
{
NodeChanged = 1
};
typedef BTreeElement< KeyT, DataT > ElemType;
BTreeNode();
~BTreeNode();
inline int add( const KeyT &key, const DataT &data );
int add( const ElemType &elem );
void removeAt( int index );
void removeAt( int index, ElemType &removed );
void clear();
bool find( const KeyT &key, int &index ) const;
bool hasChilds() const;
bool isEmpty() const;
bool isFull() const;
int count() const;
enum { maxKeys = NodeSize };
// Data
int addr_;
int less_;
ElemType elems_[ NodeSize ];
int size_;
int parent_;
uint8_t flags_;
};
#pragma pack()
#include "string.h"
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::BTreeNode
template< int NodeSize, typename KeyT, typename DataT >
BTreeNode< NodeSize, KeyT, DataT >::BTreeNode()
: addr_( 0 ),
less_( 0 ),
size_( 0 ),
parent_( 0 ),
flags_( 0 )
{
// Clear RAM garbage
::memset( &elems_, 0, sizeof( ElemType )*NodeSize );
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::~BTreeNode
template< int NodeSize, typename KeyT, typename DataT >
BTreeNode< NodeSize, KeyT, DataT >::~BTreeNode()
{}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::add
template< int NodeSize, typename KeyT, typename DataT >
inline int BTreeNode< NodeSize, KeyT, DataT >::add( const KeyT &key, const DataT &data )
{
bool added = false;
int i = 0;
for ( i = 0; i < size_; i++ )
{
if ( elems_[ i ].key_ > key )
{
// Move all greater elems
::memmove( elems_ + i + 1, elems_ + i,
( size_ - i )*sizeof( ElemType ) );
// Assign new value
elems_[ i ].key_ = key;
elems_[ i ].data_ = data;
elems_[ i ].link_ = 0;
added = true;
break;
}
}
if ( !added )
{
elems_[ size_ ].key_ = key;
elems_[ size_ ].data_ = data;
i = size_;
}
size_++;
flags_ = NodeChanged;
return i;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::add
template< int NodeSize, typename KeyT, typename DataT >
int BTreeNode< NodeSize, KeyT, DataT >::add( const typename ElemType &elem )
{
int index = add( elem.key_, elem.data_ );
elems_[ index ].link_ = elem.link_;
return index;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::removeAt
template< int NodeSize, typename KeyT, typename DataT >
void BTreeNode< NodeSize, KeyT, DataT >::removeAt( int index )
{
elems_[ index ] = ElemType();
::memmove( elems_ + index, elems_ + index + 1,
( size_ - index - 1 )*sizeof( ElemType ) );
size_--;
flags_ = NodeChanged;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::removeAt
template< int NodeSize, typename KeyT, typename DataT >
void BTreeNode< NodeSize, KeyT, DataT >::removeAt( int index,
typename ElemType &removed )
{
removed = elems_[ index ];
elems_[ index ] = ElemType();
::memmove( elems_ + index, elems_ + index + 1,
( size_ - index - 1 )*sizeof( ElemType ) );
size_--;
flags_ = NodeChanged;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::clear
template< int NodeSize, typename KeyT, typename DataT >
void BTreeNode< NodeSize, KeyT, DataT >::clear()
{
for ( int i = 0; i < size_; i++ )
{
elems_[ i ] = ElemType();
}
size_ = 0;
flags_ = 0;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::find
template< int NodeSize, typename KeyT, typename DataT >
bool BTreeNode< NodeSize, KeyT, DataT >::find( const KeyT &key, int &index ) const
{
int lb = 0, ub = size_ - 1;
while( lb <= ub )
{
index = ( lb + ub ) >> 1;
if( key < elems_[ index ].key_ )
{
ub = index - 1;
}
else
{
if( key > elems_[ index ].key_ )
{
lb = index + 1;
}
else
{
return true;
}
}
}
index = lb;
return false;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::hasChilds
template< int NodeSize, typename KeyT, typename DataT >
bool BTreeNode< NodeSize, KeyT, DataT >::hasChilds() const
{
return less_ != 0;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::isEmpty
template< int NodeSize, typename KeyT, typename DataT >
bool BTreeNode< NodeSize, KeyT, DataT >::isEmpty() const
{
return size_ == 0;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::isFull
template< int NodeSize, typename KeyT, typename DataT >
bool BTreeNode< NodeSize, KeyT, DataT >::isFull() const
{
return size_ == maxKeys;
}
// ===================================================================
// BTreeNode< NodeSize, KeyT, DataT >::count
template< int NodeSize, typename KeyT, typename DataT >
int BTreeNode< NodeSize, KeyT, DataT >::count() const
{
return size_;
}
#endif // __BTreeNode_h__

45
aegisub/src/btree/README Normal file
View file

@ -0,0 +1,45 @@
Template Based B+ Tree Implementation
=====================================
Description
-----------
B+ Tree is a type of tree, which represents sorted data in a way that allows for efficient insertion,
retrieval and removal of records, each of which is identified by a key.
It is a dynamic, multilevel index, with maximum and minimum bounds on the number of keys in each index
segment (usually called a 'block' or 'node'). In a B+ tree, in contrast to a B-tree,
all records are stored at the lowest level of the tree; only keys are stored in interior blocks.
more info: http://en.wikipedia.org/wiki/B+_tree
Installation
------------
For installation or compiling instructions, see the INSTALL file.
License
-------
This program is licensed under permissive BSD license.
See the license files for more information.
Date: October 16th, 2007
Project Maintainers:
Yuriy Soroka
ysoroka@scalingweb.com
Anton Fedoruk
afedoruk@scalingweb.com
http://www.scalingweb.com/
How you can help
----------------
Comments, patches, bug reports are welcome.

View file

@ -0,0 +1,235 @@
//////////////////////////////////////////////////////////////////
///
/// (C) 2007: ScalingWeb.com
///
/// Author: Anton Fedoruk <afedoruk@scalingweb.com>
///
//////////////////////////////////////////////////////////////////
#ifndef __RamBTreeController_h__
#define __RamBTreeController_h__
#include "BTreeNode.h"
///
/// BTreeController with RAM as storage implementation
///
template< int NodeSize, typename KeyT, typename DataT >
class RamBTreeController
{
public:
typedef BTreeNode< NodeSize, KeyT, DataT > NodeType;
RamBTreeController();
virtual ~RamBTreeController();
bool isOpen();
inline void flushChanges();
inline void releaseCache();
inline void setMaxCacheSize( unsigned int cacheSize );
inline unsigned int getMaxCacheSize();
inline void releaseNode( int addr );
inline bool nodeInCache( int addr );
void assign( RamBTreeController *copy );
void clear();
protected:
// Storage related operations
inline NodeType* newNode();
inline void deleteNode( NodeType *node );
inline bool loadNode( NodeType **node, int addr );
inline int rootAddr();
inline void rootAddr( int addr );
void rclear( NodeType *node );
void closeController();
// Data
NodeType *root_;
};
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::RamBTreeController
template< int NodeSize, typename KeyT, typename DataT >
RamBTreeController< NodeSize, KeyT, DataT >::RamBTreeController() :
root_( 0 )
{}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::RamBTreeController
template< int NodeSize, typename KeyT, typename DataT >
RamBTreeController< NodeSize, KeyT, DataT >::~RamBTreeController()
{
clear();
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::isOpen
template< int NodeSize, typename KeyT, typename DataT >
bool RamBTreeController< NodeSize, KeyT, DataT >::isOpen()
{
return true;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::newNode
template< int NodeSize, typename KeyT, typename DataT >
typename RamBTreeController< NodeSize, KeyT, DataT >::NodeType*
RamBTreeController< NodeSize, KeyT, DataT >::newNode()
{
NodeType *newnode = new NodeType();
newnode->addr_ = ( int ) newnode;
return newnode;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::deleteNode
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::deleteNode( NodeType* node )
{
delete node;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::loadNode
template< int NodeSize, typename KeyT, typename DataT >
bool RamBTreeController< NodeSize, KeyT, DataT >::loadNode( NodeType **node, int addr )
{
if ( !addr )
{
*node = 0;
return true;
}
*node = ( NodeType* ) addr;
return true;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::releaseCache
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::flushChanges()
{}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::releaseCache
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::releaseCache()
{}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::rootAddr
template< int NodeSize, typename KeyT, typename DataT >
int RamBTreeController< NodeSize, KeyT, DataT >::rootAddr()
{
return ( int ) root_;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::closeController
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::closeController()
{}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::rootAddr
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::rootAddr( int addr )
{
root_ = ( NodeType* ) addr;
}
template< int NodeSize, typename KeyT, typename DataT >
inline void RamBTreeController< NodeSize, KeyT, DataT >::setMaxCacheSize( unsigned int )
{}
template< int NodeSize, typename KeyT, typename DataT >
inline unsigned int RamBTreeController< NodeSize, KeyT, DataT >::getMaxCacheSize()
{}
template< int NodeSize, typename KeyT, typename DataT >
inline void RamBTreeController< NodeSize, KeyT, DataT >::releaseNode( int )
{}
template< int NodeSize, typename KeyT, typename DataT >
inline bool RamBTreeController< NodeSize, KeyT, DataT >::nodeInCache( int )
{
return true;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::assign
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::assign( RamBTreeController *rhv )
{
root_ = rhv->root_;
rhv->root_ = 0;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::clear
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::clear()
{
rclear( root_ );
root_ = 0;
}
// ===================================================================
// RamBTreeController< NodeSize, KeyT, DataT >::rclear
template< int NodeSize, typename KeyT, typename DataT >
void RamBTreeController< NodeSize, KeyT, DataT >::rclear( NodeType *node )
{
if ( !node ) return;
if ( node->less_ )
{
NodeType *less = 0;
if ( loadNode( &less, node->less_ ) )
{
rclear( less );
}
}
for ( int i = 0; i < node->count(); i++ )
{
if ( node->elems_[ i ].link_ )
{
NodeType *kid = 0;
if ( loadNode( &kid, node->elems_[ i ].link_ ) )
{
rclear( kid );
}
}
}
delete node;
}
#endif // __RamBTreeController_h__

View file

@ -0,0 +1,31 @@
Software License Agreement (BSD License)
Copyright (c) 2006, ScalingWeb.com
All rights reserved.
Redistribution and use of this software in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of ScalingWeb.com nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of ScalingWeb.com.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.