lsm-tree-1.0.0.0: src-core/Database/LSMTree/Internal/Map/Range.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_HADDOCK not-home #-}
module Database.LSMTree.Internal.Map.Range (
Bound (.., BoundExclusive, BoundInclusive)
, Clusive (..)
, rangeLookup
) where
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Map.Internal (Map (..))
data Clusive = Exclusive | Inclusive deriving stock Show
data Bound k = NoBound | Bound !k !Clusive deriving stock Show
{-# COMPLETE BoundExclusive, BoundInclusive #-}
pattern BoundExclusive :: k -> Bound k
pattern BoundExclusive k = Bound k Exclusive
pattern BoundInclusive :: k -> Bound k
pattern BoundInclusive k = Bound k Inclusive
-- | Find all the keys in the given range and return the corresponding
-- (key, value) pairs (in ascending order).
--
rangeLookup ::
forall k v. Ord k
=> Bound k -- ^ lower bound
-> Bound k -- ^ upper bound
-> Map k v
-> [(k, v)]
rangeLookup NoBound NoBound m = Map.toList m
rangeLookup (Bound lb lc) NoBound m = rangeLookupLo lb lc m []
rangeLookup NoBound (Bound ub uc) m = rangeLookupHi ub uc m []
rangeLookup (Bound lb lc) (Bound ub uc) m = rangeLookupBoth lb lc ub uc m []
toDList :: Map k v -> [(k, v)] -> [(k, v)]
toDList Tip = id
toDList (Bin _ k v l r) = toDList l . ((k,v):) . toDList r
rangeLookupLo :: Ord k => k -> Clusive -> Map k v -> [(k, v)] -> [(k, v)]
rangeLookupLo !_ !_ Tip = id
rangeLookupLo lb lc (Bin _ k v l r)
-- ... | --- k -----
| evalLowerBound lb lc k
= rangeLookupLo lb lc l . ((k, v) :) . toDList r
-- ... k ... |--------
| otherwise
= rangeLookupLo lb lc r
rangeLookupHi :: Ord k => k -> Clusive -> Map k v -> [(k, v)] -> [(k, v)]
rangeLookupHi !_ !_ Tip = id
rangeLookupHi ub uc (Bin _ k v l r)
-- --- k --- | ...
| evalUpperBound ub uc k
= toDList l . ((k, v) :) . rangeLookupHi ub uc r
-- --------- | ... k ...
| otherwise
= rangeLookupHi ub uc l
rangeLookupBoth :: Ord k => k -> Clusive -> k -> Clusive -> Map k v -> [(k, v)] -> [(k, v)]
rangeLookupBoth !_ !_ !_ !_ Tip = id
rangeLookupBoth lb lc ub uc (Bin _ k v l r)
-- ... |--- k ---| ...
| evalLowerBound lb lc k
, evalUpperBound ub uc k
= rangeLookupLo lb lc l . ((k,v):) . rangeLookupHi ub uc r
-- ... |-------| ... k ...
| evalLowerBound lb lc k
= rangeLookupBoth lb lc ub uc l
-- ... k ... |-------| ...
| evalUpperBound ub uc k
= rangeLookupBoth lb lc ub uc r
| otherwise
= id
evalLowerBound :: Ord k => k -> Clusive -> k -> Bool
evalLowerBound b Exclusive k = b < k
evalLowerBound b Inclusive k = b <= k
evalUpperBound :: Ord k => k -> Clusive -> k -> Bool
evalUpperBound b Exclusive k = k < b
evalUpperBound b Inclusive k = k <= b