diff options
author | Joey Hess <joey@kitenet.net> | 2012-11-18 20:06:28 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-11-18 20:30:05 -0400 |
commit | 6aa68125b6d476f0ad9372a0f0fbaa5c118e7096 (patch) | |
tree | baadc0f86773f86903239e242559df8553bd41fa /Utility | |
parent | ac71b499ac6d53408cfce19a1ddd00bfa4b2645f (diff) |
upload progress bars for webdav!
Diffstat (limited to 'Utility')
-rw-r--r-- | Utility/Observed.hs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/Utility/Observed.hs b/Utility/Observed.hs new file mode 100644 index 000000000..3ee973429 --- /dev/null +++ b/Utility/Observed.hs @@ -0,0 +1,43 @@ +module Utility.Observed where + +import qualified Data.ByteString.Lazy as L +import qualified Data.ByteString as S +import System.IO +import System.IO.Unsafe +import Foreign.Storable (Storable(sizeOf)) + +{- This is like L.hGetContents, but after each chunk is read, an action + - is run to observe the size of the chunk. + - + - Note that the observer is run in unsafeInterleaveIO, which means that + - it can be run at any time. It's even possible for observers to run out + - of order, as different parts of the ByteString are consumed. + - + - All the usual caveats about using unsafeInterleaveIO apply to the observers, + - so use caution. + -} +hGetContentsObserved :: Handle -> (Int -> IO ()) -> IO L.ByteString +hGetContentsObserved h observe = lazyRead + where + lazyRead = unsafeInterleaveIO loop + + loop = do + c <- S.hGetSome h defaultChunkSize + if S.null c + then do + hClose h + return $ L.empty + else do + observe $ S.length c + {- unsafeInterleaveIO causes this to be + - deferred until the data is read from the + - ByteString. -} + cs <- lazyRead + return $ L.append (L.fromChunks [c]) cs + +{- Same default chunk size Lazy ByteStrings use. -} +defaultChunkSize :: Int +defaultChunkSize = 32 * k - chunkOverhead + where + k = 1024 + chunkOverhead = 2 * sizeOf (undefined :: Int) -- GHC specific |