2017-05-26 04:48:44 +08:00
/*
* RangeMap . h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013 - 2018 Apple Inc . and the FoundationDB project authors
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* http : //www.apache.org/licenses/LICENSE-2.0
2018-02-22 02:25:11 +08:00
*
2017-05-26 04:48:44 +08:00
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
# ifndef FLOW_RANGEMAP_H
# define FLOW_RANGEMAP_H
# pragma once
# include "flow/flow.h"
# include <boost/range.hpp>
# include "flow/IndexedSet.h"
using boost : : iterator_range ;
template < class Key >
class RangeMapRange {
public :
Key begin , end ;
RangeMapRange ( Key const & begin , Key const & end ) : begin ( begin ) , end ( end ) { }
} ;
template < class Key >
RangeMapRange < Key > rangeMapRange ( Key const & begin , Key const & end ) { return RangeMapRange < Key > ( begin , end ) ; }
template < class Metric >
struct ConstantMetric {
template < typename pair_type >
Metric operator ( ) ( pair_type const & p ) const { return Metric ( 1 ) ; }
} ;
template < class Metric >
struct KeyBytesMetric {
template < typename pair_type >
Metric operator ( ) ( pair_type const & p ) const { return Metric ( p . key . size ( ) + sizeof ( pair_type ) ) ; }
} ;
template < class Metric >
struct ValueBytesMetric {
template < typename pair_type >
Metric operator ( ) ( pair_type const & p ) const { return Metric ( p . value . size ( ) + sizeof ( pair_type ) ) ; }
} ;
template < class Metric >
struct KeyValueBytesMetric {
template < typename pair_type >
Metric operator ( ) ( pair_type const & p ) const { return Metric ( p . key . size ( ) + p . value . size ( ) + sizeof ( pair_type ) ) ; }
} ;
template < class Key , class Val , class Range = RangeMapRange < Key > , class Metric = int , class MetricFunc = ConstantMetric < Metric > >
class RangeMap {
private :
typedef MapPair < Key , Val > pair_type ;
//Applications may decrement an iterator before ranges begin, or increment after ranges end, but once in this state cannot do further incrementing or decrementing
2020-07-10 13:05:37 +08:00
template < bool isConst >
class IteratorImpl {
using self_t = IteratorImpl < isConst > ;
2017-05-26 04:48:44 +08:00
public :
2020-07-10 13:05:37 +08:00
using value_type = std : : conditional_t < isConst , typename Map < Key , Val , pair_type , Metric > : : const_iterator ,
typename Map < Key , Val , pair_type , Metric > : : iterator > ;
typedef std : : forward_iterator_tag iterator_category ;
using difference_type = int ;
using pointer = self_t * ;
using reference = self_t & ;
IteratorImpl ( ) { } // singular
explicit IteratorImpl < isConst > ( const value_type it ) : it ( it ) { }
2017-05-26 04:48:44 +08:00
Key const & begin ( ) { return it - > key ; }
Key const & end ( ) { auto j = it ; + + j ; return j - > key ; }
Range range ( ) { return Range ( begin ( ) , end ( ) ) ; }
2020-07-11 10:04:35 +08:00
std : : conditional_t < isConst , const Val & , Val & > value ( ) {
2017-05-26 04:48:44 +08:00
//ASSERT( it->key != allKeys.end );
2020-04-01 03:13:02 +08:00
return it - > value ;
2017-05-26 04:48:44 +08:00
}
2020-07-11 10:04:35 +08:00
const Val & cvalue ( ) const { return it - > value ; }
2017-05-26 04:48:44 +08:00
void operator + + ( ) { + + it ; }
void operator - - ( ) { it . decrementNonEnd ( ) ; }
2020-07-10 13:05:37 +08:00
bool operator = = ( self_t const & r ) const { return it = = r . it ; }
bool operator ! = ( self_t const & r ) const { return it ! = r . it ; }
2020-04-01 03:13:02 +08:00
2017-05-26 04:48:44 +08:00
// operator* and -> return this
2020-07-10 13:05:37 +08:00
self_t & operator * ( ) { return * this ; }
self_t * operator - > ( ) { return this ; }
2017-05-26 04:48:44 +08:00
private :
2020-07-10 13:05:37 +08:00
value_type it ;
2017-05-26 04:48:44 +08:00
} ;
2020-07-11 10:04:35 +08:00
public :
2020-07-11 01:43:33 +08:00
using iterator = IteratorImpl < false > ;
using const_iterator = IteratorImpl < true > ;
using Ranges = iterator_range < iterator > ;
using ConstRanges = iterator_range < const_iterator > ;
2017-05-26 04:48:44 +08:00
explicit RangeMap ( Key endKey , Val v = Val ( ) , MetricFunc m = MetricFunc ( ) ) : mf ( m ) {
Key beginKey = Key ( ) ;
pair_type beginPair ( beginKey , v ) ;
map . insert ( beginPair , true , mf ( beginPair ) ) ;
pair_type endPair ( endKey , Val ( ) ) ;
map . insert ( endPair , true , mf ( endPair ) ) ;
}
Val const & operator [ ] ( const Key & k ) { return rangeContaining ( k ) . value ( ) ; }
2020-07-11 01:43:33 +08:00
Ranges ranges ( ) { return Ranges ( iterator ( map . begin ( ) ) , iterator ( map . lastItem ( ) ) ) ; }
ConstRanges ranges ( ) const { return ConstRanges ( const_iterator ( map . begin ( ) ) , const_iterator ( map . lastItem ( ) ) ) ; }
2020-04-16 04:32:52 +08:00
// intersectingRanges returns [begin, end] where begin <= r.begin and end >= r.end
2020-07-10 13:05:37 +08:00
Ranges intersectingRanges ( const Range & r ) {
2020-07-11 01:43:33 +08:00
return Ranges ( rangeContaining ( r . begin ) , iterator ( map . lower_bound ( r . end ) ) ) ;
2020-07-10 13:05:37 +08:00
}
ConstRanges intersectingRanges ( const Range & r ) const {
2020-07-11 01:43:33 +08:00
return ConstRanges ( rangeContaining ( r . begin ) , const_iterator ( map . lower_bound ( r . end ) ) ) ;
2020-07-10 13:05:37 +08:00
}
2017-05-26 04:48:44 +08:00
// containedRanges() will return all ranges that are fully contained by the passed range (note that a range fully contains itself)
2020-07-10 13:05:37 +08:00
Ranges containedRanges ( const Range & r ) {
2020-07-11 01:43:33 +08:00
iterator s ( map . lower_bound ( r . begin ) ) ;
if ( s . begin ( ) > = r . end ) return Ranges ( s , s ) ;
2017-05-26 04:48:44 +08:00
return Ranges ( s , rangeContaining ( r . end ) ) ;
}
template < class ComparableToKey >
2020-07-11 01:43:33 +08:00
iterator rangeContaining ( const ComparableToKey & k ) {
return iterator ( map . lastLessOrEqual ( k ) ) ;
2020-07-10 13:05:37 +08:00
}
template < class ComparableToKey >
2020-07-11 01:43:33 +08:00
const_iterator rangeContaining ( const ComparableToKey & k ) const {
return const_iterator ( map . lastLessOrEqual ( k ) ) ;
2017-05-26 04:48:44 +08:00
}
// Returns the range containing a key infinitesimally before k, or the first range if k==Key()
template < class ComparableToKey >
2020-07-11 01:43:33 +08:00
iterator rangeContainingKeyBefore ( const ComparableToKey & k ) {
iterator i ( map . lower_bound ( k ) ) ;
2020-07-10 13:05:37 +08:00
if ( ! i - > begin ( ) . size ( ) ) return i ;
- - i ;
return i ;
}
template < class ComparableToKey >
2020-07-11 01:43:33 +08:00
const_iterator rangeContainingKeyBefore ( const ComparableToKey & k ) const {
const_iterator i ( map . lower_bound ( k ) ) ;
2017-05-26 04:48:44 +08:00
if ( ! i - > begin ( ) . size ( ) ) return i ;
- - i ;
return i ;
}
2020-07-11 01:43:33 +08:00
iterator lastItem ( ) {
2020-07-10 13:05:37 +08:00
auto i ( map . lastItem ( ) ) ;
2017-05-26 04:48:44 +08:00
i . decrementNonEnd ( ) ;
2020-07-11 01:43:33 +08:00
return iterator ( i ) ;
2017-05-26 04:48:44 +08:00
}
2020-08-20 08:32:11 +08:00
const_iterator lastItem ( ) const {
auto i ( map . lastItem ( ) ) ;
i . decrementNonEnd ( ) ;
return const_iterator ( i ) ;
}
2017-05-26 04:48:44 +08:00
int size ( ) const { return map . size ( ) - 1 ; } // We always have one range bounded by two entries
2020-07-11 01:43:33 +08:00
iterator randomRange ( ) { return iterator ( map . index ( deterministicRandom ( ) - > randomInt ( 0 , map . size ( ) - 1 ) ) ) ; }
const_iterator randomRange ( ) const {
return const_iterator ( map . index ( deterministicRandom ( ) - > randomInt ( 0 , map . size ( ) - 1 ) ) ) ;
}
iterator nthRange ( int n ) { return iterator ( map . index ( n ) ) ; }
const_iterator nthRange ( int n ) const { return const_iterator ( map . index ( n ) ) ; }
2017-05-26 04:48:44 +08:00
bool allEqual ( const Range & r , const Val & v ) ;
template < class ComparableToKey >
void coalesce ( const ComparableToKey & k ) ;
void coalesce ( const Range & k ) ;
void validateCoalesced ( ) ;
2020-06-10 08:33:41 +08:00
void operator = ( RangeMap & & r ) noexcept { map = std : : move ( r . map ) ; }
2017-05-26 04:48:44 +08:00
//void clear( const Val& value ) { ranges.clear(); ranges.insert(std::make_pair(Key(),value)); }
void insert ( const Range & keys , const Val & value ) ;
protected :
Map < Key , Val , pair_type , Metric > map ;
const MetricFunc mf ;
} ;
template < class Key , class Val , class Range , class Metric , class MetricFunc >
template < class ComparableToKey >
void RangeMap < Key , Val , Range , Metric , MetricFunc > : : coalesce ( const ComparableToKey & k ) {
auto begin = map . lastLessOrEqual ( k ) ;
auto end = begin ;
const Val & compareVal = begin - > value ;
ASSERT ( begin ! = map . end ( ) ) ;
while ( begin ! = map . begin ( ) & & begin - > value = = compareVal )
begin . decrementNonEnd ( ) ;
while ( end ! = map . lastItem ( ) & & end - > value = = compareVal )
+ + end ;
if ( begin - > value ! = compareVal ) {
+ + begin ;
if ( begin = = end ) return ;
}
+ + begin ;
map . erase ( begin , end ) ;
}
template < class Key , class Val , class Range , class Metric , class MetricFunc >
void RangeMap < Key , Val , Range , Metric , MetricFunc > : : coalesce ( const Range & k ) {
coalesce ( k . begin ) ;
auto it = map . lastLessOrEqual ( k . begin ) ;
Val * lastVal = & it - > value ;
+ + it ;
if ( it = = map . end ( ) )
return ;
bool doCheck = true ;
while ( it ! = map . lastItem ( ) & & doCheck ) {
doCheck = it - > key < k . end ;
if ( it - > value = = * lastVal ) {
doCheck = true ;
auto begin = it ;
+ + it ;
map . erase ( begin , it ) ;
}
else {
lastVal = & it - > value ;
+ + it ;
}
}
if ( EXPENSIVE_VALIDATION )
validateCoalesced ( ) ;
}
template < class Key , class Val , class Range , class Metric , class MetricFunc >
void RangeMap < Key , Val , Range , Metric , MetricFunc > : : validateCoalesced ( ) {
auto it = map . begin ( ) ;
Val * lastVal = & it - > value ;
+ + it ;
auto end = map . lastItem ( ) ;
for ( ; it ! = end ; + + it ) {
ASSERT ( it - > value ! = * lastVal ) ;
lastVal = & it - > value ;
}
}
template < class Key , class Val , class Range , class Metric , class MetricFunc >
bool RangeMap < Key , Val , Range , Metric , MetricFunc > : : allEqual ( const Range & keys , const Val & val ) {
auto r = intersectingRanges ( keys ) ;
for ( auto i = r . begin ( ) ; i ! = r . end ( ) ; + + i )
if ( i . value ( ) ! = val )
return false ;
return true ;
}
template < class Key , class Val , class Range , class Metric , class MetricFunc >
void RangeMap < Key , Val , Range , Metric , MetricFunc > : : insert ( const Range & keys , const Val & value ) {
if ( keys . begin = = keys . end )
return ;
auto end = map . lower_bound ( keys . end ) ;
if ( end - > key ! = keys . end ) {
end . decrementNonEnd ( ) ;
const Val & valueAfterRange = end - > value ;
pair_type endPair ( keys . end , valueAfterRange ) ;
end = map . insert ( endPair , true , mf ( endPair ) ) ;
}
auto begin = map . lower_bound ( keys . begin ) ;
map . erase ( begin , end ) ;
pair_type beginPair ( keys . begin , value ) ;
map . insert ( beginPair , true , mf ( beginPair ) ) ;
}
2020-08-20 08:32:11 +08:00
# endif