LCOV - code coverage report
Current view: top level - src - TypeSequenceManager.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 371 456 81.4 %
Date: 2020-12-16 07:07:30 Functions: 22 26 84.6 %
Branches: 884 1818 48.6 %

           Branch data     Line data    Source code
       1                 :            : #include "TypeSequenceManager.hpp"
       2                 :            : #include "SequenceData.hpp"
       3                 :            : #include "moab/Error.hpp"
       4                 :            : #include <assert.h>
       5                 :            : #include <limits>
       6                 :            : 
       7                 :            : namespace moab
       8                 :            : {
       9                 :            : 
      10                 :      10496 : TypeSequenceManager::~TypeSequenceManager()
      11                 :            : {
      12                 :            :     // We assume that for there to be multiple sequences referencing
      13                 :            :     // the same SequenceData, there must be some portion of the
      14                 :            :     // SequenceData that is unused. Otherwise the sequences should
      15                 :            :     // have been merged. Given that assumption, it is the case that
      16                 :            :     // either a) a SequenceData is in availableList or b) the
      17                 :            :     // SequenceData is referenced by exactly one sequence.
      18                 :            : 
      19                 :            :     // Delete every entity sequence
      20         [ +  + ]:       7946 :     for( iterator i = begin(); i != end(); ++i )
      21                 :            :     {
      22                 :       2698 :         EntitySequence* seq = *i;
      23                 :            :         // Check for case b) above
      24         [ +  + ]:       2698 :         if( seq->using_entire_data() )
      25                 :            :         {
      26                 :            :             // Delete sequence before data, because sequence
      27                 :            :             // has a pointer to data and may try to dereference
      28                 :            :             // that pointer during its destruction.
      29                 :        506 :             SequenceData* data = seq->data();
      30         [ +  - ]:        506 :             delete seq;
      31         [ +  - ]:        506 :             delete data;
      32                 :            :         }
      33                 :            :         else
      34                 :            :         {
      35         [ +  - ]:       2192 :             delete seq;
      36                 :            :         }
      37                 :            :     }
      38                 :       5248 :     sequenceSet.clear();
      39                 :            : 
      40                 :            :     // Case a) above
      41         [ +  + ]:       6169 :     for( data_iterator i = availableList.begin(); i != availableList.end(); ++i )
      42         [ +  - ]:        921 :         delete *i;
      43                 :       5248 :     availableList.clear();
      44                 :       5248 : }
      45                 :            : 
      46                 :      11340 : ErrorCode TypeSequenceManager::merge_internal( iterator i, iterator j )
      47                 :            : {
      48         [ +  - ]:      11340 :     EntitySequence* dead = *j;
      49         [ +  - ]:      11340 :     sequenceSet.erase( j );
      50 [ +  - ][ +  - ]:      11340 :     ErrorCode rval = ( *i )->merge( *dead );
      51         [ -  + ]:      11340 :     if( MB_SUCCESS != rval )
      52                 :            :     {
      53         [ #  # ]:          0 :         sequenceSet.insert( dead );
      54                 :          0 :         return rval;
      55                 :            :     }
      56                 :            : 
      57 [ +  + ][ +  - ]:      11340 :     if( lastReferenced == dead ) lastReferenced = *i;
      58         [ +  - ]:      11340 :     delete dead;
      59                 :            : 
      60                 :            :     // If merging results in no unused portions of the SequenceData,
      61                 :            :     // remove it from the available list.
      62 [ +  - ][ +  - ]:      11340 :     if( ( *i )->using_entire_data() ) availableList.erase( ( *i )->data() );
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
      63                 :            : 
      64                 :      11340 :     return MB_SUCCESS;
      65                 :            : }
      66                 :            : 
      67                 :    2563776 : ErrorCode TypeSequenceManager::check_merge_next( iterator i )
      68                 :            : {
      69                 :    2563776 :     iterator j = i;
      70         [ +  - ]:    2563776 :     ++j;
      71 [ +  - ][ +  - ]:    2563776 :     if( j == end() || ( *j )->data() != ( *i )->data() || ( *j )->start_handle() > ( *i )->end_handle() + 1 )
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
           [ +  +  #  # ]
      72                 :    2552546 :         return MB_SUCCESS;
      73                 :            : 
      74 [ +  - ][ +  - ]:      11230 :     assert( ( *i )->end_handle() + 1 == ( *j )->start_handle() );
         [ +  - ][ +  - ]
                 [ -  + ]
      75         [ +  - ]:    2563776 :     return merge_internal( i, j );
      76                 :            : }
      77                 :            : 
      78                 :        174 : ErrorCode TypeSequenceManager::check_merge_prev( iterator i )
      79                 :            : {
      80 [ +  - ][ +  - ]:        174 :     if( i == begin() ) return MB_SUCCESS;
                 [ +  + ]
      81                 :            : 
      82                 :        158 :     iterator j = i;
      83         [ +  - ]:        158 :     --j;
      84 [ +  - ][ +  - ]:        158 :     if( ( *j )->data() != ( *i )->data() || ( *j )->end_handle() + 1 < ( *i )->start_handle() ) return MB_SUCCESS;
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
      85                 :            : 
      86 [ +  - ][ +  - ]:        110 :     assert( ( *j )->end_handle() + 1 == ( *i )->start_handle() );
         [ +  - ][ +  - ]
                 [ -  + ]
      87         [ +  - ]:        174 :     return merge_internal( i, j );
      88                 :            : }
      89                 :            : 
      90                 :       1644 : ErrorCode TypeSequenceManager::insert_sequence( EntitySequence* seq_ptr )
      91                 :            : {
      92 [ +  - ][ +  + ]:       1644 :     if( !seq_ptr->data() ) return MB_FAILURE;
      93                 :            : 
      94 [ +  - ][ +  - ]:       4929 :     if( seq_ptr->data()->start_handle() > seq_ptr->start_handle() ||
         [ +  - ][ +  - ]
                 [ -  + ]
      95 [ +  - ][ +  - ]:       3286 :         seq_ptr->data()->end_handle() < seq_ptr->end_handle() || seq_ptr->end_handle() < seq_ptr->start_handle() )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
      96                 :          0 :         return MB_FAILURE;
      97                 :            : 
      98 [ +  - ][ +  - ]:       1643 :     iterator i = lower_bound( seq_ptr->start_handle() );
      99 [ +  - ][ +  - ]:       1643 :     if( i != end() )
                 [ +  + ]
     100                 :            :     {
     101 [ +  - ][ +  - ]:         17 :         if( ( *i )->start_handle() <= seq_ptr->end_handle() ) return MB_ALREADY_ALLOCATED;
         [ +  - ][ +  + ]
     102 [ +  - ][ +  - ]:         15 :         if( seq_ptr->data() != ( *i )->data() && ( *i )->data()->start_handle() <= seq_ptr->data()->end_handle() )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
     103                 :          1 :             return MB_ALREADY_ALLOCATED;
     104                 :            :     }
     105                 :            : 
     106 [ +  - ][ +  - ]:       1640 :     if( i != begin() )
                 [ +  + ]
     107                 :            :     {
     108                 :        402 :         iterator j = i;
     109         [ +  - ]:        402 :         --j;
     110 [ +  - ][ +  - ]:        402 :         if( seq_ptr->data() != ( *j )->data() && ( *j )->data()->end_handle() >= seq_ptr->data()->start_handle() )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
     111                 :        402 :             return MB_ALREADY_ALLOCATED;
     112                 :            :     }
     113                 :            : 
     114         [ +  - ]:       1638 :     i = sequenceSet.insert( i, seq_ptr );
     115                 :            : 
     116                 :            :     // Merge with previous sequence ?
     117 [ +  - ][ +  - ]:       1638 :     if( seq_ptr->start_handle() > seq_ptr->data()->start_handle() && i != begin() )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
           [ +  +  #  # ]
     118                 :            :     {
     119 [ +  - ][ -  + ]:        140 :         if( MB_SUCCESS != check_merge_prev( i ) )
     120                 :            :         {
     121         [ #  # ]:          0 :             sequenceSet.erase( i );
     122                 :          0 :             return MB_FAILURE;
     123                 :            :         }
     124                 :            :     }
     125                 :            : 
     126                 :            :     // Merge with next sequence ?
     127 [ +  - ][ +  - ]:       1638 :     if( ( *i )->end_handle() < ( *i )->data()->end_handle() )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
     128                 :            :     {
     129 [ +  - ][ -  + ]:       1047 :         if( MB_SUCCESS != check_merge_next( i ) )
     130                 :            :         {
     131         [ #  # ]:          0 :             sequenceSet.erase( i );
     132                 :          0 :             return MB_FAILURE;
     133                 :            :         }
     134                 :            :     }
     135                 :            : 
     136                 :            :     // We merged adjacent sequences sharing a SequenceData, so
     137                 :            :     // we can safely assume that unless this EntitySequence is
     138                 :            :     // using the entire SequenceData, there are unused portions.
     139 [ +  - ][ +  + ]:       1638 :     if( !seq_ptr->using_entire_data() ) availableList.insert( seq_ptr->data() );
         [ +  - ][ +  - ]
     140                 :            : 
     141                 :            :     // lastReferenced is only allowed to be NULL if there are
     142                 :            :     // no sequences (avoids unnecessary if's in fast path).
     143         [ +  + ]:       1638 :     if( !lastReferenced ) lastReferenced = seq_ptr;
     144                 :            : 
     145                 :            :     // Each SequenceData has a pointer to the first EntitySequence
     146                 :            :     // referencing it. Update that pointer if the new sequence is
     147                 :            :     // the first one.
     148 [ +  - ][ +  - ]:       1638 :     if( ( *i )->start_handle() == ( *i )->data()->start_handle() || lower_bound( ( *i )->data()->start_handle() ) == i )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
           [ +  +  #  # ]
     149 [ +  - ][ +  - ]:       1608 :         ( *i )->data()->seqManData.firstSequence = i;
     150                 :            : 
     151 [ +  - ][ -  + ]:       1638 :     assert( check_valid_data( seq_ptr ) );
     152                 :       1644 :     return MB_SUCCESS;
     153                 :            : }
     154                 :            : 
     155                 :         21 : ErrorCode TypeSequenceManager::replace_subsequence( EntitySequence* seq_ptr, const int* tag_sizes, int num_tag_sizes )
     156                 :            : {
     157                 :            :     // Find the sequence of interest
     158 [ +  - ][ +  - ]:         21 :     iterator i = lower_bound( seq_ptr->start_handle() );
     159 [ +  - ][ +  - ]:         21 :     if( i == end() || ( *i )->data() == seq_ptr->data() ) return MB_FAILURE;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ -  + ][ #  # ]
     160                 :            :     // New sequence must be a subset of an existing one
     161 [ +  - ][ +  - ]:         21 :     if( seq_ptr->start_handle() < ( *i )->start_handle() || seq_ptr->end_handle() > ( *i )->end_handle() )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
     162                 :          5 :         return MB_FAILURE;
     163                 :            :     // New sequence's data must be new also, and cannot intersect
     164                 :            :     // any existing sequence (just require that the data range
     165                 :            :     // matches the sequence range for now)
     166 [ +  - ][ -  + ]:         16 :     if( !seq_ptr->using_entire_data() ) return MB_FAILURE;
     167                 :            :     // Copy tag data (move ownership of var-len data)
     168 [ +  - ][ +  - ]:         16 :     SequenceData* const dead_data = ( *i )->data();
     169 [ +  - ][ +  - ]:         16 :     dead_data->move_tag_data( seq_ptr->data(), tag_sizes, num_tag_sizes );
     170                 :            : 
     171                 :            :     // Split sequences sharing old data into two groups:
     172                 :            :     // p->i : first sequence to i
     173                 :            :     // i->n : i to one past last sequence
     174         [ +  - ]:         16 :     iterator p, n = i;
     175 [ +  - ][ +  - ]:         16 :     p = ( *i )->data()->seqManData.firstSequence;
     176 [ +  - ][ +  - ]:         20 :     for( ++n; n != end() && ( *n )->data() == ( *i )->data(); ++n )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
     177                 :            :         ;
     178                 :            : 
     179                 :            :     // First subdivide EntitySequence as necessary
     180                 :            :     // Move i to be the first sequence past the insertion point
     181                 :            :     // such that the new order will be:
     182                 :            :     // [p,i-1] seq_ptr [i,n]
     183                 :            :     // where p == i if no previous sequence
     184                 :            : 
     185                 :            :     // Four possible cases:
     186                 :            :     // 0. All entities in sequence are in new sequence
     187                 :            :     // 1. Old entities in sequence before and after new sequence,
     188                 :            :     //    requiring sequence to be split.
     189                 :            :     // 2. Old entities after new sequence
     190                 :            :     // 3. Old entities before new sequence
     191 [ +  - ][ +  - ]:         16 :     const bool some_before = ( ( *i )->start_handle() < seq_ptr->start_handle() );
                 [ +  - ]
     192 [ +  - ][ +  - ]:         16 :     const bool some_after  = ( ( *i )->end_handle() > seq_ptr->end_handle() );
                 [ +  - ]
     193                 :            :     // Case 0
     194 [ +  + ][ +  + ]:         16 :     if( !( some_before || some_after ) )
     195                 :            :     {
     196                 :            :         // Remove dead sequence from internal lists
     197         [ +  - ]:         12 :         EntitySequence* seq = *i;
     198                 :         12 :         iterator dead       = i;
     199         [ +  - ]:         12 :         ++i;
     200 [ +  - ][ +  - ]:         12 :         if( p == dead ) p = i;
     201         [ +  - ]:         12 :         sequenceSet.erase( dead );
     202                 :            : 
     203                 :            :         // Delete old sequence
     204         [ +  - ]:         12 :         delete seq;
     205                 :            :         // Make sure lastReferenced isn't stale
     206         [ +  - ]:         12 :         if( lastReferenced == seq ) lastReferenced = seq_ptr;
     207                 :            :     }
     208                 :            :     // Case 1
     209 [ +  + ][ +  + ]:          4 :     else if( some_before && some_after )
     210                 :            :     {
     211 [ +  - ][ +  - ]:          1 :         i = split_sequence( i, seq_ptr->start_handle() );
     212 [ +  - ][ +  - ]:          1 :         ( *i )->pop_front( seq_ptr->size() );
                 [ +  - ]
     213                 :            :     }
     214                 :            :     // Case 2
     215         [ +  + ]:          3 :     else if( some_after )
     216                 :            :     {
     217 [ +  - ][ +  - ]:          1 :         ( *i )->pop_front( seq_ptr->size() );
                 [ +  - ]
     218                 :            :     }
     219                 :            :     // Case 3
     220                 :            :     else
     221                 :            :     {  // some_before
     222 [ +  - ][ +  - ]:          2 :         ( *i )->pop_back( seq_ptr->size() );
                 [ +  - ]
     223         [ +  - ]:          2 :         ++i;
     224                 :            :     }
     225                 :            : 
     226                 :            :     // Now subdivide the underlying sequence data as necessary
     227         [ +  - ]:         16 :     availableList.erase( dead_data );
     228 [ +  - ][ +  + ]:         16 :     if( p != i )
     229                 :            :     {
     230                 :          3 :         iterator last = i;
     231         [ +  - ]:          3 :         --last;
     232 [ +  - ][ +  - ]:          3 :         SequenceData* new_data = ( *p )->create_data_subset( ( *p )->start_handle(), ( *last )->end_handle() );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     233                 :          3 :         new_data->seqManData.firstSequence = p;
     234                 :            : 
     235 [ +  - ][ +  - ]:          9 :         for( ; p != i; ++p )
                 [ +  + ]
     236 [ +  - ][ +  - ]:          6 :             ( *p )->data( new_data );
     237                 :            :         // Copy tag data (move ownership of var-len data)
     238         [ +  - ]:          3 :         dead_data->move_tag_data( new_data, tag_sizes, num_tag_sizes );
     239 [ +  - ][ +  - ]:          3 :         if( !( *new_data->seqManData.firstSequence )->using_entire_data() ) availableList.insert( new_data );
         [ +  + ][ +  - ]
     240                 :            :     }
     241 [ +  - ][ +  + ]:         16 :     if( i != n )
     242                 :            :     {
     243                 :          3 :         iterator last = n;
     244         [ +  - ]:          3 :         --last;
     245 [ +  - ][ +  - ]:          3 :         SequenceData* new_data = ( *i )->create_data_subset( ( *i )->start_handle(), ( *last )->end_handle() );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     246                 :          3 :         new_data->seqManData.firstSequence = i;
     247 [ +  - ][ +  - ]:          9 :         for( ; i != n; ++i )
                 [ +  + ]
     248 [ +  - ][ +  - ]:          6 :             ( *i )->data( new_data );
     249                 :            :         // Copy tag data (move ownership of var-len data)
     250         [ +  - ]:          3 :         dead_data->move_tag_data( new_data, tag_sizes, num_tag_sizes );
     251 [ +  - ][ +  - ]:          3 :         if( !( *new_data->seqManData.firstSequence )->using_entire_data() ) availableList.insert( new_data );
         [ +  + ][ +  - ]
     252                 :            :     }
     253         [ +  - ]:         16 :     delete dead_data;
     254                 :            : 
     255                 :            :     // Put new sequence in lists
     256         [ +  - ]:         21 :     return insert_sequence( seq_ptr );
     257                 :            : }
     258                 :            : 
     259                 :         11 : TypeSequenceManager::iterator TypeSequenceManager::erase( iterator i )
     260                 :            : {
     261         [ +  - ]:         11 :     EntitySequence* seq = *i;
     262         [ +  - ]:         11 :     SequenceData* data  = seq->data();
     263         [ +  - ]:         11 :     iterator j;
     264                 :            : 
     265                 :            :     // Check if we need to delete the referenced SequenceData also
     266                 :            :     bool delete_data;
     267 [ +  - ][ +  + ]:         11 :     if( seq->using_entire_data() )  // Only sequence
     268                 :          1 :         delete_data = true;
     269 [ +  - ][ +  + ]:         10 :     else if( data->seqManData.firstSequence != i )
     270                 :            :     {  // Earlier sequence?
     271                 :          1 :         delete_data = false;
     272         [ +  - ]:          1 :         availableList.insert( data );
     273                 :            :     }
     274                 :            :     else
     275                 :            :     {  // Later sequence ?
     276                 :          9 :         j = i;
     277         [ +  - ]:          9 :         ++j;
     278 [ +  - ][ +  - ]:          9 :         delete_data = ( j == end() || ( *j )->data() != data );
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ #  # ]
     279         [ +  + ]:          9 :         if( delete_data )
     280         [ +  - ]:          7 :             availableList.erase( data );
     281                 :            :         else
     282                 :            :         {
     283         [ +  - ]:          2 :             availableList.insert( data );
     284                 :          2 :             data->seqManData.firstSequence = j;
     285                 :            :         }
     286                 :            :     }
     287                 :            : 
     288                 :            :     // Remove sequence, updating i to be next sequence
     289         [ +  - ]:         11 :     j = i++;
     290         [ +  - ]:         11 :     sequenceSet.erase( j );
     291                 :            : 
     292                 :            :     // Make sure lastReferenced isn't stale. It can only be NULL if
     293                 :            :     // no sequences.
     294 [ +  + ][ +  + ]:         11 :     if( lastReferenced == seq ) lastReferenced = sequenceSet.empty() ? 0 : *sequenceSet.begin();
         [ +  - ][ +  + ]
                 [ #  # ]
     295                 :            : 
     296                 :            :     // Always delete sequence before the SequenceData it references.
     297 [ +  - ][ +  - ]:         11 :     assert( 0 == find( seq->start_handle() ) );
                 [ -  + ]
     298         [ +  - ]:         11 :     delete seq;
     299         [ +  + ]:         11 :     if( delete_data )
     300         [ +  - ]:          8 :         delete data;
     301                 :            :     else
     302                 :            :     {
     303 [ +  - ][ +  - ]:          3 :         assert( check_valid_data( *data->seqManData.firstSequence ) );
                 [ -  + ]
     304         [ -  + ]:          3 :         assert( lastReferenced != seq );
     305                 :            :     }
     306                 :         11 :     return i;
     307                 :            : }
     308                 :            : 
     309                 :       6855 : ErrorCode TypeSequenceManager::remove_sequence( const EntitySequence* seq_ptr, bool& unreferenced_data )
     310                 :            : {
     311                 :            :     // Remove sequence from set
     312 [ +  - ][ +  - ]:       6855 :     iterator i = lower_bound( seq_ptr->start_handle() );
     313 [ +  - ][ +  - ]:       6855 :     if( i == end() || *i != seq_ptr ) return MB_ENTITY_NOT_FOUND;
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ #  # ]
     314         [ +  - ]:       6854 :     sequenceSet.erase( i );
     315                 :            : 
     316                 :            :     // Check if this is the only sequence referencing its data
     317 [ +  - ][ -  + ]:       6854 :     if( seq_ptr->using_entire_data() )
     318                 :          0 :         unreferenced_data = true;
     319                 :            :     else
     320                 :            :     {
     321 [ +  - ][ +  - ]:       6854 :         i                 = lower_bound( seq_ptr->data()->start_handle() );
                 [ +  - ]
     322 [ +  - ][ +  - ]:       6854 :         unreferenced_data = i == end() || ( *i )->data() != seq_ptr->data();
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ #  # ]
     323         [ +  + ]:       6854 :         if( unreferenced_data )
     324 [ +  - ][ +  - ]:         46 :             availableList.erase( seq_ptr->data() );
     325                 :            :         else
     326         [ +  - ]:       6808 :             seq_ptr->data()->seqManData.firstSequence = i;  // Might be 'i' already
     327                 :            :     }
     328                 :            : 
     329 [ +  + ][ +  + ]:       6854 :     if( lastReferenced == seq_ptr ) lastReferenced = sequenceSet.empty() ? 0 : *sequenceSet.begin();
         [ +  - ][ +  + ]
                 [ #  # ]
     330                 :            : 
     331                 :       6855 :     return MB_SUCCESS;
     332                 :            : }
     333                 :            : 
     334                 :    2563662 : TypeSequenceManager::iterator TypeSequenceManager::find_free_handle( EntityHandle min_start_handle,
     335                 :            :                                                                      EntityHandle max_end_handle, bool& append_out,
     336                 :            :                                                                      int values_per_ent )
     337                 :            : {
     338 [ +  - ][ +  - ]:    2574922 :     for( data_iterator i = availableList.begin(); i != availableList.end(); ++i )
                 [ +  + ]
     339                 :            :     {
     340 [ +  - ][ +  - ]:    2574028 :         if( ( *( *i )->seqManData.firstSequence )->values_per_entity() != values_per_ent ) continue;
         [ +  - ][ +  + ]
     341                 :            : 
     342 [ +  - ][ +  - ]:    2562769 :         if( ( *i )->start_handle() > max_end_handle || ( *i )->end_handle() < min_start_handle ) continue;
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
     343                 :            : 
     344 [ +  - ][ +  - ]:    7688319 :         for( iterator j = ( *i )->seqManData.firstSequence;
                 [ +  + ]
     345 [ +  - ][ +  - ]:    5125546 :              j != end() && ( *j )->start_handle() <= ( max_end_handle + 1 ) && ( *j )->data() == *i; ++j )
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
     346                 :            :         {
     347 [ +  - ][ +  - ]:    2562772 :             if( ( *j )->end_handle() + 1 < min_start_handle ) continue;
                 [ +  + ]
     348 [ +  - ][ +  - ]:    2562768 :             if( ( *j )->start_handle() > ( *i )->start_handle() && ( *j )->start_handle() > min_start_handle )
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
     349                 :            :             {
     350                 :         37 :                 append_out = false;
     351                 :    2562768 :                 return j;
     352                 :            :             }
     353 [ +  - ][ +  - ]:    2562731 :             if( ( *j )->end_handle() < ( *i )->end_handle() && ( *j )->end_handle() < max_end_handle )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     354                 :            :             {
     355                 :    2562731 :                 append_out = true;
     356                 :    2562731 :                 return j;
     357                 :            :             }
     358                 :            :         }
     359                 :            :     }
     360                 :            : 
     361                 :    2563662 :     return end();
     362                 :            : }
     363                 :            : 
     364                 :        310 : bool TypeSequenceManager::is_free_sequence( EntityHandle start, EntityID num_entities, SequenceData*& data_out,
     365                 :            :                                             int values_per_ent )
     366                 :            : {
     367                 :        310 :     data_out = 0;
     368 [ +  - ][ +  + ]:        310 :     if( empty() ) return true;
     369                 :            : 
     370         [ +  - ]:         87 :     const_iterator i = lower_bound( start );
     371 [ +  - ][ +  - ]:         87 :     if( i == end() )
                 [ +  + ]
     372                 :            :     {
     373         [ +  - ]:         40 :         --i;  // Safe because already tested empty()
     374                 :            :         // If we don't overlap the last data object...
     375 [ +  - ][ +  - ]:         40 :         if( ( *i )->data()->end_handle() < start ) return true;
         [ +  - ][ +  + ]
     376 [ +  - ][ +  - ]:          2 :         data_out = ( *i )->data();
     377 [ +  - ][ +  - ]:          2 :         if( ( *i )->values_per_entity() != values_per_ent ) return false;
                 [ -  + ]
     378                 :            :         // If we overlap a data object, we must be entirely inside of it
     379 [ +  - ][ +  - ]:          2 :         return start + num_entities - 1 <= ( *i )->data()->end_handle();
                 [ +  - ]
     380                 :            :     }
     381                 :            : 
     382                 :            : #ifndef NDEBUG
     383 [ +  - ][ +  - ]:         47 :     if( i != begin() )
                 [ +  + ]
     384                 :            :     {
     385                 :          5 :         const_iterator j = i;
     386         [ +  - ]:          5 :         --j;
     387 [ +  - ][ +  - ]:          5 :         assert( ( *j )->end_handle() < start );
                 [ -  + ]
     388                 :            :     }
     389                 :            : #endif
     390                 :            : 
     391                 :            :     // Check if we fit in the block of free handles
     392 [ +  - ][ +  - ]:         47 :     if( start + num_entities > ( *i )->start_handle() )  // start + num + 1 >= i->start
                 [ +  + ]
     393                 :         44 :         return false;
     394                 :            : 
     395                 :            :     // Check if we overlap the data for the next sequence
     396 [ +  - ][ +  - ]:          3 :     if( start + num_entities > ( *i )->data()->start_handle() )
         [ +  - ][ +  - ]
     397                 :            :     {
     398 [ +  - ][ +  - ]:          3 :         data_out = ( *i )->data();
     399 [ +  - ][ +  - ]:          3 :         if( ( *i )->values_per_entity() != values_per_ent ) return false;
                 [ -  + ]
     400                 :            :         // If overlap, must be entirely contained
     401 [ +  - ][ +  - ]:          3 :         return start >= data_out->start_handle() && start + num_entities - 1 <= data_out->end_handle();
         [ +  - ][ +  - ]
     402                 :            :     }
     403                 :            : 
     404                 :            :     // Check if we overlap the data for the previous sequence
     405 [ #  # ][ #  # ]:          0 :     if( i != begin() )
                 [ #  # ]
     406                 :            :     {
     407         [ #  # ]:          0 :         --i;
     408 [ #  # ][ #  # ]:          0 :         if( ( *i )->data()->end_handle() >= start )
         [ #  # ][ #  # ]
     409                 :            :         {
     410 [ #  # ][ #  # ]:          0 :             data_out = ( *i )->data();
     411 [ #  # ][ #  # ]:          0 :             if( ( *i )->values_per_entity() != values_per_ent ) return false;
                 [ #  # ]
     412 [ #  # ][ #  # ]:          0 :             return start + num_entities - 1 <= ( *i )->data()->end_handle();
                 [ #  # ]
     413                 :            :         }
     414                 :            :     }
     415                 :            : 
     416                 :            :     // Unused handle block that overlaps no SequenceData
     417                 :        310 :     return true;
     418                 :            : }
     419                 :            : 
     420                 :          0 : EntityHandle TypeSequenceManager::find_free_block( EntityID num_entities, EntityHandle min_start_handle,
     421                 :            :                                                    EntityHandle max_end_handle )
     422                 :            : {
     423         [ #  # ]:          0 :     const_iterator i = lower_bound( min_start_handle );
     424 [ #  # ][ #  # ]:          0 :     if( i == end() ) return min_start_handle;
                 [ #  # ]
     425                 :            : 
     426 [ #  # ][ #  # ]:          0 :     if( ( *i )->start_handle() < min_start_handle + num_entities ) return min_start_handle;
                 [ #  # ]
     427                 :            : 
     428 [ #  # ][ #  # ]:          0 :     EntityHandle prev_end = ( *i )->end_handle();
     429         [ #  # ]:          0 :     ++i;
     430 [ #  # ][ #  # ]:          0 :     for( ; i != end(); prev_end = ( *i )->end_handle(), ++i )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     431                 :            :     {
     432 [ #  # ][ #  # ]:          0 :         EntityID len = ( *i )->start_handle() - prev_end - 1;
     433         [ #  # ]:          0 :         if( len >= num_entities ) break;
     434                 :            :     }
     435                 :            : 
     436         [ #  # ]:          0 :     if( prev_end + num_entities > max_end_handle )
     437                 :          0 :         return 0;
     438                 :            :     else
     439                 :          0 :         return prev_end + 1;
     440                 :            : }
     441                 :            : 
     442                 :            : struct range_data
     443                 :            : {
     444                 :            :     EntityID num_entities;
     445                 :            :     EntityHandle min_start_handle, max_end_handle;
     446                 :            :     EntityHandle first, last;
     447                 :            : };
     448                 :            : 
     449                 :       1602 : static bool check_range( const range_data& d, bool prefer_end, EntityHandle& result )
     450                 :            : {
     451                 :       1602 :     EntityHandle first = std::max( d.min_start_handle, d.first );
     452                 :       1602 :     EntityHandle last  = std::min( d.max_end_handle, d.last );
     453         [ +  + ]:       1602 :     if( last < first + d.num_entities - 1 )
     454                 :            :     {
     455                 :       1275 :         result = 0;
     456                 :       1275 :         return false;
     457                 :            :     }
     458                 :            : 
     459         [ +  + ]:        327 :     result = prefer_end ? last + 1 - d.num_entities : first;
     460                 :        327 :     return true;
     461                 :            : }
     462                 :            : 
     463                 :       1319 : EntityHandle TypeSequenceManager::find_free_sequence( EntityID num_entities, EntityHandle min_start_handle,
     464                 :            :                                                       EntityHandle max_end_handle, SequenceData*& data_out,
     465                 :            :                                                       EntityID& data_size, int num_verts )
     466                 :            : {
     467         [ -  + ]:       1319 :     if( max_end_handle < min_start_handle + num_entities - 1 ) return 0;
     468                 :            : 
     469                 :            :     EntityHandle result;
     470 [ +  - ][ +  - ]:       1319 :     iterator p, i = lower_bound( min_start_handle );
     471                 :       1319 :     range_data d = { num_entities, min_start_handle, max_end_handle, 0, 0 };
     472                 :            : 
     473 [ +  - ][ +  - ]:       1319 :     if( i == end() )
                 [ +  + ]
     474                 :            :     {
     475                 :        990 :         data_out = 0;
     476                 :        990 :         return min_start_handle;
     477                 :            :     }
     478 [ +  - ][ +  - ]:        329 :     else if( i == begin() )
                 [ +  + ]
     479                 :            :     {
     480 [ +  - ][ +  - ]:        328 :         if( ( *i )->values_per_entity() == num_verts )
                 [ +  + ]
     481                 :            :         {
     482 [ +  - ][ +  - ]:        284 :             d.first = ( *i )->data()->start_handle();
                 [ +  - ]
     483 [ +  - ][ +  - ]:        284 :             d.last  = ( *i )->start_handle() - 1;
     484 [ +  - ][ +  + ]:        284 :             if( check_range( d, true, result ) )
     485                 :            :             {
     486 [ +  - ][ +  - ]:          1 :                 data_out = ( *i )->data();
     487                 :          1 :                 return result;
     488                 :            :             }
     489                 :            :         }
     490                 :        327 :         d.first = min_start_handle;
     491 [ +  - ][ +  - ]:        327 :         d.last  = ( *i )->data()->start_handle() - 1;
                 [ +  - ]
     492 [ +  - ][ +  + ]:        327 :         if( check_range( d, true, result ) )
     493                 :            :         {
     494                 :          3 :             data_out = 0;
     495                 :            :             // This will back up against the end of the seq data, so
     496                 :            :             // size the data that way
     497                 :          3 :             data_size = num_entities;
     498                 :          3 :             return result;
     499                 :            :         }
     500         [ +  - ]:        324 :         p = i++;
     501                 :            :     }
     502                 :            :     else
     503                 :            :     {
     504                 :          1 :         p = i;
     505         [ +  - ]:          1 :         --p;
     506                 :            :     }
     507                 :            : 
     508 [ +  - ][ +  - ]:        580 :     for( ; i != end() && ( *i )->start_handle() < max_end_handle; p = i++ )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
           [ +  +  #  # ]
     509                 :            :     {
     510 [ +  - ][ +  - ]:        256 :         if( ( *p )->data() == ( *i )->data() )
         [ +  - ][ +  - ]
                 [ +  + ]
     511                 :            :         {
     512 [ +  - ][ +  - ]:          7 :             if( ( *p )->values_per_entity() == num_verts )
                 [ +  - ]
     513                 :            :             {
     514 [ +  - ][ +  - ]:          7 :                 d.first = ( *p )->end_handle() + 1;
     515 [ +  - ][ +  - ]:          7 :                 d.last  = ( *i )->start_handle() - 1;
     516 [ +  - ][ +  + ]:          7 :                 if( check_range( d, false, result ) )
     517                 :            :                 {
     518 [ +  - ][ +  - ]:          1 :                     data_out = ( *p )->data();
     519                 :          1 :                     return result;
     520                 :            :                 }
     521                 :            :             }
     522                 :            :         }
     523                 :            :         else
     524                 :            :         {
     525 [ +  - ][ +  - ]:        249 :             if( ( *p )->values_per_entity() == num_verts )
                 [ +  + ]
     526                 :            :             {
     527 [ +  - ][ +  - ]:        123 :                 d.first = ( *p )->end_handle() + 1;
     528 [ +  - ][ +  - ]:        123 :                 d.last  = ( *p )->data()->end_handle();
                 [ +  - ]
     529 [ +  - ][ -  + ]:        123 :                 if( check_range( d, false, result ) )
     530                 :            :                 {
     531 [ #  # ][ #  # ]:          0 :                     data_out = ( *p )->data();
     532                 :          0 :                     return result;
     533                 :            :                 }
     534                 :            :             }
     535 [ +  - ][ +  - ]:        249 :             if( ( *i )->values_per_entity() == num_verts )
                 [ +  + ]
     536                 :            :             {
     537 [ +  - ][ +  - ]:        121 :                 d.first = ( *i )->data()->start_handle();
                 [ +  - ]
     538 [ +  - ][ +  - ]:        121 :                 d.last  = ( *i )->start_handle() - 1;
     539 [ +  - ][ -  + ]:        121 :                 if( check_range( d, true, result ) )
     540                 :            :                 {
     541 [ #  # ][ #  # ]:          0 :                     data_out = ( *i )->data();
     542                 :          0 :                     return result;
     543                 :            :                 }
     544                 :            :             }
     545 [ +  - ][ +  - ]:        249 :             d.first = ( *p )->data()->end_handle() + 1;
                 [ +  - ]
     546 [ +  - ][ +  - ]:        249 :             d.last  = ( *i )->data()->start_handle() - 1;
                 [ +  - ]
     547 [ +  - ][ -  + ]:        249 :             if( check_range( d, false, result ) )
     548                 :            :             {
     549                 :          0 :                 data_out  = 0;
     550                 :          0 :                 data_size = d.last - d.first + 1;
     551                 :          0 :                 return result;
     552                 :            :             }
     553                 :            :         }
     554                 :            :     }
     555                 :            : 
     556 [ +  - ][ +  - ]:        324 :     if( ( *p )->values_per_entity() == num_verts )
                 [ +  + ]
     557                 :            :     {
     558 [ +  - ][ +  - ]:        278 :         d.first = ( *p )->end_handle() + 1;
     559 [ +  - ][ +  - ]:        278 :         d.last  = ( *p )->data()->end_handle();
                 [ +  - ]
     560 [ +  - ][ +  + ]:        278 :         if( check_range( d, false, result ) )
     561                 :            :         {
     562 [ +  - ][ +  - ]:        111 :             data_out = ( *p )->data();
     563                 :        111 :             return result;
     564                 :            :         }
     565                 :            :     }
     566                 :            : 
     567 [ +  - ][ +  - ]:        213 :     d.first = ( *p )->data()->end_handle() + 1;
                 [ +  - ]
     568                 :        213 :     d.last  = max_end_handle;
     569 [ +  - ][ +  + ]:        213 :     if( check_range( d, false, result ) )
     570                 :            :     {
     571                 :        211 :         data_out = 0;
     572                 :        211 :         return result;
     573                 :            :     }
     574                 :            : 
     575                 :          2 :     data_out = 0;
     576                 :       1319 :     return 0;
     577                 :            : }
     578                 :            : 
     579                 :          0 : EntityHandle TypeSequenceManager::last_free_handle( EntityHandle after_this ) const
     580                 :            : {
     581                 :            :     int junk;
     582         [ #  # ]:          0 :     const_iterator it = lower_bound( after_this );
     583 [ #  # ][ #  # ]:          0 :     if( it == end() )
                 [ #  # ]
     584 [ #  # ][ #  # ]:          0 :         return CREATE_HANDLE( TYPE_FROM_HANDLE( after_this ), MB_END_ID, junk );
     585 [ #  # ][ #  # ]:          0 :     else if( ( *it )->start_handle() > after_this )
                 [ #  # ]
     586                 :            :     {
     587                 :            :         // Need to check against the sequence data first
     588 [ #  # ][ #  # ]:          0 :         EntityHandle rhandle = ( *it )->data()->start_handle();
                 [ #  # ]
     589                 :          0 :         return rhandle - 1;
     590                 :            :     }
     591                 :            :     else
     592                 :          0 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :      25175 : ErrorCode TypeSequenceManager::check_valid_handles( Error* /* error_handler */, EntityHandle first,
     596                 :            :                                                     EntityHandle last ) const
     597                 :            : {
     598         [ +  - ]:      25175 :     const_iterator i = lower_bound( first );
     599 [ +  - ][ +  - ]:      25175 :     if( i == end() || ( *i )->start_handle() > first )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
     600                 :            :     {
     601                 :            : #if 0
     602                 :            :     // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call
     603                 :            :     // MB_SET_ERR on it
     604                 :            :     fprintf(
     605                 :            :       stderr,
     606                 :            :       "[Warning]: Invalid entity handle: 0x%lx\n", (unsigned long)first
     607                 :            :       );
     608                 :            : #endif
     609                 :          7 :         return MB_ENTITY_NOT_FOUND;
     610                 :            :     }
     611                 :            : 
     612 [ +  - ][ +  - ]:      25182 :     while( ( *i )->end_handle() < last )
                 [ +  + ]
     613                 :            :     {
     614 [ +  - ][ +  - ]:         15 :         EntityHandle prev_end = ( *i )->end_handle();
     615         [ +  - ]:         15 :         ++i;
     616 [ +  - ][ +  - ]:         15 :         if( i == end() || prev_end + 1 != ( *i )->start_handle() ) return MB_ENTITY_NOT_FOUND;
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ #  # ]
     617                 :            :     }
     618                 :            : 
     619                 :      25175 :     return MB_SUCCESS;
     620                 :            : }
     621                 :            : 
     622                 :      30113 : ErrorCode TypeSequenceManager::erase( Error* /* error_handler */, EntityHandle h )
     623                 :            : {
     624                 :      30113 :     EntitySequence* seq = find( h );
     625         [ -  + ]:      30113 :     if( !seq )
     626                 :            :     {
     627                 :            : #if 0
     628                 :            :     // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call
     629                 :            :     // MB_SET_ERR on it
     630                 :            :     fprintf(
     631                 :            :       stderr,
     632                 :            :       "[Warning]: Invalid entity handle: 0x%lx\n", (unsigned long)h
     633                 :            :       );
     634                 :            : #endif
     635                 :          0 :         return MB_ENTITY_NOT_FOUND;
     636                 :            :     }
     637                 :            : 
     638         [ +  + ]:      30113 :     if( seq->start_handle() == h )
     639                 :            :     {
     640 [ +  - ][ +  + ]:      19145 :         if( seq->end_handle() != h )
     641                 :            :         {
     642 [ +  - ][ +  + ]:      12294 :             if( seq->using_entire_data() ) availableList.insert( seq->data() );
         [ +  - ][ +  - ]
     643         [ +  - ]:      12294 :             seq->pop_front( 1 );
     644                 :      12294 :             return MB_SUCCESS;
     645                 :            :         }
     646         [ +  - ]:       6851 :         SequenceData* data = seq->data();
     647                 :            :         bool delete_data;
     648         [ +  - ]:       6851 :         ErrorCode rval = remove_sequence( seq, delete_data );
     649         [ -  + ]:       6851 :         if( MB_SUCCESS != rval ) return rval;
     650         [ +  - ]:       6851 :         delete seq;
     651 [ +  + ][ +  - ]:       6851 :         if( delete_data ) delete data;
     652                 :            :     }
     653         [ +  + ]:      10968 :     else if( seq->end_handle() == h )
     654                 :            :     {
     655 [ -  + ][ #  # ]:       3910 :         if( seq->using_entire_data() ) availableList.insert( seq->data() );
     656                 :       3910 :         seq->pop_back( 1 );
     657                 :            :     }
     658                 :            :     else
     659                 :            :     {
     660         [ +  - ]:       7058 :         iterator i = lower_bound( h );
     661 [ +  - ][ +  - ]:       7058 :         if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() );
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
     662         [ +  - ]:       7058 :         i   = split_sequence( i, h );
     663         [ +  - ]:       7058 :         seq = *i;
     664 [ +  - ][ -  + ]:       7058 :         assert( seq->start_handle() == h );
     665         [ +  - ]:       7058 :         seq->pop_front( 1 );
     666                 :            :     }
     667                 :            : 
     668                 :      30113 :     return MB_SUCCESS;
     669                 :            : }
     670                 :            : 
     671                 :      12282 : ErrorCode TypeSequenceManager::erase( Error* /* error */, EntityHandle first, EntityHandle last )
     672                 :            : {
     673                 :            :     // First check that all entities in range are valid
     674                 :            : 
     675         [ +  - ]:      12282 :     ErrorCode rval = check_valid_handles( NULL, first, last );
     676         [ +  + ]:      12282 :     if( MB_SUCCESS != rval ) return rval;
     677                 :            : 
     678                 :            :     // Now remove entities
     679                 :            : 
     680                 :            :     // Get first sequence intersecting range
     681         [ +  - ]:      12280 :     iterator i = lower_bound( first );
     682 [ +  - ][ +  - ]:      12280 :     if( i == end() )  // Shouldn't be possible given check_valid_handles call above.
                 [ -  + ]
     683                 :          0 :         return MB_ENTITY_NOT_FOUND;
     684                 :            : 
     685                 :            :     // If range is entirely in interior of sequence, need to split sequence.
     686 [ +  - ][ +  - ]:      12280 :     if( ( *i )->start_handle() < first && ( *i )->end_handle() > last )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
     687                 :            :     {
     688 [ +  - ][ +  - ]:      12225 :         if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() );
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
     689         [ +  - ]:      12225 :         i = split_sequence( i, first );
     690 [ +  - ][ +  - ]:      12225 :         ( *i )->pop_front( last - first + 1 );
     691 [ +  - ][ +  - ]:      12225 :         assert( check_valid_data( *i ) );
                 [ -  + ]
     692                 :      12225 :         return MB_SUCCESS;
     693                 :            :     }
     694                 :            : 
     695                 :            :     // If range doesn't entirely contain first sequence, remove some
     696                 :            :     // handles from the end of the sequence and advance to the next
     697                 :            :     // sequence.
     698 [ +  - ][ +  - ]:         55 :     if( ( *i )->start_handle() < first )
                 [ +  + ]
     699                 :            :     {
     700 [ +  - ][ +  - ]:         23 :         if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() );
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
     701 [ +  - ][ +  - ]:         23 :         ( *i )->pop_back( ( *i )->end_handle() - first + 1 );
         [ +  - ][ +  - ]
     702         [ +  - ]:         23 :         ++i;
     703                 :            :     }
     704                 :            : 
     705                 :            :     // Destroy all sequences contained entirely within the range
     706 [ +  - ][ +  - ]:         66 :     while( i != end() && ( *i )->end_handle() <= last )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
     707         [ +  - ]:         11 :         i = erase( i );
     708                 :            : 
     709                 :            :     // If necessary, remove entities from the beginning of the
     710                 :            :     // last sequence.
     711 [ +  - ][ +  - ]:         55 :     if( i != end() && ( *i )->start_handle() <= last )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
     712                 :            :     {
     713 [ +  - ][ +  - ]:         28 :         if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() );
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
     714 [ +  - ][ +  - ]:         28 :         ( *i )->pop_front( last - ( *i )->start_handle() + 1 );
         [ +  - ][ +  - ]
     715 [ +  - ][ +  - ]:         28 :         assert( check_valid_data( *i ) );
                 [ -  + ]
     716                 :            :     }
     717                 :            : 
     718                 :      12282 :     return MB_SUCCESS;
     719                 :            : }
     720                 :            : 
     721                 :      19284 : TypeSequenceManager::iterator TypeSequenceManager::split_sequence( iterator i, EntityHandle h )
     722                 :            : {
     723 [ +  - ][ +  - ]:      19284 :     EntitySequence* seq = ( *i )->split( h );
     724 [ -  + ][ #  # ]:      19284 :     if( !seq ) return end();
     725                 :            : 
     726         [ +  - ]:      19284 :     i = sequenceSet.insert( i, seq );
     727 [ +  - ][ +  - ]:      19284 :     assert( check_valid_data( *i ) );
                 [ -  + ]
     728                 :            : 
     729                 :      19284 :     return i;
     730                 :            : }
     731                 :            : 
     732                 :          0 : ErrorCode TypeSequenceManager::is_free_handle( EntityHandle handle, iterator& seq_iter_out, SequenceData*& data_ptr_out,
     733                 :            :                                                EntityHandle& block_start, EntityHandle& block_end, int values_per_ent )
     734                 :            : {
     735                 :            :     int junk;
     736 [ #  # ][ #  # ]:          0 :     block_start = CREATE_HANDLE( TYPE_FROM_HANDLE( handle ), MB_START_ID, junk );
     737 [ #  # ][ #  # ]:          0 :     block_end   = CREATE_HANDLE( TYPE_FROM_HANDLE( handle ), MB_END_ID, junk );
     738                 :            : 
     739         [ #  # ]:          0 :     iterator i = lower_bound( handle );
     740 [ #  # ][ #  # ]:          0 :     if( i != end() )
                 [ #  # ]
     741                 :            :     {
     742 [ #  # ][ #  # ]:          0 :         block_end = ( *i )->start_handle() - 1;
     743                 :            : 
     744                 :            :         // If sequence contains handle, then already allocated
     745 [ #  # ][ #  # ]:          0 :         if( ( *i )->start_handle() <= handle ) return MB_ALREADY_ALLOCATED;
                 [ #  # ]
     746                 :            : 
     747                 :            :         // Handle is not within an existing sequence, but is
     748                 :            :         // within an existing SequenceData...
     749 [ #  # ][ #  # ]:          0 :         if( ( *i )->data()->start_handle() <= handle )
         [ #  # ][ #  # ]
     750                 :            :         {
     751                 :            :             // If values_per_entity don't match, can't put new entity
     752                 :            :             // in existing SequenceData
     753 [ #  # ][ #  # ]:          0 :             if( ( *i )->values_per_entity() != values_per_ent ) return MB_ALREADY_ALLOCATED;
                 [ #  # ]
     754                 :            : 
     755 [ #  # ][ #  # ]:          0 :             data_ptr_out = ( *i )->data();
     756         [ #  # ]:          0 :             if( block_end == handle )
     757                 :            :             {
     758                 :            :                 // Prepend to existing sequence
     759                 :          0 :                 seq_iter_out = i;
     760                 :          0 :                 block_start  = handle;
     761                 :            :             }
     762                 :            :             else
     763                 :            :             {
     764                 :            :                 // Add new sequence to existing SequenceData
     765         [ #  # ]:          0 :                 seq_iter_out = end();
     766 [ #  # ][ #  # ]:          0 :                 if( i == begin() || ( *--i )->data() != data_ptr_out )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     767         [ #  # ]:          0 :                     block_start = data_ptr_out->start_handle();
     768                 :            :                 else
     769 [ #  # ][ #  # ]:          0 :                     block_start = ( *i )->end_handle() + 1;
     770                 :            :             }
     771                 :          0 :             return MB_SUCCESS;
     772                 :            :         }
     773                 :            :     }
     774                 :            : 
     775 [ #  # ][ #  # ]:          0 :     if( i != begin() )
                 [ #  # ]
     776                 :            :     {
     777         [ #  # ]:          0 :         --i;
     778 [ #  # ][ #  # ]:          0 :         block_start = ( *i )->end_handle() + 1;
     779                 :            : 
     780                 :            :         // Handle is within previous sequence data...
     781 [ #  # ][ #  # ]:          0 :         if( ( *i )->data()->end_handle() >= handle )
         [ #  # ][ #  # ]
     782                 :            :         {
     783                 :            :             // If values_per_entity don't match, can't put new entity
     784                 :            :             // in existing SequenceData
     785 [ #  # ][ #  # ]:          0 :             if( ( *i )->values_per_entity() != values_per_ent ) return MB_ALREADY_ALLOCATED;
                 [ #  # ]
     786                 :            : 
     787 [ #  # ][ #  # ]:          0 :             data_ptr_out = ( *i )->data();
     788         [ #  # ]:          0 :             if( block_start == handle )
     789                 :            :             {
     790                 :            :                 // Append to existing sequence
     791                 :          0 :                 seq_iter_out = i;
     792                 :          0 :                 block_end    = handle;
     793                 :            :             }
     794                 :            :             else
     795                 :            :             {
     796                 :            :                 // Add new sequence to existing SequenceData
     797         [ #  # ]:          0 :                 seq_iter_out = end();
     798 [ #  # ][ #  # ]:          0 :                 if( ++i == end() || ( *i )->data() != data_ptr_out )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     799         [ #  # ]:          0 :                     block_end = data_ptr_out->end_handle();
     800                 :            :                 else
     801 [ #  # ][ #  # ]:          0 :                     block_end = ( *i )->start_handle() - 1;
     802                 :            :             }
     803                 :          0 :             return MB_SUCCESS;
     804                 :            :         }
     805                 :            :     }
     806                 :            : 
     807         [ #  # ]:          0 :     seq_iter_out = end();
     808                 :          0 :     data_ptr_out = 0;
     809                 :            : 
     810                 :          0 :     return MB_SUCCESS;
     811                 :            : }
     812                 :            : 
     813                 :    2562729 : ErrorCode TypeSequenceManager::notify_appended( iterator seq )
     814                 :            : {
     815                 :    2562729 :     ErrorCode rval = check_merge_next( seq );
     816 [ +  + ][ +  - ]:    2562729 :     if( ( *seq )->using_entire_data() ) availableList.erase( ( *seq )->data() );
     817                 :            : 
     818                 :    2562729 :     return rval;
     819                 :            : }
     820                 :            : 
     821                 :         34 : ErrorCode TypeSequenceManager::notify_prepended( iterator seq )
     822                 :            : {
     823                 :         34 :     ErrorCode rval = check_merge_prev( seq );
     824 [ -  + ][ #  # ]:         34 :     if( ( *seq )->using_entire_data() ) availableList.erase( ( *seq )->data() );
     825                 :            : 
     826                 :         34 :     return rval;
     827                 :            : }
     828                 :            : 
     829                 :         48 : void TypeSequenceManager::get_memory_use( unsigned long long& entity_storage, unsigned long long& total_storage ) const
     830                 :            : {
     831                 :         48 :     entity_storage = total_storage = 0;
     832 [ +  - ][ +  + ]:         54 :     if( empty() ) return;
     833                 :            : 
     834 [ +  - ][ +  - ]:          6 :     EntityType mytype = TYPE_FROM_HANDLE( lastReferenced->start_handle() );
     835                 :            :     int junk;
     836                 :          6 :     get_memory_use( CREATE_HANDLE( mytype, MB_START_ID, junk ), CREATE_HANDLE( mytype, MB_END_ID, junk ),
     837 [ +  - ][ +  - ]:          6 :                     entity_storage, total_storage );
                 [ +  - ]
     838                 :            : }
     839                 :            : 
     840                 :         10 : void TypeSequenceManager::append_memory_use( EntityHandle first, EntityHandle last, const SequenceData* data,
     841                 :            :                                              unsigned long long& entity_storage,
     842                 :            :                                              unsigned long long& total_storage ) const
     843                 :            : {
     844         [ +  - ]:         10 :     const unsigned long allocated_count = data->size();
     845                 :            : 
     846                 :            :     unsigned long bytes_per_ent, seq_size;
     847                 :         10 :     const_iterator i = data->seqManData.firstSequence;
     848 [ +  - ][ +  - ]:         10 :     ( *i )->get_const_memory_use( bytes_per_ent, seq_size );
     849                 :            : 
     850                 :         10 :     unsigned long other_ent_mem  = 0;
     851                 :         10 :     unsigned long occupied_count = 0, entity_count = 0, sequence_count = 0;
     852 [ +  - ][ +  - ]:         20 :     for( ; i != end() && ( *i )->data() == data; ++i )
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ +  +  #  # ]
     853                 :            :     {
     854 [ +  - ][ +  - ]:         10 :         occupied_count += ( *i )->size();
     855                 :         10 :         ++sequence_count;
     856                 :            : 
     857 [ +  - ][ +  - ]:         10 :         EntityHandle start = std::max( first, ( *i )->start_handle() );
                 [ +  - ]
     858 [ +  - ][ +  - ]:         10 :         EntityHandle stop  = std::min( last, ( *i )->end_handle() );
                 [ +  - ]
     859         [ -  + ]:         10 :         if( stop < start ) continue;
     860                 :            : 
     861                 :         10 :         entity_count += stop - start + 1;
     862 [ +  - ][ +  - ]:         10 :         other_ent_mem += ( *i )->get_per_entity_memory_use( start, stop );
     863                 :            :     }
     864                 :            : 
     865                 :         10 :     unsigned long sum = sequence_count * seq_size + allocated_count * bytes_per_ent;
     866                 :            : 
     867                 :            :     // Watch for overflow
     868 [ +  - ][ +  - ]:         10 :     assert( entity_count > 0 && occupied_count > 0 && allocated_count > 0 );
                 [ -  + ]
     869         [ -  + ]:         10 :     if( std::numeric_limits< unsigned long >::max() / entity_count <= sum )
     870                 :            :     {
     871                 :          0 :         total_storage += sum * ( entity_count / occupied_count ) + other_ent_mem;
     872                 :          0 :         entity_storage += sum * ( entity_count / allocated_count ) + other_ent_mem;
     873                 :            :     }
     874                 :            :     else
     875                 :            :     {
     876                 :         10 :         total_storage += sum * entity_count / occupied_count + other_ent_mem;
     877                 :         10 :         entity_storage += sum * entity_count / allocated_count + other_ent_mem;
     878                 :            :     }
     879                 :         10 : }
     880                 :            : 
     881                 :         10 : void TypeSequenceManager::get_memory_use( EntityHandle first, EntityHandle last, unsigned long long& entity_storage,
     882                 :            :                                           unsigned long long& total_storage ) const
     883                 :            : {
     884                 :         10 :     entity_storage = total_storage = 0;
     885                 :            : 
     886         [ +  + ]:         20 :     while( first <= last )
     887                 :            :     {
     888         [ +  - ]:         16 :         const_iterator i = lower_bound( first );
     889 [ +  - ][ +  - ]:         20 :         if( i == end() ) return;
                 [ +  + ]
     890                 :            : 
     891 [ +  - ][ +  - ]:         10 :         SequenceData* data = ( *i )->data();
     892 [ +  - ][ +  - ]:         10 :         if( first < data->end_handle() ) { append_memory_use( first, last, data, entity_storage, total_storage ); }
                 [ +  - ]
     893         [ +  - ]:         10 :         first = data->end_handle() + 1;
     894                 :            :     }
     895                 :            : }
     896                 :            : 
     897                 :          0 : EntityID TypeSequenceManager::get_occupied_size( const SequenceData* data ) const
     898                 :            : {
     899                 :          0 :     EntityID result = 0;
     900 [ #  # ][ #  # ]:          0 :     for( const_iterator i = data->seqManData.firstSequence; i != end() && ( *i )->data() == data; ++i )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     901 [ #  # ][ #  # ]:          0 :         result += ( *i )->size();
     902                 :            : 
     903                 :          0 :     return result;
     904                 :            : }
     905                 :            : 
     906                 :            : #ifndef NDEBUG
     907                 :      33178 : bool TypeSequenceManager::check_valid_data( const EntitySequence* seq ) const
     908                 :            : {
     909                 :            :     // Caller passed a sequence that should be contained, so cannot be empty
     910 [ +  - ][ -  + ]:      33178 :     if( empty() ) return false;
     911                 :            : 
     912                 :            :     // Make sure lastReferenced points to something
     913         [ -  + ]:      33178 :     if( !lastReferenced ) return false;
     914                 :            : 
     915         [ +  - ]:      33178 :     const_iterator seqi = sequenceSet.lower_bound( lastReferenced );
     916 [ +  - ][ +  - ]:      33178 :     if( seqi == sequenceSet.end() || *seqi != lastReferenced ) return false;
         [ +  - ][ -  + ]
         [ +  - ][ -  + ]
                 [ #  # ]
     917                 :            : 
     918                 :            :     // Make sure passed sequence is in list
     919 [ +  - ][ +  - ]:      33178 :     const EntitySequence* seq2 = find( seq->start_handle() );
     920         [ -  + ]:      33178 :     if( seq2 != seq ) return false;
     921                 :            : 
     922                 :            :     // Check all sequences referencing the same SequenceData
     923         [ +  - ]:      33178 :     const SequenceData* data = seq->data();
     924 [ +  - ][ +  - ]:      33178 :     const_iterator i         = lower_bound( data->start_handle() );
     925 [ +  - ][ -  + ]:      33178 :     if( i != data->seqManData.firstSequence ) return false;
     926                 :            : 
     927 [ +  - ][ +  - ]:      33178 :     if( i != begin() )
                 [ +  + ]
     928                 :            :     {
     929                 :      19146 :         const_iterator j = i;
     930         [ +  - ]:      19146 :         --j;
     931 [ +  - ][ +  - ]:      19146 :         if( ( *j )->end_handle() >= data->start_handle() ) return false;
         [ +  - ][ -  + ]
     932 [ +  - ][ +  - ]:      19146 :         if( ( *j )->data()->end_handle() >= data->start_handle() ) return false;
         [ +  - ][ +  - ]
                 [ -  + ]
     933                 :            :     }
     934                 :            : 
     935                 :            :     for( ;; )
     936                 :            :     {
     937         [ +  - ]:    6250727 :         seq2 = *i;
     938         [ +  - ]:    6250727 :         ++i;
     939 [ +  - ][ +  - ]:    6250727 :         if( i == end() ) return true;
                 [ +  + ]
     940 [ +  - ][ +  - ]:    6224071 :         if( ( *i )->data() != data ) break;
                 [ +  + ]
     941                 :            : 
     942 [ +  - ][ +  - ]:    6217549 :         if( seq2->end_handle() >= ( *i )->start_handle() ) return false;
         [ +  - ][ -  + ]
     943                 :            :     }
     944                 :            : 
     945 [ +  - ][ +  - ]:       6522 :     if( ( *i )->start_handle() <= data->end_handle() ) return false;
         [ +  - ][ -  + ]
     946 [ +  - ][ +  - ]:       6522 :     if( ( *i )->data()->start_handle() <= data->end_handle() ) return false;
         [ +  - ][ +  - ]
                 [ -  + ]
     947                 :            : 
     948                 :    6250727 :     return true;
     949                 :            : }
     950                 :            : 
     951                 :            : #endif
     952                 :            : 
     953                 :            : }  // namespace moab

Generated by: LCOV version 1.11