{-# LANGUAGE CPP #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE ScopedTypeVariables #-} -- | Streaming functions for interacting with the filesystem. module System.Directory.OsPath.Streaming ( DirStream , openDirStream , readDirStream , closeDirStream ) where import System.OsPath (osp) #ifdef mingw32_HOST_OS import Control.Concurrent.Counter (Counter) import Control.Concurrent.Counter qualified as Counter import Control.Monad (unless) import System.OsPath.Types (OsPath) import System.OsString.Internal.Types (OsString(OsString), getOsString) import System.OsString.Windows (pstr) import System.Win32.Types qualified as Win32 import System.Win32.WindowsString.File qualified as Win32 data DirStream = DirStream !Win32.HANDLE !Win32.FindData !Counter openDirStream :: OsPath -> IO DirStream openDirStream fp = do (h, fdat) <- Win32.findFirstFile $ getOsString fp <> [pstr|\*|] hasMore <- Counter.new 1 -- always at least two records, "." and ".." pure $! DirStream h fdat hasMore closeDirStream :: DirStream -> IO () closeDirStream (DirStream h _ _) = Win32.findClose h readDirStream :: DirStream -> IO (Maybe OsPath) readDirStream (DirStream h fdat hasMore) = go where go = do hasMore' <- Counter.get hasMore if hasMore' /= 0 then do filename <- Win32.getFindDataFileName fdat hasMore'' <- Win32.findNextFile h fdat unless hasMore'' $ Counter.set hasMore 0 if filename == getOsString [osp|.|] || filename == getOsString [osp|..|] then go else pure $ Just $ OsString filename else pure Nothing #else import System.OsPath.Types (OsPath) import System.OsString.Internal.Types (OsString(OsString), getOsString) import System.Posix.Directory.PosixPath (DirStream, closeDirStream) import System.Posix.Directory.PosixPath qualified as Posix openDirStream :: OsPath -> IO DirStream openDirStream = Posix.openDirStream . getOsString {-# INLINE readDirStream #-} readDirStream :: DirStream -> IO (Maybe OsPath) readDirStream ds = go where go = do fp <- Posix.readDirStream ds case () of _ | fp == mempty -> pure Nothing | fp == getOsString [osp|.|] || fp == getOsString [osp|..|] -> go | otherwise -> pure $ Just $ OsString fp #endif