Skip to content

Commit a2e6261

Browse files
committed
Expose dirent pointer and added readDirStreamWith
This commit exposes the dirent pointer used in the directory stream functions wrapped in a newtype called `DirEnt`. It also adds a new function `readDirStreamWith` that takes a callback that is used to obtain the result from the pointer to the directory entry.
1 parent a7014ec commit a2e6261

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

System/Posix/Directory.hsc

+21-5
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ module System.Posix.Directory (
2929

3030
-- * Reading directories
3131
DirStream,
32+
DirEnt(..),
3233
openDirStream,
3334
readDirStream,
3435
readDirStreamMaybe,
36+
readDirStreamWith,
3537
rewindDirStream,
3638
closeDirStream,
3739
DirStreamOffset,
@@ -95,10 +97,24 @@ readDirStream = fmap (fromMaybe "") . readDirStreamMaybe
9597
-- | @readDirStreamMaybe dp@ calls @readdir@ to obtain the
9698
-- next directory entry (@struct dirent@) for the open directory
9799
-- stream @dp@. It returns the @d_name@ member of that
98-
-- structure wrapped in a @Just d_name@ if an entry was read and @Nothing@ if
99-
-- the end of the directory stream was reached.
100+
-- structure wrapped in a @Just d_name@ if an entry was read and @Nothing@ if
101+
-- the end of the directory stream was reached.
100102
readDirStreamMaybe :: DirStream -> IO (Maybe FilePath)
101-
readDirStreamMaybe (DirStream dirp) =
103+
readDirStreamMaybe = readDirStreamWith
104+
(\(DirEnt dEnt) -> d_name dEnt >>= peekFilePath)
105+
106+
-- | @readDirStreamWith f dp@ calls @readdir@ to obtain the next directory entry
107+
-- (@struct dirent@) for the open directory stream @dp@. If an entry is read,
108+
-- it passes the pointer to that structure to the provided function @f@ for
109+
-- processing. It returns the result of that function call wrapped in a @Just@
110+
-- if an entry was read and @Nothing@ if the end of the directory stream was
111+
-- reached.
112+
--
113+
-- __NOTE:__ The lifetime of the pointer wrapped in the `DirEnt` is limited to
114+
-- invocation of the callback and it will be freed automatically after. Do not
115+
-- pass it to the outside world!
116+
readDirStreamWith :: (DirEnt -> IO a) -> DirStream -> IO (Maybe a)
117+
readDirStreamWith f (DirStream dirp) =
102118
alloca $ \ptr_dEnt -> loop ptr_dEnt
103119
where
104120
loop ptr_dEnt = do
@@ -109,9 +125,9 @@ readDirStreamMaybe (DirStream dirp) =
109125
if (dEnt == nullPtr)
110126
then return Nothing
111127
else do
112-
entry <- (d_name dEnt >>= peekFilePath)
128+
res <- f (DirEnt dEnt)
113129
c_freeDirEnt dEnt
114-
return $ Just entry
130+
return (Just res)
115131
else do errno <- getErrno
116132
if (errno == eINTR) then loop ptr_dEnt else do
117133
let (Errno eo) = errno

System/Posix/Directory/Common.hsc

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "HsUnix.h"
1818

1919
module System.Posix.Directory.Common (
20-
DirStream(..), CDir, CDirent, DirStreamOffset(..),
20+
DirStream(..), DirEnt(..), CDir, CDirent, DirStreamOffset(..),
2121
unsafeOpenDirStreamFd,
2222
rewindDirStream,
2323
closeDirStream,
@@ -38,6 +38,8 @@ import Foreign.C
3838

3939
newtype DirStream = DirStream (Ptr CDir)
4040

41+
newtype DirEnt = DirEnt (Ptr CDirent)
42+
4143
data {-# CTYPE "DIR" #-} CDir
4244
data {-# CTYPE "struct dirent" #-} CDirent
4345

0 commit comments

Comments
 (0)