struct cigar_t * merge_cigar_t( const struct cigar_t * c ) { struct cigar_t * res = NULL; if ( c != NULL && c -> length > 0 ) { res = malloc( sizeof * res ); if ( res != NULL ) { init_cigar_t( res, c->size ); if ( res->size == c->size ) { int i, last; append_to_cigar_t( res, c->op[ 0 ], c->count[ 0 ] ); for ( i = 1; i < c->length; ++i ) { last = res->length - 1; if ( can_merge( c->op[ i ], res->op[ last ] ) ) { res->count[ last ] += c->count[ i ]; res->op[ last ] = 'M'; } else append_to_cigar_t( res, c->op[ i ], c->count[ i ] ); } } } } return res; }
inline bool try_merge(Run& run, Iterator iter, Range const& range) { // if *iter intersects with, or is adjacent to, 'range'... if (can_merge(*iter, range)) { typedef typename Range::value_type value_type; typedef integer_traits<value_type> integer_traits; // merge range and *iter merge(*iter, range); // collapse all subsequent ranges that can merge with *iter: Iterator i = iter+1; // 1. skip subsequent ranges completely included in *iter while (i != run.end() && i->last <= iter->last) ++i; // 2. collapse next range if adjacent or overlapping with *iter if (i != run.end() && i->first-1 <= iter->last) { iter->last = i->last; ++i; } // erase all ranges that were collapsed run.erase(iter+1, i); return true; } return false; }
void Header::merge_header(const Header& to_merge_with) { // should have already verified that could merge before performing merge. //// DEBUG if (! can_merge(to_merge_with)) assert(false); //// END DEBUG // do not currently handle differently-sized headers. if (to_merge_with._header_str.size() != _header_str.size()) assert(false); for (int i = 0; i < _header_str.size(); ++i) { char my_char = _header_str[i]; // keep match any char if (my_char == MATCH_ANY_CHAR) continue; char their_char = to_merge_with._header_str[i]; if (my_char != their_char) _header_str[i] = MATCH_ANY_CHAR; } }
/* * Mark a range of blocks as belonging to the "system zone" --- that * is, filesystem metadata blocks which should never be used by * inodes. */ static int add_system_zone(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, unsigned int count) { struct ext4_system_zone *new_entry = NULL, *entry; struct rb_node **n = &sbi->system_blks.rb_node, *node; struct rb_node *parent = NULL, *new_node = NULL; while (*n) { parent = *n; entry = rb_entry(parent, struct ext4_system_zone, node); if (start_blk < entry->start_blk) n = &(*n)->rb_left; else if (start_blk >= (entry->start_blk + entry->count)) n = &(*n)->rb_right; else { if (start_blk + count > (entry->start_blk + entry->count)) entry->count = (start_blk + count - entry->start_blk); new_node = *n; new_entry = rb_entry(new_node, struct ext4_system_zone, node); break; } } if (!new_entry) { new_entry = kmem_cache_alloc(ext4_system_zone_cachep, GFP_KERNEL); if (!new_entry) return -ENOMEM; new_entry->start_blk = start_blk; new_entry->count = count; new_node = &new_entry->node; rb_link_node(new_node, parent, n); rb_insert_color(new_node, &sbi->system_blks); } /* Can we merge to the left? */ node = rb_prev(new_node); if (node) { entry = rb_entry(node, struct ext4_system_zone, node); if (can_merge(entry, new_entry)) { new_entry->start_blk = entry->start_blk; new_entry->count += entry->count; rb_erase(node, &sbi->system_blks); kmem_cache_free(ext4_system_zone_cachep, entry); } } /* Can we merge to the right? */ node = rb_next(new_node); if (node) { entry = rb_entry(node, struct ext4_system_zone, node); if (can_merge(new_entry, entry)) { new_entry->count += entry->count; rb_erase(node, &sbi->system_blks); kmem_cache_free(ext4_system_zone_cachep, entry); } } return 0; }