@@ -85,9 +85,10 @@ module Streamly.Internal.FileSystem.Path.Common
8585 , normalizeSeparators
8686 -- , normalize -- separators and /./ components (split/combine)
8787 , eqPathBytes
88- , EqCfg (.. )
89- , eqCfg
90- , eqPathWith
88+ , EqCfg
89+ , ignoreTrailingSeparators
90+ , ignoreCase
91+ , allowRelativeEquality
9192 , eqPath
9293 -- , commonPrefix -- common prefix of two paths
9394 -- , eqPrefix -- common prefix is equal to first path
@@ -146,6 +147,7 @@ import qualified Streamly.Internal.Unicode.Stream as Unicode
146147>>> import qualified Streamly.Internal.Data.Array as Array
147148>>> import qualified Streamly.Internal.FileSystem.Path.Common as Common
148149>>> import qualified Streamly.Internal.Unicode.Stream as Unicode
150+ >>> import Streamly.Internal.FileSystem.Path.Common (ignoreTrailingSeparators, allowRelativeEquality, ignoreCase)
149151
150152>>> packPosix = unsafePerformIO . Stream.fold Array.create . Unicode.encodeUtf8' . Stream.fromList
151153>>> unpackPosix = runIdentity . Stream.toList . Unicode.decodeUtf8' . Array.read
@@ -1388,11 +1390,19 @@ eqPathBytes = Array.byteEq
13881390-- | Options for path comparison operation. By default path comparison uses a
13891391-- strict criteria for equality. The following options are provided to
13901392-- control the strictness.
1393+ --
1394+ -- The default configuration is as follows:
1395+ -- >>> :{
1396+ -- defaultMod = ignoreTrailingSeparators False
1397+ -- . ignoreCase False
1398+ -- . allowRelativeEquality False
1399+ -- :}
1400+ --
13911401data EqCfg =
13921402 EqCfg
1393- { ignoreTrailingSeparators :: Bool -- ^ Allows "x\/" == "x"
1394- , ignoreCase :: Bool -- ^ Allows "x" == \"X\"
1395- , allowRelativeEquality :: Bool
1403+ { _ignoreTrailingSeparators :: Bool -- ^ Allows "x\/" == "x"
1404+ , _ignoreCase :: Bool -- ^ Allows "x" == \"X\"
1405+ , _allowRelativeEquality :: Bool
13961406 -- ^ A leading dot is ignored, thus ".\/x" == ".\/x" and ".\/x" == "x".
13971407 -- On Windows allows "\/x" == \/x" and "C:x == C:x"
13981408
@@ -1413,11 +1423,21 @@ data EqCfg =
14131423--
14141424eqCfg :: EqCfg
14151425eqCfg = EqCfg
1416- { ignoreTrailingSeparators = False
1417- , ignoreCase = False
1418- , allowRelativeEquality = False
1426+ { _ignoreTrailingSeparators = False
1427+ , _ignoreCase = False
1428+ , _allowRelativeEquality = False
14191429 }
14201430
1431+ ignoreTrailingSeparators :: Bool -> EqCfg -> EqCfg
1432+ ignoreTrailingSeparators val conf = conf { _ignoreTrailingSeparators = val }
1433+
1434+ ignoreCase :: Bool -> EqCfg -> EqCfg
1435+ ignoreCase val conf = conf { _ignoreCase = val }
1436+
1437+ allowRelativeEquality :: Bool -> EqCfg -> EqCfg
1438+ allowRelativeEquality val conf = conf { _allowRelativeEquality = val }
1439+
1440+
14211441data PosixRoot = PosixRootAbs | PosixRootRel deriving Eq
14221442
14231443data WindowsRoot =
@@ -1521,38 +1541,34 @@ eqComponentsWith ignCase decoder os a b =
15211541 Array. byteEq (splitPath_ os a) (splitPath_ os b)
15221542
15231543-- XXX can we do something like SpecConstr for such functions e.g. without
1524- -- inlining the function we can use two copies one for allowRelativeEquality
1544+ -- inlining the function we can use two copies one for _allowRelativeEquality
15251545-- True and other for False and so on for other values of PathEq.
15261546
1527- {-# INLINE eqPathWith #-}
1528- eqPathWith :: (Unbox a , Integral a ) =>
1547+ {-# INLINE eqPath #-}
1548+ eqPath :: (Unbox a , Integral a ) =>
15291549 (Stream Identity a -> Stream Identity Char )
1530- -> OS -> EqCfg -> Array a -> Array a -> Bool
1531- eqPathWith decoder os EqCfg { .. } a b =
1550+ -> OS -> ( EqCfg -> EqCfg ) -> Array a -> Array a -> Bool
1551+ eqPath decoder os configMod a b =
15321552 let (rootA, stemA) = splitRoot os a
15331553 (rootB, stemB) = splitRoot os b
15341554
15351555 eqRelative =
1536- if allowRelativeEquality
1537- then eqRootLax ignoreCase os rootA rootB
1556+ if _allowRelativeEquality
1557+ then eqRootLax _ignoreCase os rootA rootB
15381558 else (not (isRootRelative os rootA)
15391559 && not (isRootRelative os rootB))
1540- && eqRootStrict ignoreCase os rootA rootB
1560+ && eqRootStrict _ignoreCase os rootA rootB
15411561
15421562 -- XXX If one ends in a "." and the other ends in ./ (and same for ".."
15431563 -- and "../") then they can be equal. We can append a slash in these two
15441564 -- cases before comparing.
15451565 eqTrailingSep =
1546- ignoreTrailingSeparators
1566+ _ignoreTrailingSeparators
15471567 || hasTrailingSeparator os a == hasTrailingSeparator os b
15481568
15491569 in
15501570 eqRelative
15511571 && eqTrailingSep
1552- && eqComponentsWith ignoreCase decoder os stemA stemB
1553-
1554- {-# INLINE eqPath #-}
1555- eqPath :: (Unbox a , Integral a ) =>
1556- (Stream Identity a -> Stream Identity Char )
1557- -> OS -> Array a -> Array a -> Bool
1558- eqPath decoder os = eqPathWith decoder os eqCfg
1572+ && eqComponentsWith _ignoreCase decoder os stemA stemB
1573+ where
1574+ EqCfg {.. } = configMod eqCfg
0 commit comments