{-# LANGUAGE UnliftedFFITypes #-}
module Streamly.Internal.FileSystem.Path.Common
(
OS (..)
, isValidPath
, isValidPath'
, validatePath
, validatePath'
, validateFile
, fromChunk
, unsafeFromChunk
, fromChars
, unsafeFromChars
, mkQ
, toChunk
, toString
, toChars
, primarySeparator
, isSeparator
, dropTrailingSeparators
, hasTrailingSeparator
, hasLeadingSeparator
, isBranch
, isRooted
, isAbsolute
, isRootRelative
, isRelativeWithDrive
, hasDrive
, append
, append'
, unsafeAppend
, appendCString
, appendCString'
, unsafeJoinPaths
, splitRoot
, splitHead
, splitTail
, splitPath
, splitPath_
, splitFile
, splitDir
, extensionWord
, splitExtension
, normalizeSeparators
, eqPathBytes
, EqCfg(..)
, eqCfg
, eqPathWith
, eqPath
, wordToChar
, charToWord
, unsafeIndexChar
, unsafeSplitTopLevel
, unsafeSplitDrive
, unsafeSplitUNC
, splitCompact
, splitWithFilter
)
where
#include "assert.hs"
import Control.Monad (when)
import Control.Monad.Catch (MonadThrow(..))
import Control.Monad.IO.Class (MonadIO(..))
import Data.Char (chr, ord, isAlpha, toUpper)
import Data.Function ((&))
import Data.Functor.Identity (Identity(..))
import Data.Word (Word8, Word16)
import Foreign (castPtr)
import Foreign.C (CString, CSize(..))
import GHC.Base (unsafeChr, Addr#)
import GHC.Ptr (Ptr(..))
import Language.Haskell.TH (Q, Exp)
import Language.Haskell.TH.Quote (QuasiQuoter (..))
import Streamly.Internal.Data.Array (Array(..))
import Streamly.Internal.Data.MutArray (MutArray)
import Streamly.Internal.Data.MutByteArray (Unbox(..))
import Streamly.Internal.Data.Path (PathException(..))
import Streamly.Internal.Data.Stream (Stream)
import System.IO.Unsafe (unsafePerformIO)
import qualified Data.List as List
import qualified Streamly.Internal.Data.Array as Array
import qualified Streamly.Internal.Data.Fold as Fold
import qualified Streamly.Internal.Data.MutArray as MutArray
import qualified Streamly.Internal.Data.Stream as Stream
import qualified Streamly.Internal.Unicode.Stream as Unicode
data OS = Windows | Posix deriving OS -> OS -> Bool
(OS -> OS -> Bool) -> (OS -> OS -> Bool) -> Eq OS
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OS -> OS -> Bool
== :: OS -> OS -> Bool
$c/= :: OS -> OS -> Bool
/= :: OS -> OS -> Bool
Eq
charToWord :: Integral a => Char -> a
charToWord :: forall a. Integral a => Char -> a
charToWord Char
c =
let n :: Int
n = Char -> Int
ord Char
c
in Bool -> a -> a
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
255) (Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
wordToChar :: Integral a => a -> Char
wordToChar :: forall a. Integral a => a -> Char
wordToChar = Int -> Char
unsafeChr (Int -> Char) -> (a -> Int) -> a -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
unsafeIndexChar :: (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar :: forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
i Array a
a = a -> Char
forall a. Integral a => a -> Char
wordToChar (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
i Array a
a)
foldArr :: Unbox a => Fold.Fold Identity a b -> Array a -> b
foldArr :: forall a b. Unbox a => Fold Identity a b -> Array a -> b
foldArr Fold Identity a b
f Array a
arr = Identity b -> b
forall a. Identity a -> a
runIdentity (Identity b -> b) -> Identity b -> b
forall a b. (a -> b) -> a -> b
$ Fold Identity a b -> Array a -> Identity b
forall (m :: * -> *) a b.
(Monad m, Unbox a) =>
Fold m a b -> Array a -> m b
Array.foldM Fold Identity a b
f Array a
arr
{-# INLINE countLeadingBy #-}
countLeadingBy :: Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy :: forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy a -> Bool
p = Fold Identity a Int -> Array a -> Int
forall a b. Unbox a => Fold Identity a b -> Array a -> b
foldArr ((a -> Bool) -> Fold Identity a Int -> Fold Identity a Int
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy_ (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) Fold Identity a Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length)
countTrailingBy :: Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy :: forall a. Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy a -> Bool
p = Fold Identity a Int -> Array a -> Int
forall a b. Unbox a => Fold Identity a b -> Array a -> b
Array.foldRev ((a -> Bool) -> Fold Identity a Int -> Fold Identity a Int
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy_ (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) Fold Identity a Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length)
extensionWord :: Integral a => a
extensionWord :: forall a. Integral a => a
extensionWord = Char -> a
forall a. Integral a => Char -> a
charToWord Char
'.'
posixSeparator :: Char
posixSeparator :: Char
posixSeparator = Char
'/'
windowsSeparator :: Char
windowsSeparator :: Char
windowsSeparator = Char
'\\'
{-# INLINE primarySeparator #-}
primarySeparator :: OS -> Char
primarySeparator :: OS -> Char
primarySeparator OS
Posix = Char
posixSeparator
primarySeparator OS
Windows = Char
windowsSeparator
{-# INLINE isSeparator #-}
isSeparator :: OS -> Char -> Bool
isSeparator :: OS -> Char -> Bool
isSeparator OS
Posix Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
posixSeparator
isSeparator OS
Windows Char
c = (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
windowsSeparator) Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
posixSeparator)
{-# INLINE isSeparatorWord #-}
isSeparatorWord :: Integral a => OS -> a -> Bool
isSeparatorWord :: forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os = OS -> Char -> Bool
isSeparator OS
os (Char -> Bool) -> (a -> Char) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Char
forall a. Integral a => a -> Char
wordToChar
{-# INLINE dropTrailingBy #-}
dropTrailingBy :: (Unbox a, Integral a) =>
OS -> (a -> Bool) -> Array a -> Array a
dropTrailingBy :: forall a.
(Unbox a, Integral a) =>
OS -> (a -> Bool) -> Array a -> Array a
dropTrailingBy OS
os a -> Bool
p Array a
arr =
let len :: Int
len = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
arr
n :: Int
n = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy a -> Bool
p Array a
arr
arr1 :: Array a
arr1 = (Array a, Array a) -> Array a
forall a b. (a, b) -> a
fst ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) Array a
arr
in if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then Array a
arr
else if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len
then (Array a, Array a) -> Array a
forall a b. (a, b) -> a
fst ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
1 Array a
arr
else if (OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
Windows)
Bool -> Bool -> Bool
&& (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Array a
arr a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
':')
then (Array a, Array a) -> Array a
forall a b. (a, b) -> a
fst ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Array a
arr
else Array a
arr1
{-# INLINE compactTrailingBy #-}
compactTrailingBy :: Unbox a => (a -> Bool) -> Array a -> Array a
compactTrailingBy :: forall a. Unbox a => (a -> Bool) -> Array a -> Array a
compactTrailingBy a -> Bool
p Array a
arr =
let len :: Int
len = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
arr
n :: Int
n = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy a -> Bool
p Array a
arr
in if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
then Array a
arr
else (Array a, Array a) -> Array a
forall a b. (a, b) -> a
fst ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Array a
arr
{-# INLINE dropTrailingSeparators #-}
dropTrailingSeparators :: (Unbox a, Integral a) => OS -> Array a -> Array a
dropTrailingSeparators :: forall a. (Unbox a, Integral a) => OS -> Array a -> Array a
dropTrailingSeparators OS
os =
OS -> (a -> Bool) -> Array a -> Array a
forall a.
(Unbox a, Integral a) =>
OS -> (a -> Bool) -> Array a -> Array a
dropTrailingBy OS
os (OS -> Char -> Bool
isSeparator OS
os (Char -> Bool) -> (a -> Char) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Char
forall a. Integral a => a -> Char
wordToChar)
hasLeadingSeparator :: (Unbox a, Integral a) => OS -> Array a -> Bool
hasLeadingSeparator :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
hasLeadingSeparator OS
os Array a
a
| Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
a = Bool
False
| OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
a) = Bool
True
| Bool
otherwise = Bool
False
{-# INLINE hasTrailingSeparator #-}
hasTrailingSeparator :: (Integral a, Unbox a) => OS -> Array a -> Bool
hasTrailingSeparator :: forall a. (Integral a, Unbox a) => OS -> Array a -> Bool
hasTrailingSeparator OS
os Array a
path =
let e :: Maybe a
e = Int -> Array a -> Maybe a
forall a. Unbox a => Int -> Array a -> Maybe a
Array.getIndexRev Int
0 Array a
path
in case Maybe a
e of
Maybe a
Nothing -> Bool
False
Just a
x -> OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
x
{-# INLINE toDefaultSeparator #-}
toDefaultSeparator :: Integral a => a -> a
toDefaultSeparator :: forall a. Integral a => a -> a
toDefaultSeparator a
x =
if OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows a
x
then Char -> a
forall a. Integral a => Char -> a
charToWord (OS -> Char
primarySeparator OS
Windows)
else a
x
{-# INLINE normalizeSeparators #-}
normalizeSeparators :: (Integral a, Unbox a) => Array a -> Array a
normalizeSeparators :: forall a. (Integral a, Unbox a) => Array a -> Array a
normalizeSeparators Array a
a =
Int -> Stream Identity a -> Array a
forall a. Unbox a => Int -> Stream Identity a -> Array a
Array.fromPureStreamN (Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a)
(Stream Identity a -> Array a) -> Stream Identity a -> Array a
forall a b. (a -> b) -> a -> b
$ (a -> a) -> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Integral a => a -> a
toDefaultSeparator
(Stream Identity a -> Stream Identity a)
-> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read Array a
a
{-# INLINE unsafeHasDrive #-}
unsafeHasDrive :: (Unbox a, Integral a) => Array a -> Bool
unsafeHasDrive :: forall a. (Unbox a, Integral a) => Array a -> Bool
unsafeHasDrive Array a
a
| Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
1 Array a
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
':' = Bool
False
| Bool -> Bool
not (Char -> Bool
isAlpha (Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
0 Array a
a)) = Bool
False
| Bool
otherwise = Bool
True
hasDrive :: (Unbox a, Integral a) => Array a -> Bool
hasDrive :: forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
a = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 Bool -> Bool -> Bool
&& Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
unsafeHasDrive Array a
a
isDrive :: (Unbox a, Integral a) => Array a -> Bool
isDrive :: forall a. (Unbox a, Integral a) => Array a -> Bool
isDrive Array a
a = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 Bool -> Bool -> Bool
&& Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
unsafeHasDrive Array a
a
isRelativeCurDir :: (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
os Array a
a
| Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Bool
False
| a -> Char
forall a. Integral a => a -> Char
wordToChar (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
a) Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.' = Bool
False
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = Bool
True
| Bool
otherwise = OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
1 Array a
a)
where
len :: Int
len = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a
isRelativeCurDriveRoot :: (Unbox a, Integral a) => Array a -> Bool
isRelativeCurDriveRoot :: forall a. (Unbox a, Integral a) => Array a -> Bool
isRelativeCurDriveRoot Array a
a
| Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Bool
False
| Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& Bool
sep0 = Bool
True
| Bool
sep0 Bool -> Bool -> Bool
&& a
c0 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
c1 = Bool
True
| Bool
otherwise = Bool
False
where
len :: Int
len = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a
c0 :: a
c0 = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
a
c1 :: a
c1 = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
1 Array a
a
sep0 :: Bool
sep0 = OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows a
c0
isRelativeWithDrive :: (Unbox a, Integral a) => Array a -> Bool
isRelativeWithDrive :: forall a. (Unbox a, Integral a) => Array a -> Bool
isRelativeWithDrive Array a
a =
Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
a
Bool -> Bool -> Bool
&& ( Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
3
Bool -> Bool -> Bool
|| Bool -> Bool
not (OS -> Char -> Bool
isSeparator OS
Windows (Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
2 Array a
a))
)
isRootRelative :: (Unbox a, Integral a) => OS -> Array a -> Bool
isRootRelative :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRootRelative OS
Posix Array a
a = OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
Posix Array a
a
isRootRelative OS
Windows Array a
a =
OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
Windows Array a
a
Bool -> Bool -> Bool
|| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isRelativeCurDriveRoot Array a
a
Bool -> Bool -> Bool
|| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isRelativeWithDrive Array a
a
isAbsoluteWithDrive :: (Unbox a, Integral a) => Array a -> Bool
isAbsoluteWithDrive :: forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteWithDrive Array a
a =
Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
3
Bool -> Bool -> Bool
&& Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
unsafeHasDrive Array a
a
Bool -> Bool -> Bool
&& OS -> Char -> Bool
isSeparator OS
Windows (Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
2 Array a
a)
isAbsoluteUNC :: (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC :: forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC Array a
a
| Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = Bool
False
| OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows a
c0 Bool -> Bool -> Bool
&& a
c0 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
c1 = Bool
True
| Bool
otherwise = Bool
False
where
c0 :: a
c0 = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
a
c1 :: a
c1 = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
1 Array a
a
isAbsolute :: (Unbox a, Integral a) => OS -> Array a -> Bool
isAbsolute :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isAbsolute OS
Posix Array a
arr =
OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
hasLeadingSeparator OS
Posix Array a
arr
isAbsolute OS
Windows Array a
arr =
Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteWithDrive Array a
arr Bool -> Bool -> Bool
|| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC Array a
arr
isRooted :: (Unbox a, Integral a) => OS -> Array a -> Bool
isRooted :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRooted OS
Posix Array a
a =
OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
hasLeadingSeparator OS
Posix Array a
a
Bool -> Bool -> Bool
|| OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
Posix Array a
a
isRooted OS
Windows Array a
a =
OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
hasLeadingSeparator OS
Windows Array a
a
Bool -> Bool -> Bool
|| OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
Windows Array a
a
Bool -> Bool -> Bool
|| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
a
isBranch :: (Unbox a, Integral a) => OS -> Array a -> Bool
isBranch :: forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isBranch OS
os = Bool -> Bool
not (Bool -> Bool) -> (Array a -> Bool) -> Array a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRooted OS
os
unsafeSplitPrefix :: (Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix :: forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
os Int
prefixLen Array a
arr =
Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
cnt Array a
arr
where
afterDrive :: Array a
afterDrive = (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
prefixLen Array a
arr
n :: Int
n = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os) Array a
afterDrive
cnt :: Int
cnt = Int
prefixLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n
unsafeSplitTopLevel :: (Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
unsafeSplitTopLevel :: forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
unsafeSplitTopLevel OS
os = OS -> Int -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
os Int
1
unsafeSplitDrive :: (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitDrive :: forall a. (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitDrive = OS -> Int -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
Windows Int
2
parseSegment :: (Unbox a, Integral a) => Array a -> Int -> (Int, Int)
parseSegment :: forall a. (Unbox a, Integral a) => Array a -> Int -> (Int, Int)
parseSegment Array a
arr Int
sepOff = (Int
segOff, Int
segCnt)
where
arr1 :: Array a
arr1 = (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
sepOff Array a
arr
sepCnt :: Int
sepCnt = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows) Array a
arr1
segOff :: Int
segOff = Int
sepOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sepCnt
arr2 :: Array a
arr2 = (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
segOff Array a
arr
segCnt :: Int
segCnt = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows) Array a
arr2
unsafeSplitUNC :: (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitUNC :: forall a. (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitUNC Array a
arr =
if Int
cnt1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
2 Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'?'
then do
if Int
uncLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3
Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
uncOff Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'U'
Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar (Int
uncOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'N'
Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar (Int
uncOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'C'
then OS -> Int -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
Windows (Int
serverOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
serverLen) Array a
arr
else OS -> Int -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
Windows Int
sepOff1 Array a
arr
else OS -> Int -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Int -> Array a -> (Array a, Array a)
unsafeSplitPrefix OS
Windows Int
sepOff Array a
arr
where
arr1 :: Array a
arr1 = (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
2 Array a
arr
cnt1 :: Int
cnt1 = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows) Array a
arr1
sepOff :: Int
sepOff = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
cnt1
(Int
uncOff, Int
uncLen) = Array a -> Int -> (Int, Int)
forall a. (Unbox a, Integral a) => Array a -> Int -> (Int, Int)
parseSegment Array a
arr Int
sepOff
sepOff1 :: Int
sepOff1 = Int
uncOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
uncLen
(Int
serverOff, Int
serverLen) = Array a -> Int -> (Int, Int)
forall a. (Unbox a, Integral a) => Array a -> Int -> (Int, Int)
parseSegment Array a
arr Int
sepOff1
{-# INLINE splitRoot #-}
splitRoot :: (Unbox a, Integral a) => OS -> Array a -> (Array a, Array a)
splitRoot :: forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitRoot OS
Posix Array a
arr
| OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRooted OS
Posix Array a
arr
= OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
unsafeSplitTopLevel OS
Posix Array a
arr
| Bool
otherwise = (Array a
forall a. Array a
Array.empty, Array a
arr)
splitRoot OS
Windows Array a
arr
| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isRelativeCurDriveRoot Array a
arr Bool -> Bool -> Bool
|| OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRelativeCurDir OS
Windows Array a
arr
= OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
unsafeSplitTopLevel OS
Windows Array a
arr
| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
arr = Array a -> (Array a, Array a)
forall a. (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitDrive Array a
arr
| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC Array a
arr = Array a -> (Array a, Array a)
forall a. (Unbox a, Integral a) => Array a -> (Array a, Array a)
unsafeSplitUNC Array a
arr
| Bool
otherwise = (Array a
forall a. Array a
Array.empty, Array a
arr)
{-# INLINE splitWithFilter #-}
splitWithFilter
:: (Unbox a, Integral a, Monad m)
=> ((Int, Int) -> Bool)
-> Bool
-> OS
-> Array a
-> Stream m (Array a)
splitWithFilter :: forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
((Int, Int) -> Bool) -> Bool -> OS -> Array a -> Stream m (Array a)
splitWithFilter (Int, Int) -> Bool
filt Bool
withSep OS
os Array a
arr =
(a -> Bool) -> Stream m a -> Stream m (Int, Int)
forall {a}. (a -> Bool) -> Stream m a -> Stream m (Int, Int)
f (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os) (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read Array a
arr)
Stream m (Int, Int)
-> (Stream m (Int, Int) -> Stream m (Int, Int))
-> Stream m (Int, Int)
forall a b. a -> (a -> b) -> b
& ((Int, Int) -> Bool) -> Stream m (Int, Int) -> Stream m (Int, Int)
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Stream m a -> Stream m a
Stream.filter (Int, Int) -> Bool
filt
Stream m (Int, Int)
-> (Stream m (Int, Int) -> Stream m (Array a))
-> Stream m (Array a)
forall a b. a -> (a -> b) -> b
& ((Int, Int) -> Array a)
-> Stream m (Int, Int) -> Stream m (Array a)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Int
i, Int
len) -> Int -> Int -> Array a -> Array a
forall a. Unbox a => Int -> Int -> Array a -> Array a
Array.unsafeSliceOffLen Int
i Int
len Array a
arr)
where
f :: (a -> Bool) -> Stream m a -> Stream m (Int, Int)
f = if Bool
withSep then (a -> Bool) -> Stream m a -> Stream m (Int, Int)
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Stream m a -> Stream m (Int, Int)
Stream.indexEndBy else (a -> Bool) -> Stream m a -> Stream m (Int, Int)
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Stream m a -> Stream m (Int, Int)
Stream.indexEndBy_
{-# INLINE splitCompact #-}
splitCompact
:: (Unbox a, Integral a, Monad m)
=> Bool
-> OS
-> Array a
-> Stream m (Array a)
splitCompact :: forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitCompact Bool
withSep OS
os Array a
arr =
((Int, Int) -> Bool) -> Bool -> OS -> Array a -> Stream m (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
((Int, Int) -> Bool) -> Bool -> OS -> Array a -> Stream m (Array a)
splitWithFilter (Bool -> Bool
not (Bool -> Bool) -> ((Int, Int) -> Bool) -> (Int, Int) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> Bool
forall {a}. (Num a, Eq a) => (Int, a) -> Bool
shouldFilterOut) Bool
withSep OS
os Array a
arr
where
sepFilter :: (Int, a) -> Bool
sepFilter (Int
off, a
len) =
( a
len a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1
Bool -> Bool -> Bool
&& OS -> Char -> Bool
isSeparator OS
os (Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
off Array a
arr)
)
Bool -> Bool -> Bool
||
( a
len a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
2
Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
off Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.'
Bool -> Bool -> Bool
&& OS -> Char -> Bool
isSeparator OS
os (Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Array a
arr)
)
{-# INLINE shouldFilterOut #-}
shouldFilterOut :: (Int, a) -> Bool
shouldFilterOut (Int
off, a
len) =
a
len a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
Bool -> Bool -> Bool
|| (a
len a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 Bool -> Bool -> Bool
&& Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
off Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.')
Bool -> Bool -> Bool
|| (Bool
withSep Bool -> Bool -> Bool
&& (Int, a) -> Bool
forall {a}. (Num a, Eq a) => (Int, a) -> Bool
sepFilter (Int
off, a
len))
{-# INLINE splitPathUsing #-}
splitPathUsing
:: (Unbox a, Integral a, Monad m)
=> Bool
-> OS
-> Array a
-> Stream m (Array a)
splitPathUsing :: forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitPathUsing Bool
withSep OS
os Array a
arr =
let stream :: Stream m (Array a)
stream = Bool -> OS -> Array a -> Stream m (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitCompact Bool
withSep OS
os Array a
rest
in if Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
root
then Stream m (Array a)
stream
else Array a -> Stream m (Array a) -> Stream m (Array a)
forall (m :: * -> *) a.
Applicative m =>
a -> Stream m a -> Stream m a
Stream.cons Array a
root1 Stream m (Array a)
stream
where
(Array a
root, Array a
rest) = OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitRoot OS
os Array a
arr
root1 :: Array a
root1 =
if Bool
withSep
then (a -> Bool) -> Array a -> Array a
forall a. Unbox a => (a -> Bool) -> Array a -> Array a
compactTrailingBy (OS -> Char -> Bool
isSeparator OS
os (Char -> Bool) -> (a -> Char) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Char
forall a. Integral a => a -> Char
wordToChar) Array a
root
else OS -> Array a -> Array a
forall a. (Unbox a, Integral a) => OS -> Array a -> Array a
dropTrailingSeparators OS
os Array a
root
{-# INLINE splitPath_ #-}
splitPath_
:: (Unbox a, Integral a, Monad m)
=> OS -> Array a -> Stream m (Array a)
splitPath_ :: forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
OS -> Array a -> Stream m (Array a)
splitPath_ = Bool -> OS -> Array a -> Stream m (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitPathUsing Bool
False
{-# INLINE splitPath #-}
splitPath
:: (Unbox a, Integral a, Monad m)
=> OS -> Array a -> Stream m (Array a)
splitPath :: forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
OS -> Array a -> Stream m (Array a)
splitPath = Bool -> OS -> Array a -> Stream m (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitPathUsing Bool
True
{-# INLINE splitHead #-}
splitHead ::
OS -> Array a -> (Array a, Array a)
splitHead :: forall a. OS -> Array a -> (Array a, Array a)
splitHead OS
_os Array a
_arr = (Array a, Array a)
forall a. (?callStack::CallStack) => a
undefined
{-# INLINE splitTail #-}
splitTail ::
OS -> Array a -> (Array a, Array a)
splitTail :: forall a. OS -> Array a -> (Array a, Array a)
splitTail OS
_os Array a
_arr = (Array a, Array a)
forall a. (?callStack::CallStack) => a
undefined
validateFile :: (MonadThrow m, Unbox a, Integral a) => OS -> Array a -> m ()
validateFile :: forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS -> Array a -> m ()
validateFile OS
os Array a
arr = do
[Char]
s1 <-
Stream m Char -> m [Char]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList
(Stream m Char -> m [Char]) -> Stream m Char -> m [Char]
forall a b. (a -> b) -> a -> b
$ Int -> Stream m Char -> Stream m Char
forall (m :: * -> *) a.
Applicative m =>
Int -> Stream m a -> Stream m a
Stream.take Int
3
(Stream m Char -> Stream m Char) -> Stream m Char -> Stream m Char
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Stream m Char -> Stream m Char
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Stream m a -> Stream m a
Stream.takeWhile (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS -> Char -> Bool
isSeparator OS
os)
(Stream m Char -> Stream m Char) -> Stream m Char -> Stream m Char
forall a b. (a -> b) -> a -> b
$ (a -> Char) -> Stream m a -> Stream m Char
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Char
forall a. Integral a => a -> Char
wordToChar
(Stream m a -> Stream m Char) -> Stream m a -> Stream m Char
forall a b. (a -> b) -> a -> b
$ Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.readRev Array a
arr
case [Char]
s1 of
[] -> PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"A file name cannot have a trailing separator"
Char
'.' : [Char]
xs ->
case [Char]
xs of
[] -> PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"A file name cannot have a trailing \".\""
Char
'.' : [] ->
PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"A file name cannot have a trailing \"..\""
[Char]
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
[Char]
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
case OS
os of
OS
Windows ->
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isDrive Array a
arr)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"A drive root is not a valid file name"
OS
Posix -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
{-# INLINE splitFile #-}
splitFile :: (Unbox a, Integral a) => OS -> Array a -> (Array a, Array a)
splitFile :: forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitFile OS
os Array a
arr =
let p :: a -> Bool
p a
x =
if OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
Windows
then a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
':' Bool -> Bool -> Bool
|| OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
x
else OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
x
fileLen :: Int
fileLen = Identity Int -> Int
forall a. Identity a -> a
runIdentity
(Identity Int -> Int) -> Identity Int -> Int
forall a b. (a -> b) -> a -> b
$ Fold Identity a Int -> Stream Identity a -> Identity Int
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
Stream.fold ((a -> Bool) -> Fold Identity a Int -> Fold Identity a Int
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy_ a -> Bool
forall {a}. Integral a => a -> Bool
p Fold Identity a Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length)
(Stream Identity a -> Identity Int)
-> Stream Identity a -> Identity Int
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.readRev Array a
arr
arrLen :: Int
arrLen = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
arr
baseLen :: Int
baseLen = Int
arrLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
fileLen
(Array a
base, Array a
file) = Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
baseLen Array a
arr
fileFirst :: a
fileFirst = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
file
fileSecond :: a
fileSecond = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
1 Array a
file
in
if Int
fileLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
Bool -> Bool -> Bool
&& Bool -> Bool
not (Int
fileLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& a
fileFirst a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
'.')
Bool -> Bool -> Bool
&& Bool -> Bool
not (Int
fileLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2
Bool -> Bool -> Bool
&& a
fileFirst a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
'.'
Bool -> Bool -> Bool
&& a
fileSecond a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
'.')
then
if Int
baseLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then (Array a
forall a. Array a
Array.empty, Array a
arr)
else (Int -> Int -> Array a -> Array a
forall a. Unbox a => Int -> Int -> Array a -> Array a
Array.unsafeSliceOffLen Int
0 Int
baseLen Array a
base, Array a
file)
else (Array a
arr, Array a
forall a. Array a
Array.empty)
{-# INLINE splitDir #-}
splitDir ::
OS -> Array a -> (Array a, Array a)
splitDir :: forall a. OS -> Array a -> (Array a, Array a)
splitDir OS
_os Array a
_arr = (Array a, Array a)
forall a. (?callStack::CallStack) => a
undefined
{-# INLINE splitExtensionBy #-}
splitExtensionBy :: (Unbox a, Integral a) =>
a -> OS -> Array a -> (Array a, Array a)
splitExtensionBy :: forall a.
(Unbox a, Integral a) =>
a -> OS -> Array a -> (Array a, Array a)
splitExtensionBy a
c OS
os Array a
arr =
let p :: a -> Bool
p a
x = a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
c Bool -> Bool -> Bool
|| OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
x
extLen :: Int
extLen = Identity Int -> Int
forall a. Identity a -> a
runIdentity
(Identity Int -> Int) -> Identity Int -> Int
forall a b. (a -> b) -> a -> b
$ Fold Identity a Int -> Stream Identity a -> Identity Int
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
Stream.fold ((a -> Bool) -> Fold Identity a Int -> Fold Identity a Int
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy a -> Bool
p Fold Identity a Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length)
(Stream Identity a -> Identity Int)
-> Stream Identity a -> Identity Int
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.readRev Array a
arr
arrLen :: Int
arrLen = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
arr
baseLen :: Int
baseLen = Int
arrLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
extLen
res :: (Array a, Array a)
res@(Array a
base, Array a
ext) = Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
baseLen Array a
arr
baseLast :: a
baseLast = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndexRev Int
0 Array a
base
extFirst :: a
extFirst = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
ext
in
if Int
arrLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2
Bool -> Bool -> Bool
&& Int
extLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
Bool -> Bool -> Bool
&& a
extFirst a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
c
Bool -> Bool -> Bool
&& Int
baseLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
Bool -> Bool -> Bool
&& Bool -> Bool
not (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
baseLast)
Bool -> Bool -> Bool
&& Bool -> Bool
not (OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
Windows Bool -> Bool -> Bool
&& a
baseLast a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
':')
then (Array a, Array a)
res
else (Array a
arr, Array a
forall a. Array a
Array.empty)
{-# INLINE splitExtension #-}
splitExtension :: (Unbox a, Integral a) => OS -> Array a -> (Array a, Array a)
splitExtension :: forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitExtension = a -> OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
a -> OS -> Array a -> (Array a, Array a)
splitExtensionBy a
forall a. Integral a => a
extensionWord
{-# INLINE isInvalidPathChar #-}
isInvalidPathChar :: Integral a => OS -> a -> Bool
isInvalidPathChar :: forall a. Integral a => OS -> a -> Bool
isInvalidPathChar OS
Posix a
x = a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
isInvalidPathChar OS
Windows a
x =
case a
x of
a
34 -> Bool
True
a
42 -> Bool
True
a
58 -> Bool
True
a
60 -> Bool
True
a
62 -> Bool
True
a
63 -> Bool
True
a
124 -> Bool
True
a
_ -> a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= Char -> a
forall a. Integral a => Char -> a
charToWord Char
'\US'
countLeadingValid :: (Unbox a, Integral a) => OS -> Array a -> Int
countLeadingValid :: forall a. (Unbox a, Integral a) => OS -> Array a -> Int
countLeadingValid OS
os Array a
path =
let f :: Fold Identity a Int
f = (a -> Bool) -> Fold Identity a Int -> Fold Identity a Int
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy_ (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isInvalidPathChar OS
os) Fold Identity a Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length
in Fold Identity a Int -> Array a -> Int
forall a b. Unbox a => Fold Identity a b -> Array a -> b
foldArr Fold Identity a Int
f Array a
path
isInvalidPathComponent :: Integral a => [[a]]
isInvalidPathComponent :: forall a. Integral a => [[a]]
isInvalidPathComponent = ([Char] -> [a]) -> [[Char]] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Char -> a) -> [Char] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> a
forall a. Integral a => Char -> a
charToWord)
[ [Char]
"CON",[Char]
"PRN",[Char]
"AUX",[Char]
"NUL",[Char]
"CLOCK$"
, [Char]
"COM1",[Char]
"COM2",[Char]
"COM3",[Char]
"COM4",[Char]
"COM5",[Char]
"COM6",[Char]
"COM7",[Char]
"COM8",[Char]
"COM9"
, [Char]
"LPT1",[Char]
"LPT2",[Char]
"LPT3",[Char]
"LPT4",[Char]
"LPT5",[Char]
"LPT6",[Char]
"LPT7",[Char]
"LPT8",[Char]
"LPT9"
]
validatePathWith :: (MonadThrow m, Integral a, Unbox a) =>
Bool -> OS -> Array a -> m ()
validatePathWith :: forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
Bool -> OS -> Array a -> m ()
validatePathWith Bool
_ OS
Posix Array a
path =
let pathLen :: Int
pathLen = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
path
validLen :: Int
validLen = OS -> Array a -> Int
forall a. (Unbox a, Integral a) => OS -> Array a -> Int
countLeadingValid OS
Posix Array a
path
in if Int
pathLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"Empty path"
else if Int
pathLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
validLen
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
([Char] -> PathException) -> [Char] -> PathException
forall a b. (a -> b) -> a -> b
$ [Char]
"Null char found after " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
validLen [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" characters."
else () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
validatePathWith Bool
allowRoot OS
Windows Array a
path
| Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
path = PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"Empty path"
| Bool
otherwise = do
if Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
path Bool -> Bool -> Bool
&& Int
postDriveSep Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
[Char]
"More than one separators between drive root and the path"
else if Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC Array a
path
then
if Int
postDriveSep Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
[Char]
"Path starts with more than two separators"
else if Bool
invalidRootComponent
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
[Char]
"Special filename component found in share root"
else if Int
rootEndSeps Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
([Char] -> PathException) -> [Char] -> PathException
forall a b. (a -> b) -> a -> b
$ [Char]
"Share name is needed and exactly one separator is needed "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"after the share root"
else if Bool -> Bool
not Bool
allowRoot Bool -> Bool -> Bool
&& Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
stem
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
[Char]
"the share root must be followed by a non-empty path"
else () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
else () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
if Int
stemLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
validStemLen
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
([Char] -> PathException) -> [Char] -> PathException
forall a b. (a -> b) -> a -> b
$ [Char]
"Disallowed char found after "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Int
rootLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
validStemLen)
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" characters. The invalid char is: "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Char -> [Char]
forall a. Show a => a -> [Char]
show (Int -> Char
chr (Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
invalidVal))
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" [" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Word16 -> [Char]
forall a. Show a => a -> [Char]
show Word16
invalidVal [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
else if Bool
invalidComponent
then PathException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (PathException -> m ()) -> PathException -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath [Char]
"Disallowed Windows filename in path"
else () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
where
postDrive :: Array a
postDrive = (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
2 Array a
path
postDriveSep :: Int
postDriveSep = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countLeadingBy (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows) Array a
postDrive
(Array a
root, Array a
stem) = OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitRoot OS
Windows Array a
path
rootLen :: Int
rootLen = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
root
stemLen :: Int
stemLen = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
stem
validStemLen :: Int
validStemLen = OS -> Array a -> Int
forall a. (Unbox a, Integral a) => OS -> Array a -> Int
countLeadingValid OS
Windows Array a
stem
invalidVal :: Word16
invalidVal = a -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
validStemLen Array a
stem) :: Word16
rootEndSeps :: Int
rootEndSeps = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
Windows) Array a
root
toUp :: a -> a
toUp a
w16 =
if a
w16 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
256
then Char -> a
forall a. Integral a => Char -> a
charToWord (Char -> a) -> Char -> a
forall a b. (a -> b) -> a -> b
$ Char -> Char
toUpper (a -> Char
forall a. Integral a => a -> Char
wordToChar a
w16)
else a
w16
isSpace :: a -> Bool
isSpace a
x = a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
' '
getBaseName :: Array a -> [a]
getBaseName Array a
x =
Identity [a] -> [a]
forall a. Identity a -> a
runIdentity
(Identity [a] -> [a]) -> Identity [a] -> [a]
forall a b. (a -> b) -> a -> b
$ Stream Identity a -> Identity [a]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList
(Stream Identity a -> Identity [a])
-> Stream Identity a -> Identity [a]
forall a b. (a -> b) -> a -> b
$ (a -> a) -> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Integral a => a -> a
toUp
(Stream Identity a -> Stream Identity a)
-> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read
(Array a -> Stream Identity a) -> Array a -> Stream Identity a
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> Array a -> Array a
forall a. Unbox a => (a -> Bool) -> Array a -> Array a
Array.dropAround a -> Bool
forall {a}. Integral a => a -> Bool
isSpace
(Array a -> Array a) -> Array a -> Array a
forall a b. (a -> b) -> a -> b
$ (Array a, Array a) -> Array a
forall a b. (a, b) -> a
fst ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> Array a -> (Array a, Array a)
forall a. Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
Array.breakEndBy_ (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Integral a => a
extensionWord) Array a
x
components :: Array a -> [[a]]
components =
Identity [[a]] -> [[a]]
forall a. Identity a -> a
runIdentity
(Identity [[a]] -> [[a]])
-> (Array a -> Identity [[a]]) -> Array a -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Identity [a] -> Identity [[a]]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList
(Stream Identity [a] -> Identity [[a]])
-> (Array a -> Stream Identity [a]) -> Array a -> Identity [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Array a -> [a])
-> Stream Identity (Array a) -> Stream Identity [a]
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Array a -> [a]
forall {a}. (Integral a, Unbox a) => Array a -> [a]
getBaseName
(Stream Identity (Array a) -> Stream Identity [a])
-> (Array a -> Stream Identity (Array a))
-> Array a
-> Stream Identity [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> OS -> Array a -> Stream Identity (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
Bool -> OS -> Array a -> Stream m (Array a)
splitCompact Bool
False OS
Windows
invalidRootComponent :: Bool
invalidRootComponent =
([a] -> Bool) -> [[a]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
List.any ([a] -> [[a]] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`List.elem` [[a]]
forall a. Integral a => [[a]]
isInvalidPathComponent) (Array a -> [[a]]
components Array a
root)
invalidComponent :: Bool
invalidComponent =
([a] -> Bool) -> [[a]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
List.any ([a] -> [[a]] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`List.elem` [[a]]
forall a. Integral a => [[a]]
isInvalidPathComponent) (Array a -> [[a]]
components Array a
stem)
{-# INLINE validatePath #-}
validatePath :: (MonadThrow m, Integral a, Unbox a) => OS -> Array a -> m ()
validatePath :: forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath = Bool -> OS -> Array a -> m ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
Bool -> OS -> Array a -> m ()
validatePathWith Bool
True
{-# INLINE validatePath' #-}
validatePath' :: (MonadThrow m, Integral a, Unbox a) => OS -> Array a -> m ()
validatePath' :: forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath' = Bool -> OS -> Array a -> m ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
Bool -> OS -> Array a -> m ()
validatePathWith Bool
False
{-# INLINE isValidPath #-}
isValidPath :: (Integral a, Unbox a) => OS -> Array a -> Bool
isValidPath :: forall a. (Integral a, Unbox a) => OS -> Array a -> Bool
isValidPath OS
os Array a
path =
case OS -> Array a -> Maybe ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath OS
os Array a
path of
Maybe ()
Nothing -> Bool
False
Just ()
_ -> Bool
True
{-# INLINE isValidPath' #-}
isValidPath' :: (Integral a, Unbox a) => OS -> Array a -> Bool
isValidPath' :: forall a. (Integral a, Unbox a) => OS -> Array a -> Bool
isValidPath' OS
os Array a
path =
case OS -> Array a -> Maybe ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath' OS
os Array a
path of
Maybe ()
Nothing -> Bool
False
Just ()
_ -> Bool
True
{-# INLINE unsafeFromChunk #-}
unsafeFromChunk :: Array Word8 -> Array a
unsafeFromChunk :: forall a. Array Word8 -> Array a
unsafeFromChunk = Array Word8 -> Array a
forall a b. Array a -> Array b
Array.unsafeCast
{-# INLINE fromChunk #-}
fromChunk :: forall m a. (MonadThrow m, Unbox a, Integral a) =>
OS -> Array Word8 -> m (Array a)
fromChunk :: forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS -> Array Word8 -> m (Array a)
fromChunk OS
Posix Array Word8
arr =
let arr1 :: Array a
arr1 = Array Word8 -> Array a
forall a b. Array a -> Array b
Array.unsafeCast Array Word8
arr :: Array a
in OS -> Array a -> m ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath OS
Posix Array a
arr1 m () -> m (Array a) -> m (Array a)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Array a -> m (Array a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array a
arr1
fromChunk OS
Windows Array Word8
arr =
case Array Word8 -> Maybe (Array a)
forall a b. Unbox b => Array a -> Maybe (Array b)
Array.cast Array Word8
arr of
Maybe (Array a)
Nothing ->
PathException -> m (Array a)
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM
(PathException -> m (Array a)) -> PathException -> m (Array a)
forall a b. (a -> b) -> a -> b
$ [Char] -> PathException
InvalidPath
([Char] -> PathException) -> [Char] -> PathException
forall a b. (a -> b) -> a -> b
$ [Char]
"Encoded path length " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Array Word8 -> Int
forall a. Array a -> Int
Array.byteLength Array Word8
arr)
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" is not a multiple of 16-bit."
Just Array a
x -> OS -> Array a -> m ()
forall (m :: * -> *) a.
(MonadThrow m, Integral a, Unbox a) =>
OS -> Array a -> m ()
validatePath OS
Windows Array a
x m () -> m (Array a) -> m (Array a)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Array a -> m (Array a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array a
x
{-# INLINE toChunk #-}
toChunk :: Array a -> Array Word8
toChunk :: forall a. Array a -> Array Word8
toChunk = Array a -> Array Word8
forall a. Array a -> Array Word8
Array.asBytes
{-# INLINE unsafeFromChars #-}
unsafeFromChars :: (Unbox a) =>
(Stream Identity Char -> Stream Identity a)
-> Stream Identity Char
-> Array a
unsafeFromChars :: forall a.
Unbox a =>
(Stream Identity Char -> Stream Identity a)
-> Stream Identity Char -> Array a
unsafeFromChars Stream Identity Char -> Stream Identity a
encode Stream Identity Char
s =
let n :: Int
n = Identity Int -> Int
forall a. Identity a -> a
runIdentity (Identity Int -> Int) -> Identity Int -> Int
forall a b. (a -> b) -> a -> b
$ Fold Identity Char Int -> Stream Identity Char -> Identity Int
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
Stream.fold Fold Identity Char Int
forall (m :: * -> *) a. Monad m => Fold m a Int
Fold.length Stream Identity Char
s
in Int -> Stream Identity a -> Array a
forall a. Unbox a => Int -> Stream Identity a -> Array a
Array.fromPureStreamN Int
n (Stream Identity Char -> Stream Identity a
encode Stream Identity Char
s)
{-# INLINE fromChars #-}
fromChars :: (MonadThrow m, Unbox a, Integral a) =>
OS
-> (Stream Identity Char -> Stream Identity a)
-> Stream Identity Char
-> m (Array a)
fromChars :: forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS
-> (Stream Identity Char -> Stream Identity a)
-> Stream Identity Char
-> m (Array a)
fromChars OS
os Stream Identity Char -> Stream Identity a
encode Stream Identity Char
s =
let arr :: Array a
arr = (Stream Identity Char -> Stream Identity a)
-> Stream Identity Char -> Array a
forall a.
Unbox a =>
(Stream Identity Char -> Stream Identity a)
-> Stream Identity Char -> Array a
unsafeFromChars Stream Identity Char -> Stream Identity a
encode Stream Identity Char
s
in OS -> Array Word8 -> m (Array a)
forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS -> Array Word8 -> m (Array a)
fromChunk OS
os (Array a -> Array Word8
forall a b. Array a -> Array b
Array.unsafeCast Array a
arr)
{-# INLINE toChars #-}
toChars :: (Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
toChars :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
toChars Stream m a -> Stream m Char
decode Array a
arr = Stream m a -> Stream m Char
decode (Stream m a -> Stream m Char) -> Stream m a -> Stream m Char
forall a b. (a -> b) -> a -> b
$ Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read Array a
arr
{-# INLINE toString #-}
toString :: Unbox a =>
(Stream Identity a -> Stream Identity Char) -> Array a -> [Char]
toString :: forall a.
Unbox a =>
(Stream Identity a -> Stream Identity Char) -> Array a -> [Char]
toString Stream Identity a -> Stream Identity Char
decode = Identity [Char] -> [Char]
forall a. Identity a -> a
runIdentity (Identity [Char] -> [Char])
-> (Array a -> Identity [Char]) -> Array a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Identity Char -> Identity [Char]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList (Stream Identity Char -> Identity [Char])
-> (Array a -> Stream Identity Char) -> Array a -> Identity [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stream Identity a -> Stream Identity Char)
-> Array a -> Stream Identity Char
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
toChars Stream Identity a -> Stream Identity Char
decode
mkQ :: (String -> Q Exp) -> QuasiQuoter
mkQ :: ([Char] -> Q Exp) -> QuasiQuoter
mkQ [Char] -> Q Exp
f =
QuasiQuoter
{ quoteExp :: [Char] -> Q Exp
quoteExp = [Char] -> Q Exp
f
, quotePat :: [Char] -> Q Pat
quotePat = [Char] -> [Char] -> Q Pat
forall {m :: * -> *} {p} {a}. MonadFail m => [Char] -> p -> m a
err [Char]
"pattern"
, quoteType :: [Char] -> Q Type
quoteType = [Char] -> [Char] -> Q Type
forall {m :: * -> *} {p} {a}. MonadFail m => [Char] -> p -> m a
err [Char]
"type"
, quoteDec :: [Char] -> Q [Dec]
quoteDec = [Char] -> [Char] -> Q [Dec]
forall {m :: * -> *} {p} {a}. MonadFail m => [Char] -> p -> m a
err [Char]
"declaration"
}
where
err :: [Char] -> p -> m a
err [Char]
x p
_ = [Char] -> m a
forall a. [Char] -> m a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> m a) -> [Char] -> m a
forall a b. (a -> b) -> a -> b
$ [Char]
"QuasiQuote used as a " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", can be used only as an expression"
foreign import ccall unsafe "string.h strlen" c_strlen_pinned
:: Addr# -> IO CSize
{-# INLINE appendCStringWith #-}
appendCStringWith ::
(Int -> IO (MutArray Word8))
-> OS
-> Array Word8
-> CString
-> IO (Array Word8)
appendCStringWith :: (Int -> IO (MutArray Word8))
-> OS -> Array Word8 -> CString -> IO (Array Word8)
appendCStringWith Int -> IO (MutArray Word8)
create OS
os Array Word8
a b :: CString
b@(Ptr Addr#
addrB#) = do
let lenA :: Int
lenA = Array Word8 -> Int
forall a. Unbox a => Array a -> Int
Array.length Array Word8
a
Int
lenB <- (CSize -> Int) -> IO CSize -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CSize -> IO Int) -> IO CSize -> IO Int
forall a b. (a -> b) -> a -> b
$ Addr# -> IO CSize
c_strlen_pinned Addr#
addrB#
assertM(Int
lenA Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Int
lenB Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0)
let len :: Int
len = Int
lenA Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lenB
MutArray Word8
arr <- Int -> IO (MutArray Word8)
create Int
len
MutArray Word8
arr1 <- MutArray Word8 -> MutArray Word8 -> IO (MutArray Word8)
forall (m :: * -> *) a.
MonadIO m =>
MutArray a -> MutArray a -> m (MutArray a)
MutArray.unsafeSplice MutArray Word8
arr (Array Word8 -> MutArray Word8
forall a. Array a -> MutArray a
Array.unsafeThaw Array Word8
a)
MutArray Word8
arr2 <- MutArray Word8 -> Word8 -> IO (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> a -> m (MutArray a)
MutArray.unsafeSnoc MutArray Word8
arr1 (Char -> Word8
forall a. Integral a => Char -> a
charToWord (OS -> Char
primarySeparator OS
os))
MutArray Word8
arr3 :: MutArray.MutArray Word8 <-
MutArray Word8 -> Ptr Word8 -> Int -> IO (MutArray Word8)
forall (m :: * -> *).
MonadIO m =>
MutArray Word8 -> Ptr Word8 -> Int -> m (MutArray Word8)
MutArray.unsafeAppendPtrN MutArray Word8
arr2 (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
b) Int
lenB
Array Word8 -> IO (Array Word8)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutArray Word8 -> Array Word8
forall a. MutArray a -> Array a
Array.unsafeFreeze MutArray Word8
arr3)
{-# INLINE appendCString #-}
appendCString :: OS -> Array Word8 -> CString -> IO (Array Word8)
appendCString :: OS -> Array Word8 -> CString -> IO (Array Word8)
appendCString = (Int -> IO (MutArray Word8))
-> OS -> Array Word8 -> CString -> IO (Array Word8)
appendCStringWith Int -> IO (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> m (MutArray a)
MutArray.emptyOf
{-# INLINE appendCString' #-}
appendCString' :: OS -> Array Word8 -> CString -> IO (Array Word8)
appendCString' :: OS -> Array Word8 -> CString -> IO (Array Word8)
appendCString' = (Int -> IO (MutArray Word8))
-> OS -> Array Word8 -> CString -> IO (Array Word8)
appendCStringWith Int -> IO (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> m (MutArray a)
MutArray.emptyOf'
{-# INLINE doAppend #-}
doAppend :: (Unbox a, Integral a) => OS -> Array a -> Array a -> Array a
doAppend :: forall a.
(Unbox a, Integral a) =>
OS -> Array a -> Array a -> Array a
doAppend OS
os Array a
a Array a
b = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
let lenA :: Int
lenA = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
a
lenB :: Int
lenB = Array a -> Int
forall a. Unbox a => Array a -> Int
Array.length Array a
b
assertM(Int
lenA Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Int
lenB Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0)
let lastA :: a
lastA = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndexRev Int
0 Array a
a
sepA :: Bool
sepA = OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os a
lastA
sepB :: Bool
sepB = OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
Array.unsafeGetIndex Int
0 Array a
b)
let len :: Int
len = Int
lenA Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lenB
MutArray a
arr <- Int -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> m (MutArray a)
MutArray.emptyOf Int
len
MutArray a
arr1 <- MutArray a -> MutArray a -> IO (MutArray a)
forall (m :: * -> *) a.
MonadIO m =>
MutArray a -> MutArray a -> m (MutArray a)
MutArray.unsafeSplice MutArray a
arr (Array a -> MutArray a
forall a. Array a -> MutArray a
Array.unsafeThaw Array a
a)
MutArray a
arr2 <-
if Int
lenA Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
Bool -> Bool -> Bool
&& Int
lenB Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
sepA
Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
sepB
Bool -> Bool -> Bool
&& Bool -> Bool
not (OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
Windows Bool -> Bool -> Bool
&& a
lastA a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> a
forall a. Integral a => Char -> a
charToWord Char
':')
then MutArray a -> a -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> a -> m (MutArray a)
MutArray.unsafeSnoc MutArray a
arr1 (Char -> a
forall a. Integral a => Char -> a
charToWord (OS -> Char
primarySeparator OS
os))
else MutArray a -> IO (MutArray a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure MutArray a
arr1
let arrB :: Array a
arrB =
if Bool
sepA Bool -> Bool -> Bool
&& Bool
sepB
then (Array a, Array a) -> Array a
forall a b. (a, b) -> b
snd ((Array a, Array a) -> Array a) -> (Array a, Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> (Array a, Array a)
forall a. Unbox a => Int -> Array a -> (Array a, Array a)
Array.unsafeBreakAt Int
1 Array a
b
else Array a
b
MutArray a
arr3 <- MutArray a -> MutArray a -> IO (MutArray a)
forall (m :: * -> *) a.
MonadIO m =>
MutArray a -> MutArray a -> m (MutArray a)
MutArray.unsafeSplice MutArray a
arr2 (Array a -> MutArray a
forall a. Array a -> MutArray a
Array.unsafeThaw Array a
arrB)
Array a -> IO (Array a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutArray a -> Array a
forall a. MutArray a -> Array a
Array.unsafeFreeze MutArray a
arr3)
{-# INLINE withAppendCheck #-}
withAppendCheck :: (Unbox b, Integral b) =>
OS -> (Array b -> String) -> Array b -> a -> a
withAppendCheck :: forall b a.
(Unbox b, Integral b) =>
OS -> (Array b -> [Char]) -> Array b -> a -> a
withAppendCheck OS
os Array b -> [Char]
toStr Array b
arr a
f =
if OS -> Array b -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRooted OS
os Array b
arr
then [Char] -> a
forall a. (?callStack::CallStack) => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"append: cannot append a rooted path " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Array b -> [Char]
toStr Array b
arr
else a
f
{-# INLINE unsafeAppend #-}
unsafeAppend :: (Unbox a, Integral a) =>
OS -> (Array a -> String) -> Array a -> Array a -> Array a
unsafeAppend :: forall a.
(Unbox a, Integral a) =>
OS -> (Array a -> [Char]) -> Array a -> Array a -> Array a
unsafeAppend OS
os Array a -> [Char]
_toStr = OS -> Array a -> Array a -> Array a
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> Array a -> Array a
doAppend OS
os
{-# INLINE append #-}
append :: (Unbox a, Integral a) =>
OS -> (Array a -> String) -> Array a -> Array a -> Array a
append :: forall a.
(Unbox a, Integral a) =>
OS -> (Array a -> [Char]) -> Array a -> Array a -> Array a
append OS
os Array a -> [Char]
toStr Array a
a Array a
b = OS -> (Array a -> [Char]) -> Array a -> Array a -> Array a
forall b a.
(Unbox b, Integral b) =>
OS -> (Array b -> [Char]) -> Array b -> a -> a
withAppendCheck OS
os Array a -> [Char]
toStr Array a
b (OS -> Array a -> Array a -> Array a
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> Array a -> Array a
doAppend OS
os Array a
a Array a
b)
{-# INLINE append' #-}
append' :: (Unbox a, Integral a) =>
OS -> (Array a -> String) -> Array a -> Array a -> Array a
append' :: forall a.
(Unbox a, Integral a) =>
OS -> (Array a -> [Char]) -> Array a -> Array a -> Array a
append' OS
os Array a -> [Char]
toStr Array a
a Array a
b =
let hasSep :: Bool
hasSep = (a -> Bool) -> Array a -> Int
forall a. Unbox a => (a -> Bool) -> Array a -> Int
countTrailingBy (OS -> a -> Bool
forall a. Integral a => OS -> a -> Bool
isSeparatorWord OS
os) Array a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
hasColon :: Bool
hasColon =
OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== OS
Windows
Bool -> Bool -> Bool
&& Int -> Array a -> Maybe a
forall a. Unbox a => Int -> Array a -> Maybe a
Array.getIndexRev Int
0 Array a
a Maybe a -> Maybe a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Maybe a
forall a. a -> Maybe a
Just (Char -> a
forall a. Integral a => Char -> a
charToWord Char
':')
in if Bool
hasSep Bool -> Bool -> Bool
|| Bool
hasColon
then OS -> (Array a -> [Char]) -> Array a -> Array a -> Array a
forall b a.
(Unbox b, Integral b) =>
OS -> (Array b -> [Char]) -> Array b -> a -> a
withAppendCheck OS
os Array a -> [Char]
toStr Array a
b (OS -> Array a -> Array a -> Array a
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> Array a -> Array a
doAppend OS
os Array a
a Array a
b)
else [Char] -> Array a
forall a. (?callStack::CallStack) => [Char] -> a
error
([Char] -> Array a) -> [Char] -> Array a
forall a b. (a -> b) -> a -> b
$ [Char]
"append': first path must be dir like i.e. must have a "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"trailing separator or colon on windows: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Array a -> [Char]
toStr Array a
a
{-# INLINE unsafeJoinPaths #-}
unsafeJoinPaths
:: (Unbox a, Integral a, MonadIO m)
=> OS -> Stream m (Array a) -> m (Array a)
unsafeJoinPaths :: forall a (m :: * -> *).
(Unbox a, Integral a, MonadIO m) =>
OS -> Stream m (Array a) -> m (Array a)
unsafeJoinPaths OS
os =
Stream m a -> m (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (Array a)
Array.fromStream (Stream m a -> m (Array a))
-> (Stream m (Array a) -> Stream m a)
-> Stream m (Array a)
-> m (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Stream m (Array a) -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
a -> Stream m (Array a) -> Stream m a
Array.concatSepBy (Char -> a
forall a. Integral a => Char -> a
charToWord (Char -> a) -> Char -> a
forall a b. (a -> b) -> a -> b
$ OS -> Char
primarySeparator OS
os)
eqPathBytes :: Array a -> Array a -> Bool
eqPathBytes :: forall a. Array a -> Array a -> Bool
eqPathBytes = Array a -> Array a -> Bool
forall a. Array a -> Array a -> Bool
Array.byteEq
data EqCfg =
EqCfg
{ EqCfg -> Bool
ignoreTrailingSeparators :: Bool
, EqCfg -> Bool
ignoreCase :: Bool
, EqCfg -> Bool
allowRelativeEquality :: Bool
}
eqCfg :: EqCfg
eqCfg :: EqCfg
eqCfg = EqCfg
{ ignoreTrailingSeparators :: Bool
ignoreTrailingSeparators = Bool
False
, ignoreCase :: Bool
ignoreCase = Bool
False
, allowRelativeEquality :: Bool
allowRelativeEquality = Bool
False
}
data PosixRoot = PosixRootAbs | PosixRootRel deriving PosixRoot -> PosixRoot -> Bool
(PosixRoot -> PosixRoot -> Bool)
-> (PosixRoot -> PosixRoot -> Bool) -> Eq PosixRoot
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PosixRoot -> PosixRoot -> Bool
== :: PosixRoot -> PosixRoot -> Bool
$c/= :: PosixRoot -> PosixRoot -> Bool
/= :: PosixRoot -> PosixRoot -> Bool
Eq
data WindowsRoot =
WindowsRootPosix
| WindowsRootNonPosix
deriving WindowsRoot -> WindowsRoot -> Bool
(WindowsRoot -> WindowsRoot -> Bool)
-> (WindowsRoot -> WindowsRoot -> Bool) -> Eq WindowsRoot
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WindowsRoot -> WindowsRoot -> Bool
== :: WindowsRoot -> WindowsRoot -> Bool
$c/= :: WindowsRoot -> WindowsRoot -> Bool
/= :: WindowsRoot -> WindowsRoot -> Bool
Eq
{-# INLINE normalizeCaseAndSeparators #-}
normalizeCaseAndSeparators :: Monad m => Array Word16 -> Stream m Char
normalizeCaseAndSeparators :: forall (m :: * -> *). Monad m => Array Word16 -> Stream m Char
normalizeCaseAndSeparators =
(Char -> Char) -> Stream m Char -> Stream m Char
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> Char
toUpper
(Stream m Char -> Stream m Char)
-> (Array Word16 -> Stream m Char) -> Array Word16 -> Stream m Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream m Word16 -> Stream m Char
forall (m :: * -> *). Monad m => Stream m Word16 -> Stream m Char
Unicode.decodeUtf16le'
(Stream m Word16 -> Stream m Char)
-> (Array Word16 -> Stream m Word16)
-> Array Word16
-> Stream m Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word16 -> Word16) -> Stream m Word16 -> Stream m Word16
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word16 -> Word16
forall a. Integral a => a -> a
toDefaultSeparator
(Stream m Word16 -> Stream m Word16)
-> (Array Word16 -> Stream m Word16)
-> Array Word16
-> Stream m Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array Word16 -> Stream m Word16
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read
{-# INLINE normalizeCaseWith #-}
normalizeCaseWith :: (Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
normalizeCaseWith :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
normalizeCaseWith Stream m a -> Stream m Char
decoder =
(Char -> Char) -> Stream m Char -> Stream m Char
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> Char
toUpper
(Stream m Char -> Stream m Char)
-> (Array a -> Stream m Char) -> Array a -> Stream m Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream m a -> Stream m Char
decoder
(Stream m a -> Stream m Char)
-> (Array a -> Stream m a) -> Array a -> Stream m Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read
eqWindowsRootStrict :: (Unbox a, Integral a) =>
Bool -> Array a -> Array a -> Bool
eqWindowsRootStrict :: forall a.
(Unbox a, Integral a) =>
Bool -> Array a -> Array a -> Bool
eqWindowsRootStrict Bool
ignCase Array a
a Array a
b =
let f :: Array Word16 -> Stream Identity Char
f = Array Word16 -> Stream Identity Char
forall (m :: * -> *). Monad m => Array Word16 -> Stream m Char
normalizeCaseAndSeparators
in if Bool
ignCase
then
Identity Bool -> Bool
forall a. Identity a -> a
runIdentity
(Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Char -> Char -> Bool)
-> Stream Identity Char -> Stream Identity Char -> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
Stream.eqBy Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
(==)
(Array Word16 -> Stream Identity Char
f (Array Word16 -> Stream Identity Char)
-> Array Word16 -> Stream Identity Char
forall a b. (a -> b) -> a -> b
$ Array a -> Array Word16
forall a b. Array a -> Array b
Array.unsafeCast Array a
a) (Array Word16 -> Stream Identity Char
f (Array Word16 -> Stream Identity Char)
-> Array Word16 -> Stream Identity Char
forall a b. (a -> b) -> a -> b
$ Array a -> Array Word16
forall a b. Array a -> Array b
Array.unsafeCast Array a
b)
else
Identity Bool -> Bool
forall a. Identity a -> a
runIdentity
(Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> a -> Bool)
-> Stream Identity a -> Stream Identity a -> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
Stream.eqBy a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
((a -> a) -> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Integral a => a -> a
toDefaultSeparator (Stream Identity a -> Stream Identity a)
-> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read Array a
a)
((a -> a) -> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Integral a => a -> a
toDefaultSeparator (Stream Identity a -> Stream Identity a)
-> Stream Identity a -> Stream Identity a
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
Array.read Array a
b)
{-# INLINE eqRootStrict #-}
eqRootStrict :: (Unbox a, Integral a) =>
Bool -> OS -> Array a -> Array a -> Bool
eqRootStrict :: forall a.
(Unbox a, Integral a) =>
Bool -> OS -> Array a -> Array a -> Bool
eqRootStrict Bool
_ OS
Posix Array a
a Array a
b =
Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
b
eqRootStrict Bool
ignCase OS
Windows Array a
a Array a
b = Bool -> Array a -> Array a -> Bool
forall a.
(Unbox a, Integral a) =>
Bool -> Array a -> Array a -> Bool
eqWindowsRootStrict Bool
ignCase Array a
a Array a
b
{-# INLINE eqPosixRootLax #-}
eqPosixRootLax :: (Unbox a, Integral a) => Array a -> Array a -> Bool
eqPosixRootLax :: forall a. (Unbox a, Integral a) => Array a -> Array a -> Bool
eqPosixRootLax Array a
a Array a
b = Array a -> PosixRoot
forall {a}. (Unbox a, Integral a) => Array a -> PosixRoot
getRoot Array a
a PosixRoot -> PosixRoot -> Bool
forall a. Eq a => a -> a -> Bool
== Array a -> PosixRoot
forall {a}. (Unbox a, Integral a) => Array a -> PosixRoot
getRoot Array a
b
where
getRoot :: Array a -> PosixRoot
getRoot Array a
arr =
if Array a -> Bool
forall a. Array a -> Bool
Array.null Array a
arr Bool -> Bool -> Bool
|| Int -> Array a -> Char
forall a. (Unbox a, Integral a) => Int -> Array a -> Char
unsafeIndexChar Int
0 Array a
arr Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.'
then PosixRoot
PosixRootRel
else PosixRoot
PosixRootAbs
{-# INLINABLE eqRootLax #-}
eqRootLax :: (Unbox a, Integral a) => Bool -> OS -> Array a -> Array a -> Bool
eqRootLax :: forall a.
(Unbox a, Integral a) =>
Bool -> OS -> Array a -> Array a -> Bool
eqRootLax Bool
_ OS
Posix Array a
a Array a
b = Array a -> Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Array a -> Bool
eqPosixRootLax Array a
a Array a
b
eqRootLax Bool
ignCase OS
Windows Array a
a Array a
b =
let aType :: WindowsRoot
aType = Array a -> WindowsRoot
forall {a}. (Unbox a, Integral a) => Array a -> WindowsRoot
getRootType Array a
a
bType :: WindowsRoot
bType = Array a -> WindowsRoot
forall {a}. (Unbox a, Integral a) => Array a -> WindowsRoot
getRootType Array a
b
in WindowsRoot
aType WindowsRoot -> WindowsRoot -> Bool
forall a. Eq a => a -> a -> Bool
== WindowsRoot
bType
Bool -> Bool -> Bool
&& (
(WindowsRoot
aType WindowsRoot -> WindowsRoot -> Bool
forall a. Eq a => a -> a -> Bool
== WindowsRoot
WindowsRootPosix Bool -> Bool -> Bool
&& Array a -> Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Array a -> Bool
eqPosixRootLax Array a
a Array a
b)
Bool -> Bool -> Bool
|| Bool -> Array a -> Array a -> Bool
forall a.
(Unbox a, Integral a) =>
Bool -> Array a -> Array a -> Bool
eqWindowsRootStrict Bool
ignCase Array a
a Array a
b
)
where
getRootType :: Array a -> WindowsRoot
getRootType Array a
arr =
if Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
isAbsoluteUNC Array a
arr Bool -> Bool -> Bool
|| Array a -> Bool
forall a. (Unbox a, Integral a) => Array a -> Bool
hasDrive Array a
arr
then WindowsRoot
WindowsRootNonPosix
else WindowsRoot
WindowsRootPosix
{-# INLINE eqComponentsWith #-}
eqComponentsWith :: (Unbox a, Integral a) =>
Bool
-> (Stream Identity a -> Stream Identity Char)
-> OS
-> Array a
-> Array a
-> Bool
eqComponentsWith :: forall a.
(Unbox a, Integral a) =>
Bool
-> (Stream Identity a -> Stream Identity Char)
-> OS
-> Array a
-> Array a
-> Bool
eqComponentsWith Bool
ignCase Stream Identity a -> Stream Identity Char
decoder OS
os Array a
a Array a
b =
if Bool
ignCase
then
let streamEq :: Stream Identity b -> Stream Identity b -> Bool
streamEq Stream Identity b
x Stream Identity b
y = Identity Bool -> Bool
forall a. Identity a -> a
runIdentity (Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (b -> b -> Bool)
-> Stream Identity b -> Stream Identity b -> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
Stream.eqBy b -> b -> Bool
forall a. Eq a => a -> a -> Bool
(==) Stream Identity b
x Stream Identity b
y
toComponents :: Array a -> Stream Identity (Stream Identity Char)
toComponents = (Array a -> Stream Identity Char)
-> Stream Identity (Array a)
-> Stream Identity (Stream Identity Char)
forall a b. (a -> b) -> Stream Identity a -> Stream Identity b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Stream Identity a -> Stream Identity Char)
-> Array a -> Stream Identity Char
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
normalizeCaseWith Stream Identity a -> Stream Identity Char
decoder) (Stream Identity (Array a)
-> Stream Identity (Stream Identity Char))
-> (Array a -> Stream Identity (Array a))
-> Array a
-> Stream Identity (Stream Identity Char)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS -> Array a -> Stream Identity (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
OS -> Array a -> Stream m (Array a)
splitPath_ OS
os
in Identity Bool -> Bool
forall a. Identity a -> a
runIdentity
(Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Stream Identity Char -> Stream Identity Char -> Bool)
-> Stream Identity (Stream Identity Char)
-> Stream Identity (Stream Identity Char)
-> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
Stream.eqBy Stream Identity Char -> Stream Identity Char -> Bool
forall {b}. Eq b => Stream Identity b -> Stream Identity b -> Bool
streamEq (Array a -> Stream Identity (Stream Identity Char)
toComponents Array a
a) (Array a -> Stream Identity (Stream Identity Char)
toComponents Array a
b)
else
Identity Bool -> Bool
forall a. Identity a -> a
runIdentity
(Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Array a -> Array a -> Bool)
-> Stream Identity (Array a)
-> Stream Identity (Array a)
-> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
Stream.eqBy
Array a -> Array a -> Bool
forall a. Array a -> Array a -> Bool
Array.byteEq (OS -> Array a -> Stream Identity (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
OS -> Array a -> Stream m (Array a)
splitPath_ OS
os Array a
a) (OS -> Array a -> Stream Identity (Array a)
forall a (m :: * -> *).
(Unbox a, Integral a, Monad m) =>
OS -> Array a -> Stream m (Array a)
splitPath_ OS
os Array a
b)
{-# INLINE eqPathWith #-}
eqPathWith :: (Unbox a, Integral a) =>
(Stream Identity a -> Stream Identity Char)
-> OS -> EqCfg -> Array a -> Array a -> Bool
eqPathWith :: forall a.
(Unbox a, Integral a) =>
(Stream Identity a -> Stream Identity Char)
-> OS -> EqCfg -> Array a -> Array a -> Bool
eqPathWith Stream Identity a -> Stream Identity Char
decoder OS
os EqCfg{Bool
ignoreTrailingSeparators :: EqCfg -> Bool
ignoreCase :: EqCfg -> Bool
allowRelativeEquality :: EqCfg -> Bool
ignoreTrailingSeparators :: Bool
ignoreCase :: Bool
allowRelativeEquality :: Bool
..} Array a
a Array a
b =
let (Array a
rootA, Array a
stemA) = OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitRoot OS
os Array a
a
(Array a
rootB, Array a
stemB) = OS -> Array a -> (Array a, Array a)
forall a.
(Unbox a, Integral a) =>
OS -> Array a -> (Array a, Array a)
splitRoot OS
os Array a
b
eqRelative :: Bool
eqRelative =
if Bool
allowRelativeEquality
then Bool -> OS -> Array a -> Array a -> Bool
forall a.
(Unbox a, Integral a) =>
Bool -> OS -> Array a -> Array a -> Bool
eqRootLax Bool
ignoreCase OS
os Array a
rootA Array a
rootB
else (Bool -> Bool
not (OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRootRelative OS
os Array a
rootA)
Bool -> Bool -> Bool
&& Bool -> Bool
not (OS -> Array a -> Bool
forall a. (Unbox a, Integral a) => OS -> Array a -> Bool
isRootRelative OS
os Array a
rootB))
Bool -> Bool -> Bool
&& Bool -> OS -> Array a -> Array a -> Bool
forall a.
(Unbox a, Integral a) =>
Bool -> OS -> Array a -> Array a -> Bool
eqRootStrict Bool
ignoreCase OS
os Array a
rootA Array a
rootB
eqTrailingSep :: Bool
eqTrailingSep =
Bool
ignoreTrailingSeparators
Bool -> Bool -> Bool
|| OS -> Array a -> Bool
forall a. (Integral a, Unbox a) => OS -> Array a -> Bool
hasTrailingSeparator OS
os Array a
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== OS -> Array a -> Bool
forall a. (Integral a, Unbox a) => OS -> Array a -> Bool
hasTrailingSeparator OS
os Array a
b
in
Bool
eqRelative
Bool -> Bool -> Bool
&& Bool
eqTrailingSep
Bool -> Bool -> Bool
&& Bool
-> (Stream Identity a -> Stream Identity Char)
-> OS
-> Array a
-> Array a
-> Bool
forall a.
(Unbox a, Integral a) =>
Bool
-> (Stream Identity a -> Stream Identity Char)
-> OS
-> Array a
-> Array a
-> Bool
eqComponentsWith Bool
ignoreCase Stream Identity a -> Stream Identity Char
decoder OS
os Array a
stemA Array a
stemB
{-# INLINE eqPath #-}
eqPath :: (Unbox a, Integral a) =>
(Stream Identity a -> Stream Identity Char)
-> OS -> Array a -> Array a -> Bool
eqPath :: forall a.
(Unbox a, Integral a) =>
(Stream Identity a -> Stream Identity Char)
-> OS -> Array a -> Array a -> Bool
eqPath Stream Identity a -> Stream Identity Char
decoder OS
os = (Stream Identity a -> Stream Identity Char)
-> OS -> EqCfg -> Array a -> Array a -> Bool
forall a.
(Unbox a, Integral a) =>
(Stream Identity a -> Stream Identity Char)
-> OS -> EqCfg -> Array a -> Array a -> Bool
eqPathWith Stream Identity a -> Stream Identity Char
decoder OS
os EqCfg
eqCfg