@@ -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.
100102readDirStreamMaybe :: 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
0 commit comments