packages feed

bytestring 0.9.0.2 → 0.9.0.3

raw patch · 6 files changed

+137/−102 lines, 6 files

Files

Data/ByteString.hs view
@@ -227,10 +227,10 @@  -- Control.Exception.bracket not available in yhc or nhc #ifndef __NHC__-import Control.Exception        (bracket, assert)+import Control.Exception        (finally, bracket, assert) import qualified Control.Exception as Exception #else-import IO			(bracket)+import IO			(bracket, finally) #endif import Control.Monad            (when) @@ -1628,30 +1628,12 @@     memcpy p (f `plusPtr` s) (fromIntegral l)  -- ------------------------------------------------------------------------ line IO+-- Line IO  -- | Read a line from stdin. getLine :: IO ByteString getLine = hGetLine stdin -{---- | Lazily construct a list of lines of ByteStrings. This will be much--- better on memory consumption than using 'hGetContents >>= lines'--- If you're considering this, a better choice might be to use--- Data.ByteString.Lazy-hGetLines :: Handle -> IO [ByteString]-hGetLines h = go-    where-        go = unsafeInterleaveIO $ do-                e <- hIsEOF h-                if e-                  then return []-                  else do-                x  <- hGetLine h-                xs <- go-                return (x:xs)--}- -- | Read a line from a handle  hGetLine :: Handle -> IO ByteString@@ -1751,9 +1733,13 @@ putStrLn :: ByteString -> IO () putStrLn = hPutStrLn stdout +------------------------------------------------------------------------+-- Low level IO+ -- | Read a 'ByteString' directly from the specified 'Handle'.  This -- is far more efficient than reading the characters into a 'String' -- and then using 'pack'.+-- hGet :: Handle -> Int -> IO ByteString hGet _ 0 = return empty hGet h i = createAndTrim i $ \p -> hGetBuf h p i@@ -1761,6 +1747,7 @@ -- | hGetNonBlocking is identical to 'hGet', except that it will never block -- waiting for data to become available, instead it returns only whatever data -- is available.+-- hGetNonBlocking :: Handle -> Int -> IO ByteString #if defined(__GLASGOW_HASKELL__) hGetNonBlocking _ 0 = return empty@@ -1769,7 +1756,8 @@ hGetNonBlocking = hGet #endif --- | Read entire handle contents into a 'ByteString'.+-- | Read entire handle contents strictly into a 'ByteString'.+-- -- This function reads chunks at a time, doubling the chunksize on each -- read. The final buffer is then realloced to the appropriate size. For -- files > half of available memory, this may lead to memory exhaustion.@@ -1778,8 +1766,11 @@ -- As with 'hGet', the string representation in the file is assumed to -- be ISO-8859-1. --+-- The Handle is closed once the contents have been read,+-- or if an exception is thrown.+-- hGetContents :: Handle -> IO ByteString-hGetContents h = do+hGetContents h = always (hClose h) $ do -- strict, so hClose     let start_size = 1024     p <- mallocBytes start_size     i <- hGetBuf h p start_size@@ -1789,6 +1780,7 @@                 return $! PS fp 0 i         else f p start_size     where+        always = flip finally         f p s = do             let s' = 2 * s             p' <- reallocBytes p s'@@ -1800,14 +1792,17 @@                         return $! PS fp 0 i'                 else f p' s' --- | getContents. Equivalent to hGetContents stdin+-- | getContents. Read stdin strictly. Equivalent to hGetContents stdin+-- The 'Handle' is closed after the contents have been read.+-- getContents :: IO ByteString getContents = hGetContents stdin  -- | The interact function takes a function of type @ByteString -> ByteString@ -- as its argument. The entire input from the standard input device is passed -- to this function as its argument, and the resulting string is output on the--- standard output device. It's great for writing one line programs!+-- standard output device.+-- interact :: (ByteString -> ByteString) -> IO () interact transformer = putStr . transformer =<< getContents @@ -1816,6 +1811,7 @@ -- 'pack'.  It also may be more efficient than opening the file and -- reading it using hGet. Files are read using 'binary mode' on Windows, -- for 'text mode' use the Char8 version of this function.+-- readFile :: FilePath -> IO ByteString readFile f = bracket (openBinaryFile f ReadMode) hClose     (\h -> hFileSize h >>= hGet h . fromIntegral)@@ -1829,64 +1825,6 @@ appendFile :: FilePath -> ByteString -> IO () appendFile f txt = bracket (openBinaryFile f AppendMode) hClose     (\h -> hPut h txt)--{------- Disable until we can move it into a portable .hsc file------- | Like readFile, this reads an entire file directly into a--- 'ByteString', but it is even more efficient.  It involves directly--- mapping the file to memory.  This has the advantage that the contents--- of the file never need to be copied.  Also, under memory pressure the--- page may simply be discarded, while in the case of readFile it would--- need to be written to swap.  If you read many small files, mmapFile--- will be less memory-efficient than readFile, since each mmapFile--- takes up a separate page of memory.  Also, you can run into bus--- errors if the file is modified.  As with 'readFile', the string--- representation in the file is assumed to be ISO-8859-1.------ On systems without mmap, this is the same as a readFile.----mmapFile :: FilePath -> IO ByteString-mmapFile f = mmap f >>= \(fp,l) -> return $! PS fp 0 l--mmap :: FilePath -> IO (ForeignPtr Word8, Int)-mmap f = do-    h <- openBinaryFile f ReadMode-    l <- fromIntegral `fmap` hFileSize h-    -- Don't bother mmaping small files because each mmapped file takes up-    -- at least one full VM block.-    if l < mmap_limit-       then do thefp <- mallocByteString l-               withForeignPtr thefp $ \p-> hGetBuf h p l-               hClose h-               return (thefp, l)-       else do-               -- unix only :(-               fd <- fromIntegral `fmap` handleToFd h-               p  <- my_mmap l fd-               fp <- if p == nullPtr-                     then do thefp <- mallocByteString l-                             withForeignPtr thefp $ \p' -> hGetBuf h p' l-                             return thefp-                     else do-                          -- The munmap leads to crashes on OpenBSD.-                          -- maybe there's a use after unmap in there somewhere?-                          -- Bulat suggests adding the hClose to the-                          -- finalizer, excellent idea.-#if !defined(__OpenBSD__)-                             let unmap = c_munmap p l >> return ()-#else-                             let unmap = return ()-#endif-                             fp <- newForeignPtr p unmap-                             return fp-               c_close fd-               hClose h-               return (fp, l)-    where mmap_limit = 16*1024--}  -- --------------------------------------------------------------------- -- Internal utilities
Data/ByteString/Internal.hs view
@@ -55,7 +55,7 @@ #endif          -- * Chars-        w2c, c2w, isSpaceWord8+        w2c, c2w, isSpaceWord8, isSpaceChar8    ) where @@ -268,20 +268,30 @@ c2w = fromIntegral . ord {-# INLINE c2w #-} --- Selects white-space characters in the Latin-1 range--- ordered by frequency--- Idea from Ketil+-- | Selects words corresponding to white-space characters in the Latin-1 range+-- ordered by frequency.  isSpaceWord8 :: Word8 -> Bool-isSpaceWord8 w = case w of-    0x20 -> True -- SPACE-    0x0A -> True -- LF, \n-    0x09 -> True -- HT, \t-    0x0C -> True -- FF, \f-    0x0D -> True -- CR, \r-    0x0B -> True -- VT, \v-    0xA0 -> True -- spotted by QC..-    _    -> False+isSpaceWord8 w =+    w == 0x20 ||+    w == 0x0A || -- LF, \n+    w == 0x09 || -- HT, \t+    w == 0x0C || -- FF, \f+    w == 0x0D || -- CR, \r+    w == 0x0B || -- VT, \v+    w == 0xA0    -- spotted by QC.. {-# INLINE isSpaceWord8 #-}++-- | Selects white-space characters in the Latin-1 range+isSpaceChar8 :: Char -> Bool+isSpaceChar8 c =+    c == ' '     ||+    c == '\t'    ||+    c == '\n'    ||+    c == '\r'    ||+    c == '\f'    ||+    c == '\v'    ||+    c == '\xa0'+{-# INLINE isSpaceChar8 #-}  ------------------------------------------------------------------------ 
Data/ByteString/Lazy.hs view
@@ -1172,13 +1172,20 @@  -- --------------------------------------------------------------------- -- Lazy ByteString IO+--+-- Rule for when to close: is it expected to read the whole file?+-- If so, close when done. +--  -- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks -- are read on demand, in at most @k@-sized chunks. It does not block -- waiting for a whole @k@-sized chunk, so if less than @k@ bytes are -- available then they will be returned immediately as a smaller chunk.+--+-- The handle is closed on EOF.+-- hGetContentsN :: Int -> Handle -> IO ByteString-hGetContentsN k h = lazyRead+hGetContentsN k h = lazyRead -- TODO close on exceptions   where     lazyRead = unsafeInterleaveIO loop @@ -1189,7 +1196,7 @@         -- 0 or EAGAIN         if S.null c           then do eof <- hIsEOF h-                  if eof then return Empty+                  if eof then hClose h >> return Empty                          else hWaitForInput h (-1)                            >> loop           else do cs <- lazyRead@@ -1197,6 +1204,7 @@  -- | Read @n@ bytes into a 'ByteString', directly from the -- specified 'Handle', in chunks of size @k@.+-- hGetN :: Int -> Handle -> Int -> IO ByteString hGetN _ _ 0 = return empty hGetN k h n = readChunks n@@ -1212,9 +1220,10 @@ -- | hGetNonBlockingN is similar to 'hGetContentsN', except that it will never block -- waiting for data to become available, instead it returns only whatever data -- is available. Chunks are read on demand, in @k@-sized chunks.+-- hGetNonBlockingN :: Int -> Handle -> Int -> IO ByteString #if defined(__GLASGOW_HASKELL__)-hGetNonBlockingN _ _ 0 = return empty+hGetNonBlockingN _ _ 0 = return Empty hGetNonBlockingN k h n = readChunks n   where     STRICT1(readChunks)@@ -1230,10 +1239,14 @@  -- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks -- are read on demand, using the default chunk size.+--+-- Once EOF is encountered, the Handle is closed.+-- hGetContents :: Handle -> IO ByteString hGetContents = hGetContentsN defaultChunkSize  -- | Read @n@ bytes into a 'ByteString', directly from the specified 'Handle'.+-- hGet :: Handle -> Int -> IO ByteString hGet = hGetN defaultChunkSize @@ -1248,28 +1261,35 @@ #endif  -- | Read an entire file /lazily/ into a 'ByteString'.+-- The Handle will be held open until EOF is encountered.+-- readFile :: FilePath -> IO ByteString readFile f = openBinaryFile f ReadMode >>= hGetContents  -- | Write a 'ByteString' to a file.+-- writeFile :: FilePath -> ByteString -> IO () writeFile f txt = bracket (openBinaryFile f WriteMode) hClose     (\hdl -> hPut hdl txt)  -- | Append a 'ByteString' to a file.+-- appendFile :: FilePath -> ByteString -> IO () appendFile f txt = bracket (openBinaryFile f AppendMode) hClose     (\hdl -> hPut hdl txt)  -- | getContents. Equivalent to hGetContents stdin. Will read /lazily/+-- getContents :: IO ByteString getContents = hGetContents stdin  -- | Outputs a 'ByteString' to the specified 'Handle'.+-- hPut :: Handle -> ByteString -> IO () hPut h cs = foldrChunks (\c rest -> S.hPut h c >> rest) (return ()) cs  -- | A synonym for @hPut@, for compatibility+-- hPutStr :: Handle -> ByteString -> IO () hPutStr = hPut @@ -1278,13 +1298,15 @@ putStr = hPut stdout  -- | Write a ByteString to stdout, appending a newline byte+-- putStrLn :: ByteString -> IO () putStrLn ps = hPut stdout ps >> hPut stdout (singleton 0x0a)  -- | The interact function takes a function of type @ByteString -> ByteString@ -- as its argument. The entire input from the standard input device is passed -- to this function as its argument, and the resulting string is output on the--- standard output device. It's great for writing one line programs!+-- standard output device.+-- interact :: (ByteString -> ByteString) -> IO () interact transformer = putStr . transformer =<< getContents 
Data/ByteString/Lazy/Internal.hs view
@@ -2,7 +2,7 @@ -- | -- Module      : Data.ByteString.Lazy.Internal -- License     : BSD-style--- Maintainer  : dons@cse.unsw.edu.au, duncan@haskell.org+-- Maintainer  : dons@galois.com, duncan@haskell.org -- Stability   : experimental -- Portability : portable -- 
bytestring.cabal view
@@ -1,5 +1,5 @@ Name:                bytestring-Version:             0.9.0.2+Version:             0.9.0.3 Synopsis:            Fast, packed, strict and lazy byte arrays with a list interface Description:     .
+ tests/lazy-hclose.hs view
@@ -0,0 +1,65 @@+import qualified Data.ByteString       as S+import qualified Data.ByteString.Char8 as S8++import qualified Data.ByteString.Lazy       as L+import qualified Data.ByteString.Lazy.Char8 as L8++import Control.Monad+import System.Directory+import System.Mem+import System.IO++import Data.ByteString.Internal+import Foreign.ForeignPtr++main = do+    writeFile "a" "x"++    ------------------------------------------------------------------------+    -- readFile tests++    print "Testing resource leaks for Strict.readFile"+    forM_ [1..n] $ const $ do+         r <- S.readFile "a"+         S.writeFile "b" (S8.pack "abc")+         renameFile "b" "a"++    print "Testing resource leaks for Lazy.readFile"+    forM_ [1..n] $ const $ do+         r <- L.readFile "a"+         L.length r `seq` return ()      -- force the input, and done with 'r' now.+         L.writeFile "b" (L8.pack "abc") -- but we still need the finalizers to run+         renameFile "b" "a"++    -- manage the resources explicitly.+    print "Testing resource leaks when converting lazy to strict"+    forM_ [1..n] $ const $ do+         let release c = finalizeForeignPtr fp where (fp,_,_) = toForeignPtr c+         r <- L.readFile "a"+         mapM_ release (L.toChunks r) -- should close it.+         L.writeFile "b" (L8.pack "abc")+         renameFile "b" "a"++    ------------------------------------------------------------------------+    -- hGetContents tests++    -- works now+    print "Testing strict hGetContents"+    forM_ [1..n] $ const $ do+         h <- openFile "a" ReadMode+         r <- S.hGetContents h -- should be strict, and hClosed.+         S.last r `seq` return ()+         S.writeFile "b" (S8.pack "abc")+         renameFile "b" "a"++    -- works now+    print "Testing lazy hGetContents"+    forM_ [1..n] $ const $ do+         h <- openFile "a" ReadMode+         r <- L.hGetContents h -- should be strict, and hClosed.+         L.last r `seq` return ()+         L.writeFile "b" (L8.pack "abc")+         renameFile "b" "a"+++n = 1000