{-# LANGUAGE FlexibleInstances #-} module System.Linux.Btrfs.FilePathLike ( FilePathLike(..) , RawFilePath ) where import Data.String import Data.Monoid import Data.List (dropWhileEnd) import Foreign.C.String (CString, CStringLen) import qualified System.Posix.Internals as P import GHC.IO.Encoding (getFileSystemEncoding) import qualified GHC.Foreign as GHC import qualified Data.ByteString as B import qualified Data.ByteString.Unsafe as B import qualified Data.ByteString.Char8 as B8 import System.Posix.Types (Fd, FileMode) import System.Posix.IO hiding (openFd) import System.Posix.ByteString.FilePath (RawFilePath) import qualified System.Posix.IO as S (openFd) import qualified System.Posix.IO.ByteString as B (openFd) import System.IO.Unsafe (unsafePerformIO) import Prelude class (Monoid s, IsString s) => FilePathLike s where asString :: s -> String peekFilePath :: CString -> IO s peekFilePathLen :: CStringLen -> IO s withFilePath :: s -> (CString -> IO a) -> IO a withFilePathLen :: s -> (CStringLen -> IO a) -> IO a unsafeWithFilePathLen :: s -> (CStringLen -> IO a) -> IO a openFd :: s -> OpenMode -> OpenFileFlags -> IO Fd dropTrailingSlash :: s -> s (</>) :: s -> s -> s splitFileName :: s -> (s, s) instance FilePathLike [Char] where asString :: [Char] -> [Char] asString = forall a. a -> a id peekFilePath :: CString -> IO [Char] peekFilePath = CString -> IO [Char] P.peekFilePath peekFilePathLen :: CStringLen -> IO [Char] peekFilePathLen = CStringLen -> IO [Char] P.peekFilePathLen withFilePath :: forall a. [Char] -> (CString -> IO a) -> IO a withFilePath = forall a. [Char] -> (CString -> IO a) -> IO a P.withFilePath withFilePathLen :: forall a. [Char] -> (CStringLen -> IO a) -> IO a withFilePathLen [Char] path CStringLen -> IO a action = IO TextEncoding getFileSystemEncoding forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= \TextEncoding enc -> forall a. TextEncoding -> [Char] -> (CStringLen -> IO a) -> IO a GHC.withCStringLen TextEncoding enc [Char] path CStringLen -> IO a action unsafeWithFilePathLen :: forall a. [Char] -> (CStringLen -> IO a) -> IO a unsafeWithFilePathLen = forall s a. FilePathLike s => s -> (CStringLen -> IO a) -> IO a withFilePathLen openFd :: [Char] -> OpenMode -> OpenFileFlags -> IO Fd openFd = [Char] -> OpenMode -> OpenFileFlags -> IO Fd S.openFd dropTrailingSlash :: [Char] -> [Char] dropTrailingSlash [Char] s = if forall (t :: * -> *) a. Foldable t => t a -> Bool null [Char] s' then [Char] "/" else [Char] s' where s' :: [Char] s' = forall a. (a -> Bool) -> [a] -> [a] dropWhileEnd (forall a. Eq a => a -> a -> Bool == Char '/') [Char] s [Char] _ </> :: [Char] -> [Char] -> [Char] </> s2 :: [Char] s2@(Char '/' : [Char] _) = [Char] s2 [Char] s1 </> [Char] "" = [Char] s1 [Char] "" </> [Char] s2 = [Char] s2 [Char] s1 </> [Char] s2 = if [Char] s1' forall a. Eq a => a -> a -> Bool == [Char] "/" then Char '/' forall a. a -> [a] -> [a] : [Char] s2 else [Char] s1' forall a. [a] -> [a] -> [a] ++ [Char] "/" forall a. [a] -> [a] -> [a] ++ [Char] s2 where s1' :: [Char] s1' = forall s. FilePathLike s => s -> s dropTrailingSlash [Char] s1 splitFileName :: [Char] -> ([Char], [Char]) splitFileName [Char] s = (if forall (t :: * -> *) a. Foldable t => t a -> Bool null [Char] d then [Char] "./" else forall a. [a] -> [a] reverse [Char] d, forall a. [a] -> [a] reverse [Char] n) where ([Char] n, [Char] d) = forall a. (a -> Bool) -> [a] -> ([a], [a]) span (forall a. Eq a => a -> a -> Bool /= Char '/') forall a b. (a -> b) -> a -> b $ forall a. [a] -> [a] reverse [Char] s instance FilePathLike B.ByteString where asString :: ByteString -> [Char] asString = forall s1 s2. (FilePathLike s1, FilePathLike s2) => s1 -> s2 convert peekFilePath :: CString -> IO ByteString peekFilePath = CString -> IO ByteString B.packCString peekFilePathLen :: CStringLen -> IO ByteString peekFilePathLen = CStringLen -> IO ByteString B.packCStringLen withFilePath :: forall a. ByteString -> (CString -> IO a) -> IO a withFilePath = forall a. ByteString -> (CString -> IO a) -> IO a B.useAsCString withFilePathLen :: forall a. ByteString -> (CStringLen -> IO a) -> IO a withFilePathLen = forall a. ByteString -> (CStringLen -> IO a) -> IO a B.useAsCStringLen unsafeWithFilePathLen :: forall a. ByteString -> (CStringLen -> IO a) -> IO a unsafeWithFilePathLen = forall a. ByteString -> (CStringLen -> IO a) -> IO a B.unsafeUseAsCStringLen openFd :: ByteString -> OpenMode -> OpenFileFlags -> IO Fd openFd = ByteString -> OpenMode -> OpenFileFlags -> IO Fd B.openFd dropTrailingSlash :: ByteString -> ByteString dropTrailingSlash ByteString s = if ByteString -> Bool B.null ByteString s' then ByteString slashBS else ByteString s' where (ByteString s', ByteString _) = (Char -> Bool) -> ByteString -> (ByteString, ByteString) B8.spanEnd (forall a. Eq a => a -> a -> Bool == Char '/') ByteString s ByteString s1 </> :: ByteString -> ByteString -> ByteString </> ByteString s2 | ByteString -> Bool B.null ByteString s1 = ByteString s2 | ByteString -> Bool B.null ByteString s2 = ByteString s1 | ByteString -> Char B8.head ByteString s2 forall a. Eq a => a -> a -> Bool == Char '/' = ByteString s2 | Bool otherwise = let s1' :: ByteString s1' = forall s. FilePathLike s => s -> s dropTrailingSlash ByteString s1 in if ByteString -> Char B8.last ByteString s1' forall a. Eq a => a -> a -> Bool == Char '/' then ByteString slashBS forall a. Semigroup a => a -> a -> a <> ByteString s2 else [ByteString] -> ByteString B.concat [ByteString s1', ByteString slashBS, ByteString s2] splitFileName :: ByteString -> (ByteString, ByteString) splitFileName ByteString s = (if ByteString -> Bool B.null ByteString d then ByteString curDir else ByteString d, ByteString n) where (ByteString d, ByteString n) = (Char -> Bool) -> ByteString -> (ByteString, ByteString) B8.spanEnd (forall a. Eq a => a -> a -> Bool /= Char '/') ByteString s curDir :: ByteString curDir = [Char] -> ByteString B8.pack [Char] "./" convert :: (FilePathLike s1, FilePathLike s2) => s1 -> s2 convert :: forall s1 s2. (FilePathLike s1, FilePathLike s2) => s1 -> s2 convert s1 s = forall a. IO a -> a unsafePerformIO forall a b. (a -> b) -> a -> b $ forall s a. FilePathLike s => s -> (CStringLen -> IO a) -> IO a unsafeWithFilePathLen s1 s forall s. FilePathLike s => CStringLen -> IO s peekFilePathLen slashBS :: B.ByteString slashBS :: ByteString slashBS = Char -> ByteString B8.singleton Char '/'