You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/indexlib/leafdata.cpp

167 lines
5.3 KiB

/* This file is part of indexlib.
* Copyright (C) 2005 Luís Pedro Coelho <luis@luispedro.org>
*
* Indexlib is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation and available as file
* GPL_V2 which is distributed along with indexlib.
*
* Indexlib is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of this program with any edition of
* the TQt library by Trolltech AS, Norway (or with modified versions
* of TQt that use the same license as TQt), and distribute linked
* combinations including the two. You must obey the GNU General
* Public License in all respects for all of the code used other than
* TQt. If you modify this file, you may extend this exception to
* your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from
* your version.
*/
#include "leafdata.h"
#include "logfile.h"
#include <iostream>
#include <algorithm>
#include "boost-compat/next_prior.h"
#include "format.h"
namespace {
memory_manager* manager = 0;
}
memory_manager* get_leafdata_manager() { return manager ; }
void set_leafdata_manager( memory_manager* m ) { manager = m; }
uint32_t leaf_data::get_reference( unsigned idx ) const {
leafdata_iterator iter = begin();
while ( idx-- ) { *iter; ++iter; }
return *iter;
}
bool leaf_data::can_add( uint32_t ref ) const {
if ( ( capacity() - usedbytes() ) > ( 1 + byte_io::byte_length<uint32_t>() ) ) return true;
if ( capacity() == usedbytes() ) return false;
uint32_t last = 0;
for ( iterator first = begin(), past = end(); first != past; ++first ) {
assert( first < past );
last = *first;
if ( last == ref ) return true;
}
return ( ref > last && ( ref - last ) < 256 );
}
bool leaf_data::has_reference( uint32_t ref ) const {
for ( iterator first = begin(), past = end(); first != past; ++first ) {
uint32_t here = *first;
//logfile() << format( "leaf_data[%s]::has_reference( %s ): looking at %s\n" ) % idx_ % ref % here;
if ( here == ref ) {
//logfile() << format( "leaf_data[%s]::has_reference( %s ): true\n" ) % idx_ % ref;
return true;
}
}
//logfile() << format( "leaf_data[%s]::has_reference( %s ): false\n" ) % idx_ % ref;
return false;
}
void leaf_data::add_reference( uint32_t ref ) {
//logfile() << format( "leaf_data[%s]::add_reference( %s )\n" ) % idx_ % ref;
assert( can_add( ref ) );
if ( has_reference( ref ) ) return;
iterator first = begin();
const iterator past = end();
unsigned value = 0;
while ( first != past ) {
value = *first;
++first;
}
++ref;
if ( usedbytes() ) ++value;
unsigned char* target = const_cast<unsigned char*>( first.raw() );
assert( target == my_base() + usedbytes() );
if ( ref > value && ( ref - value ) < 256 ) {
assert( ref != value );
*target = ref - value;
set_usedbytes( usedbytes() + 1 );
} else {
*target++ = 0;
byte_io::write<uint32_t>( target, ref );
set_usedbytes( usedbytes() + 1 + byte_io::byte_length<uint32_t>() );
}
assert( usedbytes() <= capacity() );
}
void leaf_data::remove_reference( uint32_t ref ) {
//logfile() << format( "leaf_data[%s]::remove_reference( %s )\n" ) % idx_ % ref;
unsigned idx = 0;
iterator first = begin();
const iterator past = end();
for ( ; first != past; ++first ) {
if ( *first == ref ) break;
++idx;
}
if ( first != past ) {
//assert( get_reference( idx ) == ref );
iterator next = boost::next( first );
unsigned nbytes = end().raw() - first.raw();
std::memmove( const_cast<unsigned char*>( first.raw() ), next.raw(), nbytes );
set_usedbytes( usedbytes() - nbytes );
unsigned char* iter = const_cast<unsigned char*>( first.raw() );
for ( ; iter < end().raw(); ++iter) {
if (*iter) --*iter;
else {
++iter;
byte_io::write<uint32_t>(iter,byte_io::read<uint32_t>(iter)-1);
iter += byte_io::byte_length<uint32_t>();
}
}
}
}
unsigned leaf_data::nelems() const {
unsigned res = 0;
for ( iterator first = begin(), past =end(); first != past; ++first ) {
++res;
*first;
}
return res;
}
unsigned leaf_data::next_byte_size() const {
return 2 * ( capacity() + data_offset );
}
void leaf_data::grow() {
set_capacity( ( next_byte_size() - data_offset ) );
memset( my_base() + usedbytes(), 0, capacity() - usedbytes() );
}
void leaf_data::construct( void* m ) {
unsigned s = leaf_data::start_bytes();
memset( m, 0, s );
byte_io::write<uint16_t>( reinterpret_cast<unsigned char*>( m ), ( s - data_offset ) );
}
void leaf_data::print( std::ostream& out ) const {
//out << format( "\tsize: %8s\n" ) % used();
out << format( "\tcapacity: %8s\n" ) % capacity();
//out << format( "\tnext: %8s\n" ) % next();
int i = 0;
for ( iterator first = begin(), past = end(); first != past; ++first ) {
out << format( "\tref[ %1% ] = %2%\n" ) % i++ % *first;
}
}