@@ -29,9 +29,11 @@ module System.Posix.Directory (
29
29
30
30
-- * Reading directories
31
31
DirStream ,
32
+ DirEnt (.. ),
32
33
openDirStream ,
33
34
readDirStream ,
34
35
readDirStreamMaybe ,
36
+ readDirStreamWith ,
35
37
rewindDirStream ,
36
38
closeDirStream ,
37
39
DirStreamOffset ,
@@ -95,10 +97,24 @@ readDirStream = fmap (fromMaybe "") . readDirStreamMaybe
95
97
-- | @readDirStreamMaybe dp@ calls @readdir@ to obtain the
96
98
-- next directory entry (@struct dirent@) for the open directory
97
99
-- 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.
100
102
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) =
102
118
alloca $ \ ptr_dEnt -> loop ptr_dEnt
103
119
where
104
120
loop ptr_dEnt = do
@@ -109,9 +125,9 @@ readDirStreamMaybe (DirStream dirp) =
109
125
if (dEnt == nullPtr)
110
126
then return Nothing
111
127
else do
112
- entry <- (d_name dEnt >>= peekFilePath )
128
+ res <- f ( DirEnt dEnt)
113
129
c_freeDirEnt dEnt
114
- return $ Just entry
130
+ return ( Just res)
115
131
else do errno <- getErrno
116
132
if (errno == eINTR) then loop ptr_dEnt else do
117
133
let (Errno eo) = errno
0 commit comments