/* This file is part of indexlib. * Copyright (C) 2005 Luís Pedro Coelho * * 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 #include #include "boost-compat/next_prior.hpp" #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() ) ) 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( 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( target, ref ); set_usedbytes( usedbytes() + 1 + byte_io::byte_length() ); } 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( first.raw() ), next.raw(), nbytes ); set_usedbytes( usedbytes() - nbytes ); unsigned char* iter = const_cast( first.raw() ); for ( ; iter < end().raw(); ++iter) { if (*iter) --*iter; else { ++iter; byte_io::write(iter,byte_io::read(iter)-1); iter += byte_io::byte_length(); } } } } 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( reinterpret_cast( 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; } }