Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 5c4dc33d0fae43b882b2a15cb5647310b8c04494 0 parents
Simon Meier authored
Showing with 101,284 additions and 0 deletions.
  1. +5 −0 .darcs-boring
  2. +3 −0  .gitignore
  3. +2,025 −0 Data/ByteString.hs
  4. +1,019 −0 Data/ByteString/Char8.hs
  5. +593 −0 Data/ByteString/Internal.hs
  6. +1,345 −0 Data/ByteString/Lazy.hs
  7. +451 −0 Data/ByteString/Lazy/Builder.hs
  8. +361 −0 Data/ByteString/Lazy/Builder/ASCII.hs
  9. +804 −0 Data/ByteString/Lazy/Builder/BasicEncoding.hs
  10. +287 −0 Data/ByteString/Lazy/Builder/BasicEncoding/ASCII.hs
  11. +336 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Binary.hs
  12. +909 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Extras.hs
  13. +353 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Internal.hs
  14. +116 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Internal/Base16.hs
  15. +55 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Internal/Floating.hs
  16. +106 −0 Data/ByteString/Lazy/Builder/BasicEncoding/Internal/UncheckedShifts.hs
  17. +125 −0 Data/ByteString/Lazy/Builder/Extras.hs
  18. +1,005 −0 Data/ByteString/Lazy/Builder/Internal.hs
  19. +854 −0 Data/ByteString/Lazy/Builder/Internal.hs-darcs-backup0
  20. +878 −0 Data/ByteString/Lazy/Char8.hs
  21. +253 −0 Data/ByteString/Lazy/Internal.hs
  22. +308 −0 Data/ByteString/Unsafe.hs
  23. +30 −0 LICENSE
  24. +205 −0 README
  25. +2 −0  Setup.hs
  26. +71 −0 TODO
  27. +263 −0 bench/BenchAll.hs
  28. +118 −0 bench/BoundsCheckFusion.hs
  29. +614 −0 bench/CSV.hs
  30. +30 −0 bench/LICENSE
  31. +72 −0 bench/bench-bytestring-builder.cabal
  32. +264 −0 bytestring.cabal
  33. +82 −0 cbits/fpstring.c
  34. +215 −0 cbits/itoa.c
  35. +6 −0 include/fpstring.h
  36. +1 −0  prologue.txt
  37. +334 −0 tests/Bench.hs
  38. +145 −0 tests/BenchUtils.hs
  39. +70 −0 tests/FusionBench.hs
  40. +312 −0 tests/FusionProperties.hs
  41. +88 −0 tests/Hash.hs
  42. +213 −0 tests/Makefile
  43. +2,467 −0 tests/Properties.hs
  44. +203 −0 tests/QuickCheckUtils.hs
  45. +32 −0 tests/Rules.hs
  46. +67 −0 tests/TestFramework.hs
  47. +27 −0 tests/Units.hs
  48. +38,617 −0 tests/Usr.Dict.Words
  49. +70 −0 tests/Words.hs
  50. +339 −0 tests/builder/Data/ByteString/Lazy/Builder/BasicEncoding/TestUtils.hs
  51. +337 −0 tests/builder/Data/ByteString/Lazy/Builder/BasicEncoding/Tests.hs
  52. +641 −0 tests/builder/Data/ByteString/Lazy/Builder/Tests.hs
  53. +21 −0 tests/builder/TestSuite.hs
  54. +3,925 −0 tests/data
  55. +23 −0 tests/down-fuse.hs
  56. +11 −0 tests/edit.hs
  57. +28 −0 tests/fuse.hs
  58. +24 −0 tests/groupby.hs
  59. +24 −0 tests/iavor.hs
  60. +21 −0 tests/inline.hs
  61. +65 −0 tests/lazy-hclose.hs
  62. +24 −0 tests/lazybuild.hs
  63. +24 −0 tests/lazybuildcons.hs
  64. +9 −0 tests/lazyio.hs
  65. +9 −0 tests/lazylines.hs
  66. +17 −0 tests/lazyread.hs
  67. +20 −0 tests/letter_frequency.hs
  68. +16 −0 tests/linesort.hs
  69. +15 −0 tests/macros.m4
  70. +3 −0  tests/pack.hs
  71. +33 −0 tests/revcomp.hs
  72. +38,618 −0 tests/spellcheck-input.txt
  73. +69 −0 tests/spellcheck.hs
  74. +30 −0 tests/sum.hs
  75. +72 −0 tests/test-compare.hs
  76. +36 −0 tests/unpack.hs
  77. +14 −0 tests/wc.hs
  78. +7 −0 tests/zipwith.hs
5 .darcs-boring
@@ -0,0 +1,5 @@
+^dist(/|$)
+^setup(/|$)
+^GNUmakefile$
+^Makefile.local$
+^.depend(.bak)?$
3  .gitignore
@@ -0,0 +1,3 @@
+dist
+cabal-dev
+_darcs/
2,025 Data/ByteString.hs
@@ -0,0 +1,2025 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__
+{-# LANGUAGE MagicHash, UnboxedTuples,
+ NamedFieldPuns, BangPatterns, RecordWildCards #-}
+#endif
+{-# OPTIONS_HADDOCK prune #-}
+#if __GLASGOW_HASKELL__ >= 701
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+-- |
+-- Module : Data.ByteString
+-- Copyright : (c) The University of Glasgow 2001,
+-- (c) David Roundy 2003-2005,
+-- (c) Simon Marlow 2005,
+-- (c) Bjorn Bringert 2006,
+-- (c) Don Stewart 2005-2008,
+-- (c) Duncan Coutts 2006-2011
+-- License : BSD-style
+--
+-- Maintainer : dons00@gmail.com, duncan@community.haskell.org
+-- Stability : stable
+-- Portability : portable
+--
+-- A time and space-efficient implementation of byte vectors using
+-- packed Word8 arrays, suitable for high performance use, both in terms
+-- of large data quantities, or high speed requirements. Byte vectors
+-- are encoded as strict 'Word8' arrays of bytes, held in a 'ForeignPtr',
+-- and can be passed between C and Haskell with little effort.
+--
+-- This module is intended to be imported @qualified@, to avoid name
+-- clashes with "Prelude" functions. eg.
+--
+-- > import qualified Data.ByteString as B
+--
+-- Original GHC implementation by Bryan O\'Sullivan.
+-- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.
+-- Rewritten to support slices and use 'ForeignPtr' by David Roundy.
+-- Rewritten again and extended by Don Stewart and Duncan Coutts.
+--
+
+module Data.ByteString (
+
+ -- * The @ByteString@ type
+ ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid
+
+ -- * Introducing and eliminating 'ByteString's
+ empty, -- :: ByteString
+ singleton, -- :: Word8 -> ByteString
+ pack, -- :: [Word8] -> ByteString
+ unpack, -- :: ByteString -> [Word8]
+
+ -- * Basic interface
+ cons, -- :: Word8 -> ByteString -> ByteString
+ snoc, -- :: ByteString -> Word8 -> ByteString
+ append, -- :: ByteString -> ByteString -> ByteString
+ head, -- :: ByteString -> Word8
+ uncons, -- :: ByteString -> Maybe (Word8, ByteString)
+ last, -- :: ByteString -> Word8
+ tail, -- :: ByteString -> ByteString
+ init, -- :: ByteString -> ByteString
+ null, -- :: ByteString -> Bool
+ length, -- :: ByteString -> Int
+
+ -- * Transforming ByteStrings
+ map, -- :: (Word8 -> Word8) -> ByteString -> ByteString
+ reverse, -- :: ByteString -> ByteString
+ intersperse, -- :: Word8 -> ByteString -> ByteString
+ intercalate, -- :: ByteString -> [ByteString] -> ByteString
+ transpose, -- :: [ByteString] -> [ByteString]
+
+ -- * Reducing 'ByteString's (folds)
+ foldl, -- :: (a -> Word8 -> a) -> a -> ByteString -> a
+ foldl', -- :: (a -> Word8 -> a) -> a -> ByteString -> a
+ foldl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+ foldl1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+
+ foldr, -- :: (Word8 -> a -> a) -> a -> ByteString -> a
+ foldr', -- :: (Word8 -> a -> a) -> a -> ByteString -> a
+ foldr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+ foldr1', -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+
+ -- ** Special folds
+ concat, -- :: [ByteString] -> ByteString
+ concatMap, -- :: (Word8 -> ByteString) -> ByteString -> ByteString
+ any, -- :: (Word8 -> Bool) -> ByteString -> Bool
+ all, -- :: (Word8 -> Bool) -> ByteString -> Bool
+ maximum, -- :: ByteString -> Word8
+ minimum, -- :: ByteString -> Word8
+
+ -- * Building ByteStrings
+ -- ** Scans
+ scanl, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
+ scanl1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
+ scanr, -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
+ scanr1, -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
+
+ -- ** Accumulating maps
+ mapAccumL, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
+ mapAccumR, -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
+
+ -- ** Generating and unfolding ByteStrings
+ replicate, -- :: Int -> Word8 -> ByteString
+ unfoldr, -- :: (a -> Maybe (Word8, a)) -> a -> ByteString
+ unfoldrN, -- :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
+
+ -- * Substrings
+
+ -- ** Breaking strings
+ take, -- :: Int -> ByteString -> ByteString
+ drop, -- :: Int -> ByteString -> ByteString
+ splitAt, -- :: Int -> ByteString -> (ByteString, ByteString)
+ takeWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString
+ dropWhile, -- :: (Word8 -> Bool) -> ByteString -> ByteString
+ span, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+ spanEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+ break, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+ breakEnd, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+ group, -- :: ByteString -> [ByteString]
+ groupBy, -- :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]
+ inits, -- :: ByteString -> [ByteString]
+ tails, -- :: ByteString -> [ByteString]
+
+ -- ** Breaking into many substrings
+ split, -- :: Word8 -> ByteString -> [ByteString]
+ splitWith, -- :: (Word8 -> Bool) -> ByteString -> [ByteString]
+
+ -- * Predicates
+ isPrefixOf, -- :: ByteString -> ByteString -> Bool
+ isSuffixOf, -- :: ByteString -> ByteString -> Bool
+ isInfixOf, -- :: ByteString -> ByteString -> Bool
+
+ -- ** Search for arbitrary substrings
+ breakSubstring, -- :: ByteString -> ByteString -> (ByteString,ByteString)
+ findSubstring, -- :: ByteString -> ByteString -> Maybe Int
+ findSubstrings, -- :: ByteString -> ByteString -> [Int]
+
+ -- * Searching ByteStrings
+
+ -- ** Searching by equality
+ elem, -- :: Word8 -> ByteString -> Bool
+ notElem, -- :: Word8 -> ByteString -> Bool
+
+ -- ** Searching with a predicate
+ find, -- :: (Word8 -> Bool) -> ByteString -> Maybe Word8
+ filter, -- :: (Word8 -> Bool) -> ByteString -> ByteString
+ partition, -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+
+ -- * Indexing ByteStrings
+ index, -- :: ByteString -> Int -> Word8
+ elemIndex, -- :: Word8 -> ByteString -> Maybe Int
+ elemIndices, -- :: Word8 -> ByteString -> [Int]
+ elemIndexEnd, -- :: Word8 -> ByteString -> Maybe Int
+ findIndex, -- :: (Word8 -> Bool) -> ByteString -> Maybe Int
+ findIndices, -- :: (Word8 -> Bool) -> ByteString -> [Int]
+ count, -- :: Word8 -> ByteString -> Int
+
+ -- * Zipping and unzipping ByteStrings
+ zip, -- :: ByteString -> ByteString -> [(Word8,Word8)]
+ zipWith, -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]
+ unzip, -- :: [(Word8,Word8)] -> (ByteString,ByteString)
+
+ -- * Ordered ByteStrings
+ sort, -- :: ByteString -> ByteString
+
+ -- * Low level conversions
+ -- ** Copying ByteStrings
+ copy, -- :: ByteString -> ByteString
+
+ -- ** Packing 'CString's and pointers
+ packCString, -- :: CString -> IO ByteString
+ packCStringLen, -- :: CStringLen -> IO ByteString
+
+ -- ** Using ByteStrings as 'CString's
+ useAsCString, -- :: ByteString -> (CString -> IO a) -> IO a
+ useAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a
+
+ -- * I\/O with 'ByteString's
+
+ -- ** Standard input and output
+ getLine, -- :: IO ByteString
+ getContents, -- :: IO ByteString
+ putStr, -- :: ByteString -> IO ()
+ putStrLn, -- :: ByteString -> IO ()
+ interact, -- :: (ByteString -> ByteString) -> IO ()
+
+ -- ** Files
+ readFile, -- :: FilePath -> IO ByteString
+ writeFile, -- :: FilePath -> ByteString -> IO ()
+ appendFile, -- :: FilePath -> ByteString -> IO ()
+
+ -- ** I\/O with Handles
+ hGetLine, -- :: Handle -> IO ByteString
+ hGetContents, -- :: Handle -> IO ByteString
+ hGet, -- :: Handle -> Int -> IO ByteString
+ hGetSome, -- :: Handle -> Int -> IO ByteString
+ hGetNonBlocking, -- :: Handle -> Int -> IO ByteString
+ hPut, -- :: Handle -> ByteString -> IO ()
+ hPutNonBlocking, -- :: Handle -> ByteString -> IO ByteString
+ hPutStr, -- :: Handle -> ByteString -> IO ()
+ hPutStrLn, -- :: Handle -> ByteString -> IO ()
+
+ breakByte
+
+ ) where
+
+import qualified Prelude as P
+import Prelude hiding (reverse,head,tail,last,init,null
+ ,length,map,lines,foldl,foldr,unlines
+ ,concat,any,take,drop,splitAt,takeWhile
+ ,dropWhile,span,break,elem,filter,maximum
+ ,minimum,all,concatMap,foldl1,foldr1
+ ,scanl,scanl1,scanr,scanr1
+ ,readFile,writeFile,appendFile,replicate
+ ,getContents,getLine,putStr,putStrLn,interact
+ ,zip,zipWith,unzip,notElem)
+
+import Data.ByteString.Internal
+import Data.ByteString.Unsafe
+
+import qualified Data.List as List
+
+import Data.Word (Word8)
+import Data.Maybe (isJust, listToMaybe)
+
+-- Control.Exception.assert not available in yhc or nhc
+#ifndef __NHC__
+import Control.Exception (finally, bracket, assert, throwIO)
+#else
+import Control.Exception (bracket, finally)
+#endif
+import Control.Monad (when)
+
+import Foreign.C.String (CString, CStringLen)
+import Foreign.C.Types (CSize)
+import Foreign.ForeignPtr
+import Foreign.Marshal.Alloc (allocaBytes, mallocBytes, reallocBytes, finalizerFree)
+import Foreign.Marshal.Array (allocaArray)
+import Foreign.Ptr
+import Foreign.Storable (Storable(..))
+
+-- hGetBuf and hPutBuf not available in yhc or nhc
+import System.IO (stdin,stdout,hClose,hFileSize
+ ,hGetBuf,hPutBuf,openBinaryFile
+ ,IOMode(..))
+import System.IO.Error (mkIOError, illegalOperationErrorType)
+
+import Data.Monoid (Monoid(..))
+
+#if !defined(__GLASGOW_HASKELL__)
+import System.IO.Unsafe
+import qualified System.Environment
+import qualified System.IO (hGetLine)
+import System.IO (hIsEOF)
+#endif
+
+#if defined(__GLASGOW_HASKELL__)
+
+import System.IO (hGetBufNonBlocking, hPutBufNonBlocking)
+
+#if MIN_VERSION_base(4,3,0)
+import System.IO (hGetBufSome)
+#else
+import System.IO (hWaitForInput, hIsEOF)
+#endif
+
+#if __GLASGOW_HASKELL__ >= 611
+import Data.IORef
+import GHC.IO.Handle.Internals
+import GHC.IO.Handle.Types
+import GHC.IO.Buffer
+import GHC.IO.BufferedIO as Buffered
+import GHC.IO (unsafePerformIO)
+import Data.Char (ord)
+import Foreign.Marshal.Utils (copyBytes)
+#else
+import System.IO.Error (isEOFError)
+import GHC.IOBase
+import GHC.Handle
+#endif
+
+import GHC.Prim (Word#)
+import GHC.Base (build)
+import GHC.Word hiding (Word8)
+
+#endif
+
+-- An alternative to Control.Exception (assert) for nhc98
+#ifdef __NHC__
+
+import System.IO (Handle)
+
+#define assert assertS "__FILE__ : __LINE__"
+assertS :: String -> Bool -> a -> a
+assertS _ True = id
+assertS s False = error ("assertion failed at "++s)
+
+-- An alternative to hWaitForInput
+hWaitForInput :: Handle -> Int -> IO ()
+hWaitForInput _ _ = return ()
+#endif
+
+-- -----------------------------------------------------------------------------
+--
+-- Useful macros, until we have bang patterns
+--
+
+#define STRICT1(f) f a | a `seq` False = undefined
+#define STRICT2(f) f a b | a `seq` b `seq` False = undefined
+#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
+#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined
+#define STRICT5(f) f a b c d e | a `seq` b `seq` c `seq` d `seq` e `seq` False = undefined
+
+-- -----------------------------------------------------------------------------
+-- Introducing and eliminating 'ByteString's
+
+-- | /O(1)/ The empty 'ByteString'
+empty :: ByteString
+empty = PS nullForeignPtr 0 0
+
+-- | /O(1)/ Convert a 'Word8' into a 'ByteString'
+singleton :: Word8 -> ByteString
+singleton c = unsafeCreate 1 $ \p -> poke p c
+{-# INLINE [1] singleton #-}
+
+-- Inline [1] for intercalate rule
+
+--
+-- XXX The use of unsafePerformIO in allocating functions (unsafeCreate) is critical!
+--
+-- Otherwise:
+--
+-- singleton 255 `compare` singleton 127
+--
+-- is compiled to:
+--
+-- case mallocByteString 2 of
+-- ForeignPtr f internals ->
+-- case writeWord8OffAddr# f 0 255 of _ ->
+-- case writeWord8OffAddr# f 0 127 of _ ->
+-- case eqAddr# f f of
+-- False -> case compare (GHC.Prim.plusAddr# f 0)
+-- (GHC.Prim.plusAddr# f 0)
+--
+--
+
+-- | /O(n)/ Convert a '[Word8]' into a 'ByteString'.
+--
+-- For applications with large numbers of string literals, pack can be a
+-- bottleneck. In such cases, consider using packAddress (GHC only).
+pack :: [Word8] -> ByteString
+pack = packBytes
+
+-- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.
+unpack :: ByteString -> [Word8]
+#if !defined(__GLASGOW_HASKELL__)
+unpack = unpackBytes
+#else
+
+unpack ps = build (unpackFoldr ps)
+{-# INLINE unpack #-}
+
+--
+-- Have unpack fuse with good list consumers
+--
+-- critical this isn't strict in the acc
+-- as it will break in the presence of list fusion. this is a known
+-- issue with seq and build/foldr rewrite rules, which rely on lazy
+-- demanding to avoid bottoms in the list.
+--
+unpackFoldr :: ByteString -> (Word8 -> a -> a) -> a -> a
+unpackFoldr (PS fp off len) f ch = withPtr fp $ \p -> do
+ let loop q n _ | q `seq` n `seq` False = undefined -- n.b.
+ loop _ (-1) acc = return acc
+ loop q n acc = do
+ a <- peekByteOff q n
+ loop q (n-1) (a `f` acc)
+ loop (p `plusPtr` off) (len-1) ch
+{-# INLINE [0] unpackFoldr #-}
+
+{-# RULES
+"ByteString unpack-list" [1] forall p .
+ unpackFoldr p (:) [] = unpackBytes p
+ #-}
+
+#endif
+
+-- ---------------------------------------------------------------------
+-- Basic interface
+
+-- | /O(1)/ Test whether a ByteString is empty.
+null :: ByteString -> Bool
+null (PS _ _ l) = assert (l >= 0) $ l <= 0
+{-# INLINE null #-}
+
+-- ---------------------------------------------------------------------
+-- | /O(1)/ 'length' returns the length of a ByteString as an 'Int'.
+length :: ByteString -> Int
+length (PS _ _ l) = assert (l >= 0) $ l
+{-# INLINE length #-}
+
+------------------------------------------------------------------------
+
+infixr 5 `cons` --same as list (:)
+infixl 5 `snoc`
+
+-- | /O(n)/ 'cons' is analogous to (:) for lists, but of different
+-- complexity, as it requires a memcpy.
+cons :: Word8 -> ByteString -> ByteString
+cons c (PS x s l) = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do
+ poke p c
+ memcpy (p `plusPtr` 1) (f `plusPtr` s) (fromIntegral l)
+{-# INLINE cons #-}
+
+-- | /O(n)/ Append a byte to the end of a 'ByteString'
+snoc :: ByteString -> Word8 -> ByteString
+snoc (PS x s l) c = unsafeCreate (l+1) $ \p -> withForeignPtr x $ \f -> do
+ memcpy p (f `plusPtr` s) (fromIntegral l)
+ poke (p `plusPtr` l) c
+{-# INLINE snoc #-}
+
+-- todo fuse
+
+-- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.
+-- An exception will be thrown in the case of an empty ByteString.
+head :: ByteString -> Word8
+head (PS x s l)
+ | l <= 0 = errorEmptyList "head"
+ | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p s
+{-# INLINE head #-}
+
+-- | /O(1)/ Extract the elements after the head of a ByteString, which must be non-empty.
+-- An exception will be thrown in the case of an empty ByteString.
+tail :: ByteString -> ByteString
+tail (PS p s l)
+ | l <= 0 = errorEmptyList "tail"
+ | otherwise = PS p (s+1) (l-1)
+{-# INLINE tail #-}
+
+-- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing
+-- if it is empty.
+uncons :: ByteString -> Maybe (Word8, ByteString)
+uncons (PS x s l)
+ | l <= 0 = Nothing
+ | otherwise = Just (inlinePerformIO $ withForeignPtr x
+ $ \p -> peekByteOff p s,
+ PS x (s+1) (l-1))
+{-# INLINE uncons #-}
+
+-- | /O(1)/ Extract the last element of a ByteString, which must be finite and non-empty.
+-- An exception will be thrown in the case of an empty ByteString.
+last :: ByteString -> Word8
+last ps@(PS x s l)
+ | null ps = errorEmptyList "last"
+ | otherwise = inlinePerformIO $ withForeignPtr x $ \p -> peekByteOff p (s+l-1)
+{-# INLINE last #-}
+
+-- | /O(1)/ Return all the elements of a 'ByteString' except the last one.
+-- An exception will be thrown in the case of an empty ByteString.
+init :: ByteString -> ByteString
+init ps@(PS p s l)
+ | null ps = errorEmptyList "init"
+ | otherwise = PS p s (l-1)
+{-# INLINE init #-}
+
+-- | /O(n)/ Append two ByteStrings
+append :: ByteString -> ByteString -> ByteString
+append = mappend
+{-# INLINE append #-}
+
+-- ---------------------------------------------------------------------
+-- Transformations
+
+-- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each
+-- element of @xs@. This function is subject to array fusion.
+map :: (Word8 -> Word8) -> ByteString -> ByteString
+map f (PS fp s len) = inlinePerformIO $ withForeignPtr fp $ \a ->
+ create len $ map_ 0 (a `plusPtr` s)
+ where
+ map_ :: Int -> Ptr Word8 -> Ptr Word8 -> IO ()
+ STRICT3(map_)
+ map_ n p1 p2
+ | n >= len = return ()
+ | otherwise = do
+ x <- peekByteOff p1 n
+ pokeByteOff p2 n (f x)
+ map_ (n+1) p1 p2
+{-# INLINE map #-}
+
+-- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order.
+reverse :: ByteString -> ByteString
+reverse (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->
+ c_reverse p (f `plusPtr` s) (fromIntegral l)
+
+-- | /O(n)/ The 'intersperse' function takes a 'Word8' and a
+-- 'ByteString' and \`intersperses\' that byte between the elements of
+-- the 'ByteString'. It is analogous to the intersperse function on
+-- Lists.
+intersperse :: Word8 -> ByteString -> ByteString
+intersperse c ps@(PS x s l)
+ | length ps < 2 = ps
+ | otherwise = unsafeCreate (2*l-1) $ \p -> withForeignPtr x $ \f ->
+ c_intersperse p (f `plusPtr` s) (fromIntegral l) c
+
+-- | The 'transpose' function transposes the rows and columns of its
+-- 'ByteString' argument.
+transpose :: [ByteString] -> [ByteString]
+transpose ps = P.map pack (List.transpose (P.map unpack ps))
+
+-- ---------------------------------------------------------------------
+-- Reducing 'ByteString's
+
+-- | 'foldl', applied to a binary operator, a starting value (typically
+-- the left-identity of the operator), and a ByteString, reduces the
+-- ByteString using the binary operator, from left to right.
+--
+-- This function is subject to array fusion.
+--
+foldl :: (a -> Word8 -> a) -> a -> ByteString -> a
+foldl f v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
+ lgo v (ptr `plusPtr` s) (ptr `plusPtr` (s+l))
+ where
+ STRICT3(lgo)
+ lgo z p q | p == q = return z
+ | otherwise = do c <- peek p
+ lgo (f z c) (p `plusPtr` 1) q
+{-# INLINE foldl #-}
+
+-- | 'foldl\'' is like 'foldl', but strict in the accumulator.
+-- However, for ByteStrings, all left folds are strict in the accumulator.
+--
+foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a
+foldl' = foldl
+{-# INLINE foldl' #-}
+
+-- | 'foldr', applied to a binary operator, a starting value
+-- (typically the right-identity of the operator), and a ByteString,
+-- reduces the ByteString using the binary operator, from right to left.
+foldr :: (Word8 -> a -> a) -> a -> ByteString -> a
+foldr k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
+ go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))
+ where
+ STRICT3(go)
+ go z p q | p == q = return z
+ | otherwise = do c <- peek p
+ go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive
+{-# INLINE foldr #-}
+
+-- | 'foldr\'' is like 'foldr', but strict in the accumulator.
+foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a
+foldr' k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
+ go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))
+ where
+ STRICT3(go)
+ go z p q | p == q = return z
+ | otherwise = do c <- peek p
+ go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive
+{-# INLINE foldr' #-}
+
+-- | 'foldl1' is a variant of 'foldl' that has no starting value
+-- argument, and thus must be applied to non-empty 'ByteStrings'.
+-- This function is subject to array fusion.
+-- An exception will be thrown in the case of an empty ByteString.
+foldl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+foldl1 f ps
+ | null ps = errorEmptyList "foldl1"
+ | otherwise = foldl f (unsafeHead ps) (unsafeTail ps)
+{-# INLINE foldl1 #-}
+
+-- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.
+-- An exception will be thrown in the case of an empty ByteString.
+foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+foldl1' f ps
+ | null ps = errorEmptyList "foldl1'"
+ | otherwise = foldl' f (unsafeHead ps) (unsafeTail ps)
+{-# INLINE foldl1' #-}
+
+-- | 'foldr1' is a variant of 'foldr' that has no starting value argument,
+-- and thus must be applied to non-empty 'ByteString's
+-- An exception will be thrown in the case of an empty ByteString.
+foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+foldr1 f ps
+ | null ps = errorEmptyList "foldr1"
+ | otherwise = foldr f (last ps) (init ps)
+{-# INLINE foldr1 #-}
+
+-- | 'foldr1\'' is a variant of 'foldr1', but is strict in the
+-- accumulator.
+foldr1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
+foldr1' f ps
+ | null ps = errorEmptyList "foldr1"
+ | otherwise = foldr' f (last ps) (init ps)
+{-# INLINE foldr1' #-}
+
+-- ---------------------------------------------------------------------
+-- Special folds
+
+-- | /O(n)/ Concatenate a list of ByteStrings.
+concat :: [ByteString] -> ByteString
+concat = mconcat
+
+-- | Map a function over a 'ByteString' and concatenate the results
+concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString
+concatMap f = concat . foldr ((:) . f) []
+
+-- foldr (append . f) empty
+
+-- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if
+-- any element of the 'ByteString' satisfies the predicate.
+any :: (Word8 -> Bool) -> ByteString -> Bool
+any _ (PS _ _ 0) = False
+any f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
+ go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))
+ where
+ STRICT2(go)
+ go p q | p == q = return False
+ | otherwise = do c <- peek p
+ if f c then return True
+ else go (p `plusPtr` 1) q
+{-# INLINE any #-}
+
+-- todo fuse
+
+-- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines
+-- if all elements of the 'ByteString' satisfy the predicate.
+all :: (Word8 -> Bool) -> ByteString -> Bool
+all _ (PS _ _ 0) = True
+all f (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
+ go (ptr `plusPtr` s) (ptr `plusPtr` (s+l))
+ where
+ STRICT2(go)
+ go p q | p == q = return True -- end of list
+ | otherwise = do c <- peek p
+ if f c
+ then go (p `plusPtr` 1) q
+ else return False
+{-# INLINE all #-}
+
+------------------------------------------------------------------------
+
+-- | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'
+-- This function will fuse.
+-- An exception will be thrown in the case of an empty ByteString.
+maximum :: ByteString -> Word8
+maximum xs@(PS x s l)
+ | null xs = errorEmptyList "maximum"
+ | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->
+ c_maximum (p `plusPtr` s) (fromIntegral l)
+{-# INLINE maximum #-}
+
+-- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'
+-- This function will fuse.
+-- An exception will be thrown in the case of an empty ByteString.
+minimum :: ByteString -> Word8
+minimum xs@(PS x s l)
+ | null xs = errorEmptyList "minimum"
+ | otherwise = inlinePerformIO $ withForeignPtr x $ \p ->
+ c_minimum (p `plusPtr` s) (fromIntegral l)
+{-# INLINE minimum #-}
+
+------------------------------------------------------------------------
+
+-- | The 'mapAccumL' function behaves like a combination of 'map' and
+-- 'foldl'; it applies a function to each element of a ByteString,
+-- passing an accumulating parameter from left to right, and returning a
+-- final value of this accumulator together with the new list.
+mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
+mapAccumL f acc (PS fp o len) = inlinePerformIO $ withForeignPtr fp $ \a -> do
+ gp <- mallocByteString len
+ acc' <- withForeignPtr gp $ \p -> mapAccumL_ acc 0 (a `plusPtr` o) p
+ return $! (acc', PS gp 0 len)
+ where
+ STRICT4(mapAccumL_)
+ mapAccumL_ s n p1 p2
+ | n >= len = return s
+ | otherwise = do
+ x <- peekByteOff p1 n
+ let (s', y) = f s x
+ pokeByteOff p2 n y
+ mapAccumL_ s' (n+1) p1 p2
+{-# INLINE mapAccumL #-}
+
+-- | The 'mapAccumR' function behaves like a combination of 'map' and
+-- 'foldr'; it applies a function to each element of a ByteString,
+-- passing an accumulating parameter from right to left, and returning a
+-- final value of this accumulator together with the new ByteString.
+mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
+mapAccumR f acc (PS fp o len) = inlinePerformIO $ withForeignPtr fp $ \a -> do
+ gp <- mallocByteString len
+ acc' <- withForeignPtr gp $ \p -> mapAccumR_ acc (len-1) (a `plusPtr` o) p
+ return $! (acc', PS gp 0 len)
+ where
+ STRICT4(mapAccumR_)
+ mapAccumR_ s n p q
+ | n < 0 = return s
+ | otherwise = do
+ x <- peekByteOff p n
+ let (s', y) = f s x
+ pokeByteOff q n y
+ mapAccumR_ s' (n-1) p q
+{-# INLINE mapAccumR #-}
+
+-- ---------------------------------------------------------------------
+-- Building ByteStrings
+
+-- | 'scanl' is similar to 'foldl', but returns a list of successive
+-- reduced values from the left. This function will fuse.
+--
+-- > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
+--
+-- Note that
+--
+-- > last (scanl f z xs) == foldl f z xs.
+--
+scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
+
+scanl f v (PS fp s len) = inlinePerformIO $ withForeignPtr fp $ \a ->
+ create (len+1) $ \q -> do
+ poke q v
+ scanl_ v 0 (a `plusPtr` s) (q `plusPtr` 1)
+ where
+ STRICT4(scanl_)
+ scanl_ z n p q
+ | n >= len = return ()
+ | otherwise = do
+ x <- peekByteOff p n
+ let z' = f z x
+ pokeByteOff q n z'
+ scanl_ z' (n+1) p q
+{-# INLINE scanl #-}
+
+ -- n.b. haskell's List scan returns a list one bigger than the
+ -- input, so we need to snoc here to get some extra space, however,
+ -- it breaks map/up fusion (i.e. scanl . map no longer fuses)
+
+-- | 'scanl1' is a variant of 'scanl' that has no starting value argument.
+-- This function will fuse.
+--
+-- > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
+scanl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
+scanl1 f ps
+ | null ps = empty
+ | otherwise = scanl f (unsafeHead ps) (unsafeTail ps)
+{-# INLINE scanl1 #-}
+
+-- | scanr is the right-to-left dual of scanl.
+scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
+scanr f v (PS fp s len) = inlinePerformIO $ withForeignPtr fp $ \a ->
+ create (len+1) $ \q -> do
+ poke (q `plusPtr` len) v
+ scanr_ v (len-1) (a `plusPtr` s) q
+ where
+ STRICT4(scanr_)
+ scanr_ z n p q
+ | n < 0 = return ()
+ | otherwise = do
+ x <- peekByteOff p n
+ let z' = f x z
+ pokeByteOff q n z'
+ scanr_ z' (n-1) p q
+{-# INLINE scanr #-}
+
+-- | 'scanr1' is a variant of 'scanr' that has no starting value argument.
+scanr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
+scanr1 f ps
+ | null ps = empty
+ | otherwise = scanr f (last ps) (init ps) -- todo, unsafe versions
+{-# INLINE scanr1 #-}
+
+-- ---------------------------------------------------------------------
+-- Unfolds and replicates
+
+-- | /O(n)/ 'replicate' @n x@ is a ByteString of length @n@ with @x@
+-- the value of every element. The following holds:
+--
+-- > replicate w c = unfoldr w (\u -> Just (u,u)) c
+--
+-- This implemenation uses @memset(3)@
+replicate :: Int -> Word8 -> ByteString
+replicate w c
+ | w <= 0 = empty
+ | otherwise = unsafeCreate w $ \ptr ->
+ memset ptr c (fromIntegral w) >> return ()
+
+-- | /O(n)/, where /n/ is the length of the result. The 'unfoldr'
+-- function is analogous to the List \'unfoldr\'. 'unfoldr' builds a
+-- ByteString from a seed value. The function takes the element and
+-- returns 'Nothing' if it is done producing the ByteString or returns
+-- 'Just' @(a,b)@, in which case, @a@ is the next byte in the string,
+-- and @b@ is the seed value for further production.
+--
+-- Examples:
+--
+-- > unfoldr (\x -> if x <= 5 then Just (x, x + 1) else Nothing) 0
+-- > == pack [0, 1, 2, 3, 4, 5]
+--
+unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString
+unfoldr f = concat . unfoldChunk 32 64
+ where unfoldChunk n n' x =
+ case unfoldrN n f x of
+ (s, Nothing) -> s : []
+ (s, Just x') -> s : unfoldChunk n' (n+n') x'
+{-# INLINE unfoldr #-}
+
+-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ByteString from a seed
+-- value. However, the length of the result is limited by the first
+-- argument to 'unfoldrN'. This function is more efficient than 'unfoldr'
+-- when the maximum length of the result is known.
+--
+-- The following equation relates 'unfoldrN' and 'unfoldr':
+--
+-- > snd (unfoldrN n f s) == take n (unfoldr f s)
+--
+unfoldrN :: Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
+unfoldrN i f x0
+ | i < 0 = (empty, Just x0)
+ | otherwise = unsafePerformIO $ createAndTrim' i $ \p -> go p x0 0
+ where STRICT3(go)
+ go p x n =
+ case f x of
+ Nothing -> return (0, n, Nothing)
+ Just (w,x')
+ | n == i -> return (0, n, Just x)
+ | otherwise -> do poke p w
+ go (p `plusPtr` 1) x' (n+1)
+{-# INLINE unfoldrN #-}
+
+-- ---------------------------------------------------------------------
+-- Substrings
+
+-- | /O(1)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix
+-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.
+take :: Int -> ByteString -> ByteString
+take n ps@(PS x s l)
+ | n <= 0 = empty
+ | n >= l = ps
+ | otherwise = PS x s n
+{-# INLINE take #-}
+
+-- | /O(1)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@
+-- elements, or @[]@ if @n > 'length' xs@.
+drop :: Int -> ByteString -> ByteString
+drop n ps@(PS x s l)
+ | n <= 0 = ps
+ | n >= l = empty
+ | otherwise = PS x (s+n) (l-n)
+{-# INLINE drop #-}
+
+-- | /O(1)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.
+splitAt :: Int -> ByteString -> (ByteString, ByteString)
+splitAt n ps@(PS x s l)
+ | n <= 0 = (empty, ps)
+ | n >= l = (ps, empty)
+ | otherwise = (PS x s n, PS x (s+n) (l-n))
+{-# INLINE splitAt #-}
+
+-- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,
+-- returns the longest prefix (possibly empty) of @xs@ of elements that
+-- satisfy @p@.
+takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString
+takeWhile f ps = unsafeTake (findIndexOrEnd (not . f) ps) ps
+{-# INLINE takeWhile #-}
+
+-- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.
+dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString
+dropWhile f ps = unsafeDrop (findIndexOrEnd (not . f) ps) ps
+{-# INLINE dropWhile #-}
+
+-- instead of findIndexOrEnd, we could use memchr here.
+
+-- | 'break' @p@ is equivalent to @'span' ('not' . p)@.
+--
+-- Under GHC, a rewrite rule will transform break (==) into a
+-- call to the specialised breakByte:
+--
+-- > break ((==) x) = breakByte x
+-- > break (==x) = breakByte x
+--
+break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+break p ps = case findIndexOrEnd p ps of n -> (unsafeTake n ps, unsafeDrop n ps)
+#if __GLASGOW_HASKELL__
+{-# INLINE [1] break #-}
+#endif
+
+{-# RULES
+"ByteString specialise break (x==)" forall x.
+ break ((==) x) = breakByte x
+"ByteString specialise break (==x)" forall x.
+ break (==x) = breakByte x
+ #-}
+
+-- INTERNAL:
+
+-- | 'breakByte' breaks its ByteString argument at the first occurence
+-- of the specified byte. It is more efficient than 'break' as it is
+-- implemented with @memchr(3)@. I.e.
+--
+-- > break (=='c') "abcd" == breakByte 'c' "abcd"
+--
+breakByte :: Word8 -> ByteString -> (ByteString, ByteString)
+breakByte c p = case elemIndex c p of
+ Nothing -> (p,empty)
+ Just n -> (unsafeTake n p, unsafeDrop n p)
+{-# INLINE breakByte #-}
+
+-- | 'breakEnd' behaves like 'break' but from the end of the 'ByteString'
+--
+-- breakEnd p == spanEnd (not.p)
+breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+breakEnd p ps = splitAt (findFromEndUntil p ps) ps
+
+-- | 'span' @p xs@ breaks the ByteString into two segments. It is
+-- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@
+span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+span p ps = break (not . p) ps
+#if __GLASGOW_HASKELL__
+{-# INLINE [1] span #-}
+#endif
+
+-- | 'spanByte' breaks its ByteString argument at the first
+-- occurence of a byte other than its argument. It is more efficient
+-- than 'span (==)'
+--
+-- > span (=='c') "abcd" == spanByte 'c' "abcd"
+--
+spanByte :: Word8 -> ByteString -> (ByteString, ByteString)
+spanByte c ps@(PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->
+ go (p `plusPtr` s) 0
+ where
+ STRICT2(go)
+ go p i | i >= l = return (ps, empty)
+ | otherwise = do c' <- peekByteOff p i
+ if c /= c'
+ then return (unsafeTake i ps, unsafeDrop i ps)
+ else go p (i+1)
+{-# INLINE spanByte #-}
+
+{-# RULES
+"ByteString specialise span (x==)" forall x.
+ span ((==) x) = spanByte x
+"ByteString specialise span (==x)" forall x.
+ span (==x) = spanByte x
+ #-}
+
+-- | 'spanEnd' behaves like 'span' but from the end of the 'ByteString'.
+-- We have
+--
+-- > spanEnd (not.isSpace) "x y z" == ("x y ","z")
+--
+-- and
+--
+-- > spanEnd (not . isSpace) ps
+-- > ==
+-- > let (x,y) = span (not.isSpace) (reverse ps) in (reverse y, reverse x)
+--
+spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+spanEnd p ps = splitAt (findFromEndUntil (not.p) ps) ps
+
+-- | /O(n)/ Splits a 'ByteString' into components delimited by
+-- separators, where the predicate returns True for a separator element.
+-- The resulting components do not contain the separators. Two adjacent
+-- separators result in an empty component in the output. eg.
+--
+-- > splitWith (=='a') "aabbaca" == ["","","bb","c",""]
+-- > splitWith (=='a') [] == []
+--
+splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]
+
+#if defined(__GLASGOW_HASKELL__)
+splitWith _pred (PS _ _ 0) = []
+splitWith pred_ (PS fp off len) = splitWith0 pred# off len fp
+ where pred# c# = pred_ (W8# c#)
+
+ STRICT4(splitWith0)
+ splitWith0 pred' off' len' fp' = withPtr fp $ \p ->
+ splitLoop pred' p 0 off' len' fp'
+
+ splitLoop :: (Word# -> Bool)
+ -> Ptr Word8
+ -> Int -> Int -> Int
+ -> ForeignPtr Word8
+ -> IO [ByteString]
+
+ splitLoop pred' p idx' off' len' fp'
+ | idx' >= len' = return [PS fp' off' idx']
+ | otherwise = do
+ w <- peekElemOff p (off'+idx')
+ if pred' (case w of W8# w# -> w#)
+ then return (PS fp' off' idx' :
+ splitWith0 pred' (off'+idx'+1) (len'-idx'-1) fp')
+ else splitLoop pred' p (idx'+1) off' len' fp'
+{-# INLINE splitWith #-}
+
+#else
+splitWith _ (PS _ _ 0) = []
+splitWith p ps = loop p ps
+ where
+ STRICT2(loop)
+ loop q qs = if null rest then [chunk]
+ else chunk : loop q (unsafeTail rest)
+ where (chunk,rest) = break q qs
+#endif
+
+-- | /O(n)/ Break a 'ByteString' into pieces separated by the byte
+-- argument, consuming the delimiter. I.e.
+--
+-- > split '\n' "a\nb\nd\ne" == ["a","b","d","e"]
+-- > split 'a' "aXaXaXa" == ["","X","X","X",""]
+-- > split 'x' "x" == ["",""]
+--
+-- and
+--
+-- > intercalate [c] . split c == id
+-- > split == splitWith . (==)
+--
+-- As for all splitting functions in this library, this function does
+-- not copy the substrings, it just constructs new 'ByteStrings' that
+-- are slices of the original.
+--
+split :: Word8 -> ByteString -> [ByteString]
+split _ (PS _ _ 0) = []
+split w (PS x s l) = loop 0
+ where
+ STRICT1(loop)
+ loop n =
+ let q = inlinePerformIO $ withForeignPtr x $ \p ->
+ memchr (p `plusPtr` (s+n))
+ w (fromIntegral (l-n))
+ in if q == nullPtr
+ then [PS x (s+n) (l-n)]
+ else let i = inlinePerformIO $ withForeignPtr x $ \p ->
+ return (q `minusPtr` (p `plusPtr` s))
+ in PS x (s+n) (i-n) : loop (i+1)
+
+{-# INLINE split #-}
+
+{-
+-- slower. but stays inside Haskell.
+split _ (PS _ _ 0) = []
+split (W8# w#) (PS fp off len) = splitWith' off len fp
+ where
+ splitWith' off' len' fp' = withPtr fp $ \p ->
+ splitLoop p 0 off' len' fp'
+
+ splitLoop :: Ptr Word8
+ -> Int -> Int -> Int
+ -> ForeignPtr Word8
+ -> IO [ByteString]
+
+ STRICT5(splitLoop)
+ splitLoop p idx' off' len' fp'
+ | idx' >= len' = return [PS fp' off' idx']
+ | otherwise = do
+ (W8# x#) <- peekElemOff p (off'+idx')
+ if word2Int# w# ==# word2Int# x#
+ then return (PS fp' off' idx' :
+ splitWith' (off'+idx'+1) (len'-idx'-1) fp')
+ else splitLoop p (idx'+1) off' len' fp'
+-}
+
+{-
+-- | Like 'splitWith', except that sequences of adjacent separators are
+-- treated as a single separator. eg.
+--
+-- > tokens (=='a') "aabbaca" == ["bb","c"]
+--
+tokens :: (Word8 -> Bool) -> ByteString -> [ByteString]
+tokens f = P.filter (not.null) . splitWith f
+{-# INLINE tokens #-}
+-}
+
+-- | The 'group' function takes a ByteString and returns a list of
+-- ByteStrings such that the concatenation of the result is equal to the
+-- argument. Moreover, each sublist in the result contains only equal
+-- elements. For example,
+--
+-- > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]
+--
+-- It is a special case of 'groupBy', which allows the programmer to
+-- supply their own equality test. It is about 40% faster than
+-- /groupBy (==)/
+group :: ByteString -> [ByteString]
+group xs
+ | null xs = []
+ | otherwise = ys : group zs
+ where
+ (ys, zs) = spanByte (unsafeHead xs) xs
+
+-- | The 'groupBy' function is the non-overloaded version of 'group'.
+groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]
+groupBy k xs
+ | null xs = []
+ | otherwise = unsafeTake n xs : groupBy k (unsafeDrop n xs)
+ where
+ n = 1 + findIndexOrEnd (not . k (unsafeHead xs)) (unsafeTail xs)
+
+-- | /O(n)/ The 'intercalate' function takes a 'ByteString' and a list of
+-- 'ByteString's and concatenates the list after interspersing the first
+-- argument between each element of the list.
+intercalate :: ByteString -> [ByteString] -> ByteString
+intercalate s = concat . (List.intersperse s)
+{-# INLINE [1] intercalate #-}
+
+{-# RULES
+"ByteString specialise intercalate c -> intercalateByte" forall c s1 s2 .
+ intercalate (singleton c) (s1 : s2 : []) = intercalateWithByte c s1 s2
+ #-}
+
+-- | /O(n)/ intercalateWithByte. An efficient way to join to two ByteStrings
+-- with a char. Around 4 times faster than the generalised join.
+--
+intercalateWithByte :: Word8 -> ByteString -> ByteString -> ByteString
+intercalateWithByte c f@(PS ffp s l) g@(PS fgp t m) = unsafeCreate len $ \ptr ->
+ withForeignPtr ffp $ \fp ->
+ withForeignPtr fgp $ \gp -> do
+ memcpy ptr (fp `plusPtr` s) (fromIntegral l)
+ poke (ptr `plusPtr` l) c
+ memcpy (ptr `plusPtr` (l + 1)) (gp `plusPtr` t) (fromIntegral m)
+ where
+ len = length f + length g + 1
+{-# INLINE intercalateWithByte #-}
+
+-- ---------------------------------------------------------------------
+-- Indexing ByteStrings
+
+-- | /O(1)/ 'ByteString' index (subscript) operator, starting from 0.
+index :: ByteString -> Int -> Word8
+index ps n
+ | n < 0 = moduleError "index" ("negative index: " ++ show n)
+ | n >= length ps = moduleError "index" ("index too large: " ++ show n
+ ++ ", length = " ++ show (length ps))
+ | otherwise = ps `unsafeIndex` n
+{-# INLINE index #-}
+
+-- | /O(n)/ The 'elemIndex' function returns the index of the first
+-- element in the given 'ByteString' which is equal to the query
+-- element, or 'Nothing' if there is no such element.
+-- This implementation uses memchr(3).
+elemIndex :: Word8 -> ByteString -> Maybe Int
+elemIndex c (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do
+ let p' = p `plusPtr` s
+ q <- memchr p' c (fromIntegral l)
+ return $! if q == nullPtr then Nothing else Just $! q `minusPtr` p'
+{-# INLINE elemIndex #-}
+
+-- | /O(n)/ The 'elemIndexEnd' function returns the last index of the
+-- element in the given 'ByteString' which is equal to the query
+-- element, or 'Nothing' if there is no such element. The following
+-- holds:
+--
+-- > elemIndexEnd c xs ==
+-- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)
+--
+elemIndexEnd :: Word8 -> ByteString -> Maybe Int
+elemIndexEnd ch (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p ->
+ go (p `plusPtr` s) (l-1)
+ where
+ STRICT2(go)
+ go p i | i < 0 = return Nothing
+ | otherwise = do ch' <- peekByteOff p i
+ if ch == ch'
+ then return $ Just i
+ else go p (i-1)
+{-# INLINE elemIndexEnd #-}
+
+-- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning
+-- the indices of all elements equal to the query element, in ascending order.
+-- This implementation uses memchr(3).
+elemIndices :: Word8 -> ByteString -> [Int]
+elemIndices w (PS x s l) = loop 0
+ where
+ STRICT1(loop)
+ loop n = let q = inlinePerformIO $ withForeignPtr x $ \p ->
+ memchr (p `plusPtr` (n+s))
+ w (fromIntegral (l - n))
+ in if q == nullPtr
+ then []
+ else let i = inlinePerformIO $ withForeignPtr x $ \p ->
+ return (q `minusPtr` (p `plusPtr` s))
+ in i : loop (i+1)
+{-# INLINE elemIndices #-}
+
+{-
+-- much slower
+elemIndices :: Word8 -> ByteString -> [Int]
+elemIndices c ps = loop 0 ps
+ where STRICT2(loop)
+ loop _ ps' | null ps' = []
+ loop n ps' | c == unsafeHead ps' = n : loop (n+1) (unsafeTail ps')
+ | otherwise = loop (n+1) (unsafeTail ps')
+-}
+
+-- | count returns the number of times its argument appears in the ByteString
+--
+-- > count = length . elemIndices
+--
+-- But more efficiently than using length on the intermediate list.
+count :: Word8 -> ByteString -> Int
+count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->
+ fmap fromIntegral $ c_count (p `plusPtr` s) (fromIntegral m) w
+{-# INLINE count #-}
+
+{-
+--
+-- around 30% slower
+--
+count w (PS x s m) = inlinePerformIO $ withForeignPtr x $ \p ->
+ go (p `plusPtr` s) (fromIntegral m) 0
+ where
+ go :: Ptr Word8 -> CSize -> Int -> IO Int
+ STRICT3(go)
+ go p l i = do
+ q <- memchr p w l
+ if q == nullPtr
+ then return i
+ else do let k = fromIntegral $ q `minusPtr` p
+ go (q `plusPtr` 1) (l-k-1) (i+1)
+-}
+
+-- | The 'findIndex' function takes a predicate and a 'ByteString' and
+-- returns the index of the first element in the ByteString
+-- satisfying the predicate.
+findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int
+findIndex k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0
+ where
+ STRICT2(go)
+ go ptr n | n >= l = return Nothing
+ | otherwise = do w <- peek ptr
+ if k w
+ then return (Just n)
+ else go (ptr `plusPtr` 1) (n+1)
+{-# INLINE findIndex #-}
+
+-- | The 'findIndices' function extends 'findIndex', by returning the
+-- indices of all elements satisfying the predicate, in ascending order.
+findIndices :: (Word8 -> Bool) -> ByteString -> [Int]
+findIndices p ps = loop 0 ps
+ where
+ STRICT2(loop)
+ loop n qs | null qs = []
+ | p (unsafeHead qs) = n : loop (n+1) (unsafeTail qs)
+ | otherwise = loop (n+1) (unsafeTail qs)
+
+-- ---------------------------------------------------------------------
+-- Searching ByteStrings
+
+-- | /O(n)/ 'elem' is the 'ByteString' membership predicate.
+elem :: Word8 -> ByteString -> Bool
+elem c ps = case elemIndex c ps of Nothing -> False ; _ -> True
+{-# INLINE elem #-}
+
+-- | /O(n)/ 'notElem' is the inverse of 'elem'
+notElem :: Word8 -> ByteString -> Bool
+notElem c ps = not (elem c ps)
+{-# INLINE notElem #-}
+
+-- | /O(n)/ 'filter', applied to a predicate and a ByteString,
+-- returns a ByteString containing those characters that satisfy the
+-- predicate. This function is subject to array fusion.
+filter :: (Word8 -> Bool) -> ByteString -> ByteString
+filter k ps@(PS x s l)
+ | null ps = ps
+ | otherwise = unsafePerformIO $ createAndTrim l $ \p -> withForeignPtr x $ \f -> do
+ t <- go (f `plusPtr` s) p (f `plusPtr` (s + l))
+ return $! t `minusPtr` p -- actual length
+ where
+ STRICT3(go)
+ go f t end | f == end = return t
+ | otherwise = do
+ w <- peek f
+ if k w
+ then poke t w >> go (f `plusPtr` 1) (t `plusPtr` 1) end
+ else go (f `plusPtr` 1) t end
+{-# INLINE filter #-}
+
+{-
+--
+-- | /O(n)/ A first order equivalent of /filter . (==)/, for the common
+-- case of filtering a single byte. It is more efficient to use
+-- /filterByte/ in this case.
+--
+-- > filterByte == filter . (==)
+--
+-- filterByte is around 10x faster, and uses much less space, than its
+-- filter equivalent
+--
+filterByte :: Word8 -> ByteString -> ByteString
+filterByte w ps = replicate (count w ps) w
+{-# INLINE filterByte #-}
+
+{-# RULES
+"ByteString specialise filter (== x)" forall x.
+ filter ((==) x) = filterByte x
+"ByteString specialise filter (== x)" forall x.
+ filter (== x) = filterByte x
+ #-}
+-}
+
+-- | /O(n)/ The 'find' function takes a predicate and a ByteString,
+-- and returns the first element in matching the predicate, or 'Nothing'
+-- if there is no such element.
+--
+-- > find f p = case findIndex f p of Just n -> Just (p ! n) ; _ -> Nothing
+--
+find :: (Word8 -> Bool) -> ByteString -> Maybe Word8
+find f p = case findIndex f p of
+ Just n -> Just (p `unsafeIndex` n)
+ _ -> Nothing
+{-# INLINE find #-}
+
+{-
+--
+-- fuseable, but we don't want to walk the whole array.
+--
+find k = foldl findEFL Nothing
+ where findEFL a@(Just _) _ = a
+ findEFL _ c | k c = Just c
+ | otherwise = Nothing
+-}
+
+-- | /O(n)/ The 'partition' function takes a predicate a ByteString and returns
+-- the pair of ByteStrings with elements which do and do not satisfy the
+-- predicate, respectively; i.e.,
+--
+-- > partition p bs == (filter p xs, filter (not . p) xs)
+--
+partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
+partition p bs = (filter p bs, filter (not . p) bs)
+--TODO: use a better implementation
+
+-- ---------------------------------------------------------------------
+-- Searching for substrings
+
+-- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'
+-- iff the first is a prefix of the second.
+isPrefixOf :: ByteString -> ByteString -> Bool
+isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2)
+ | l1 == 0 = True
+ | l2 < l1 = False
+ | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->
+ withForeignPtr x2 $ \p2 -> do
+ i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2) (fromIntegral l1)
+ return $! i == 0
+
+-- | /O(n)/ The 'isSuffixOf' function takes two ByteStrings and returns 'True'
+-- iff the first is a suffix of the second.
+--
+-- The following holds:
+--
+-- > isSuffixOf x y == reverse x `isPrefixOf` reverse y
+--
+-- However, the real implemenation uses memcmp to compare the end of the
+-- string only, with no reverse required..
+isSuffixOf :: ByteString -> ByteString -> Bool
+isSuffixOf (PS x1 s1 l1) (PS x2 s2 l2)
+ | l1 == 0 = True
+ | l2 < l1 = False
+ | otherwise = inlinePerformIO $ withForeignPtr x1 $ \p1 ->
+ withForeignPtr x2 $ \p2 -> do
+ i <- memcmp (p1 `plusPtr` s1) (p2 `plusPtr` s2 `plusPtr` (l2 - l1)) (fromIntegral l1)
+ return $! i == 0
+
+-- | Check whether one string is a substring of another. @isInfixOf
+-- p s@ is equivalent to @not (null (findSubstrings p s))@.
+isInfixOf :: ByteString -> ByteString -> Bool
+isInfixOf p s = isJust (findSubstring p s)
+
+-- | Break a string on a substring, returning a pair of the part of the
+-- string prior to the match, and the rest of the string.
+--
+-- The following relationships hold:
+--
+-- > break (== c) l == breakSubstring (singleton c) l
+--
+-- and:
+--
+-- > findSubstring s l ==
+-- > if null s then Just 0
+-- > else case breakSubstring s l of
+-- > (x,y) | null y -> Nothing
+-- > | otherwise -> Just (length x)
+--
+-- For example, to tokenise a string, dropping delimiters:
+--
+-- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)
+-- > where (h,t) = breakSubstring x y
+--
+-- To skip to the first occurence of a string:
+--
+-- > snd (breakSubstring x y)
+--
+-- To take the parts of a string before a delimiter:
+--
+-- > fst (breakSubstring x y)
+--
+breakSubstring :: ByteString -- ^ String to search for
+ -> ByteString -- ^ String to search in
+ -> (ByteString,ByteString) -- ^ Head and tail of string broken at substring
+
+breakSubstring pat src = search 0 src
+ where
+ STRICT2(search)
+ search n s
+ | null s = (src,empty) -- not found
+ | pat `isPrefixOf` s = (take n src,s)
+ | otherwise = search (n+1) (unsafeTail s)
+
+-- | Get the first index of a substring in another string,
+-- or 'Nothing' if the string is not found.
+-- @findSubstring p s@ is equivalent to @listToMaybe (findSubstrings p s)@.
+findSubstring :: ByteString -- ^ String to search for.
+ -> ByteString -- ^ String to seach in.
+ -> Maybe Int
+findSubstring f i = listToMaybe (findSubstrings f i)
+
+{-# DEPRECATED findSubstring "findSubstring is deprecated in favour of breakSubstring." #-}
+
+{-
+findSubstring pat str = search 0 str
+ where
+ STRICT2(search)
+ search n s
+ = let x = pat `isPrefixOf` s
+ in
+ if null s
+ then if x then Just n else Nothing
+ else if x then Just n
+ else search (n+1) (unsafeTail s)
+-}
+
+-- | Find the indexes of all (possibly overlapping) occurances of a
+-- substring in a string.
+--
+findSubstrings :: ByteString -- ^ String to search for.
+ -> ByteString -- ^ String to seach in.
+ -> [Int]
+findSubstrings pat str
+ | null pat = [0 .. length str]
+ | otherwise = search 0 str
+ where
+ STRICT2(search)
+ search n s
+ | null s = []
+ | pat `isPrefixOf` s = n : search (n+1) (unsafeTail s)
+ | otherwise = search (n+1) (unsafeTail s)
+
+{-# DEPRECATED findSubstrings "findSubstrings is deprecated in favour of breakSubstring." #-}
+
+{-
+{- This function uses the Knuth-Morris-Pratt string matching algorithm. -}
+
+findSubstrings pat@(PS _ _ m) str@(PS _ _ n) = search 0 0
+ where
+ patc x = pat `unsafeIndex` x
+ strc x = str `unsafeIndex` x
+
+ -- maybe we should make kmpNext a UArray before using it in search?
+ kmpNext = listArray (0,m) (-1:kmpNextL pat (-1))
+ kmpNextL p _ | null p = []
+ kmpNextL p j = let j' = next (unsafeHead p) j + 1
+ ps = unsafeTail p
+ x = if not (null ps) && unsafeHead ps == patc j'
+ then kmpNext Array.! j' else j'
+ in x:kmpNextL ps j'
+ search i j = match ++ rest -- i: position in string, j: position in pattern
+ where match = if j == m then [(i - j)] else []
+ rest = if i == n then [] else search (i+1) (next (strc i) j + 1)
+ next c j | j >= 0 && (j == m || c /= patc j) = next c (kmpNext Array.! j)
+ | otherwise = j
+-}
+
+-- ---------------------------------------------------------------------
+-- Zipping
+
+-- | /O(n)/ 'zip' takes two ByteStrings and returns a list of
+-- corresponding pairs of bytes. If one input ByteString is short,
+-- excess elements of the longer ByteString are discarded. This is
+-- equivalent to a pair of 'unpack' operations.
+zip :: ByteString -> ByteString -> [(Word8,Word8)]
+zip ps qs
+ | null ps || null qs = []
+ | otherwise = (unsafeHead ps, unsafeHead qs) : zip (unsafeTail ps) (unsafeTail qs)
+
+-- | 'zipWith' generalises 'zip' by zipping with the function given as
+-- the first argument, instead of a tupling function. For example,
+-- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of
+-- corresponding sums.
+zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
+zipWith f ps qs
+ | null ps || null qs = []
+ | otherwise = f (unsafeHead ps) (unsafeHead qs) : zipWith f (unsafeTail ps) (unsafeTail qs)
+
+--
+-- | A specialised version of zipWith for the common case of a
+-- simultaneous map over two bytestrings, to build a 3rd. Rewrite rules
+-- are used to automatically covert zipWith into zipWith' when a pack is
+-- performed on the result of zipWith.
+--
+zipWith' :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
+zipWith' f (PS fp s l) (PS fq t m) = inlinePerformIO $
+ withForeignPtr fp $ \a ->
+ withForeignPtr fq $ \b ->
+ create len $ zipWith_ 0 (a `plusPtr` s) (b `plusPtr` t)
+ where
+ zipWith_ :: Int -> Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> IO ()
+ STRICT4(zipWith_)
+ zipWith_ n p1 p2 r
+ | n >= len = return ()
+ | otherwise = do
+ x <- peekByteOff p1 n
+ y <- peekByteOff p2 n
+ pokeByteOff r n (f x y)
+ zipWith_ (n+1) p1 p2 r
+
+ len = min l m
+{-# INLINE zipWith' #-}
+
+{-# RULES
+"ByteString specialise zipWith" forall (f :: Word8 -> Word8 -> Word8) p q .
+ zipWith f p q = unpack (zipWith' f p q)
+ #-}
+
+-- | /O(n)/ 'unzip' transforms a list of pairs of bytes into a pair of
+-- ByteStrings. Note that this performs two 'pack' operations.
+unzip :: [(Word8,Word8)] -> (ByteString,ByteString)
+unzip ls = (pack (P.map fst ls), pack (P.map snd ls))
+{-# INLINE unzip #-}
+
+-- ---------------------------------------------------------------------
+-- Special lists
+
+-- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first.
+inits :: ByteString -> [ByteString]
+inits (PS x s l) = [PS x s n | n <- [0..l]]
+
+-- | /O(n)/ Return all final segments of the given 'ByteString', longest first.
+tails :: ByteString -> [ByteString]
+tails p | null p = [empty]
+ | otherwise = p : tails (unsafeTail p)
+
+-- less efficent spacewise: tails (PS x s l) = [PS x (s+n) (l-n) | n <- [0..l]]
+
+-- ---------------------------------------------------------------------
+-- ** Ordered 'ByteString's
+
+-- | /O(n)/ Sort a ByteString efficiently, using counting sort.
+sort :: ByteString -> ByteString
+sort (PS input s l) = unsafeCreate l $ \p -> allocaArray 256 $ \arr -> do
+
+ _ <- memset (castPtr arr) 0 (256 * fromIntegral (sizeOf (undefined :: CSize)))
+ withForeignPtr input (\x -> countOccurrences arr (x `plusPtr` s) l)
+
+ let STRICT2(go)
+ go 256 _ = return ()
+ go i ptr = do n <- peekElemOff arr i
+ when (n /= 0) $ memset ptr (fromIntegral i) n >> return ()
+ go (i + 1) (ptr `plusPtr` (fromIntegral n))
+ go 0 p
+ where
+ -- | Count the number of occurrences of each byte.
+ -- Used by 'sort'
+ --
+ countOccurrences :: Ptr CSize -> Ptr Word8 -> Int -> IO ()
+ STRICT3(countOccurrences)
+ countOccurrences counts str len = go 0
+ where
+ STRICT1(go)
+ go i | i == len = return ()
+ | otherwise = do k <- fromIntegral `fmap` peekElemOff str i
+ x <- peekElemOff counts k
+ pokeElemOff counts k (x + 1)
+ go (i + 1)
+
+{-
+sort :: ByteString -> ByteString
+sort (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f -> do
+ memcpy p (f `plusPtr` s) l
+ c_qsort p l -- inplace
+-}
+
+-- The 'sortBy' function is the non-overloaded version of 'sort'.
+--
+-- Try some linear sorts: radix, counting
+-- Or mergesort.
+--
+-- sortBy :: (Word8 -> Word8 -> Ordering) -> ByteString -> ByteString
+-- sortBy f ps = undefined
+
+-- ---------------------------------------------------------------------
+-- Low level constructors
+
+-- | /O(n) construction/ Use a @ByteString@ with a function requiring a
+-- null-terminated @CString@. The @CString@ will be freed
+-- automatically. This is a memcpy(3).
+useAsCString :: ByteString -> (CString -> IO a) -> IO a
+useAsCString (PS fp o l) action = do
+ allocaBytes (l+1) $ \buf ->
+ withForeignPtr fp $ \p -> do
+ memcpy buf (p `plusPtr` o) (fromIntegral l)
+ pokeByteOff buf l (0::Word8)
+ action (castPtr buf)
+
+-- | /O(n) construction/ Use a @ByteString@ with a function requiring a @CStringLen@.
+-- As for @useAsCString@ this function makes a copy of the original @ByteString@.
+useAsCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a
+useAsCStringLen p@(PS _ _ l) f = useAsCString p $ \cstr -> f (cstr,l)
+
+------------------------------------------------------------------------
+
+-- | /O(n)./ Construct a new @ByteString@ from a @CString@. The
+-- resulting @ByteString@ is an immutable copy of the original
+-- @CString@, and is managed on the Haskell heap. The original
+-- @CString@ must be null terminated.
+packCString :: CString -> IO ByteString
+packCString cstr = do
+ len <- c_strlen cstr
+ packCStringLen (cstr, fromIntegral len)
+
+-- | /O(n)./ Construct a new @ByteString@ from a @CStringLen@. The
+-- resulting @ByteString@ is an immutable copy of the original @CStringLen@.
+-- The @ByteString@ is a normal Haskell value and will be managed on the
+-- Haskell heap.
+packCStringLen :: CStringLen -> IO ByteString
+packCStringLen (cstr, len) | len >= 0 = create len $ \p ->
+ memcpy p (castPtr cstr) (fromIntegral len)
+packCStringLen (_, len) =
+ moduleErrorIO "packCStringLen" ("negative length: " ++ show len)
+
+------------------------------------------------------------------------
+
+-- | /O(n)/ Make a copy of the 'ByteString' with its own storage.
+-- This is mainly useful to allow the rest of the data pointed
+-- to by the 'ByteString' to be garbage collected, for example
+-- if a large string has been read in, and only a small part of it
+-- is needed in the rest of the program.
+--
+copy :: ByteString -> ByteString
+copy (PS x s l) = unsafeCreate l $ \p -> withForeignPtr x $ \f ->
+ memcpy p (f `plusPtr` s) (fromIntegral l)
+
+-- ---------------------------------------------------------------------
+-- Line IO
+
+-- | Read a line from stdin.
+getLine :: IO ByteString
+getLine = hGetLine stdin
+
+-- | Read a line from a handle
+
+hGetLine :: Handle -> IO ByteString
+
+#if !defined(__GLASGOW_HASKELL__)
+
+hGetLine h = System.IO.hGetLine h >>= return . pack . P.map c2w
+
+#elif __GLASGOW_HASKELL__ >= 611
+
+hGetLine h =
+ wantReadableHandle_ "Data.ByteString.hGetLine" h $
+ \ h_@Handle__{haByteBuffer} -> do
+ flushCharReadBuffer h_
+ buf <- readIORef haByteBuffer
+ if isEmptyBuffer buf
+ then fill h_ buf 0 []
+ else haveBuf h_ buf 0 []
+ where
+
+ fill h_@Handle__{haByteBuffer,haDevice} buf len xss =
+ len `seq` do
+ (r,buf') <- Buffered.fillReadBuffer haDevice buf
+ if r == 0
+ then do writeIORef haByteBuffer buf{ bufR=0, bufL=0 }
+ if len > 0
+ then mkBigPS len xss
+ else ioe_EOF
+ else haveBuf h_ buf' len xss
+
+ haveBuf h_@Handle__{haByteBuffer}
+ buf@Buffer{ bufRaw=raw, bufR=w, bufL=r }
+ len xss =
+ do
+ off <- findEOL r w raw
+ let new_len = len + off - r
+ xs <- mkPS raw r off
+
+ -- if eol == True, then off is the offset of the '\n'
+ -- otherwise off == w and the buffer is now empty.
+ if off /= w
+ then do if (w == off + 1)
+ then writeIORef haByteBuffer buf{ bufL=0, bufR=0 }
+ else writeIORef haByteBuffer buf{ bufL = off + 1 }
+ mkBigPS new_len (xs:xss)
+ else do
+ fill h_ buf{ bufL=0, bufR=0 } new_len (xs:xss)
+
+ -- find the end-of-line character, if there is one
+ findEOL r w raw
+ | r == w = return w
+ | otherwise = do
+ c <- readWord8Buf raw r
+ if c == fromIntegral (ord '\n')
+ then return r -- NB. not r+1: don't include the '\n'
+ else findEOL (r+1) w raw
+
+mkPS :: RawBuffer Word8 -> Int -> Int -> IO ByteString
+mkPS buf start end =
+ create len $ \p ->
+ withRawBuffer buf $ \pbuf -> do
+ copyBytes p (pbuf `plusPtr` start) len
+ where
+ len = end - start
+
+#else
+-- GHC 6.10 and older, pre-Unicode IO library
+
+hGetLine h = wantReadableHandle "Data.ByteString.hGetLine" h $ \ handle_ -> do
+ case haBufferMode handle_ of
+ NoBuffering -> error "no buffering"
+ _other -> hGetLineBuffered handle_
+
+ where
+ hGetLineBuffered handle_ = do
+ let ref = haBuffer handle_
+ buf <- readIORef ref
+ hGetLineBufferedLoop handle_ ref buf 0 []
+
+ hGetLineBufferedLoop handle_ ref
+ buf@Buffer{ bufRPtr=r, bufWPtr=w, bufBuf=raw } len xss =
+ len `seq` do
+ off <- findEOL r w raw
+ let new_len = len + off - r
+ xs <- mkPS raw r off
+
+ -- if eol == True, then off is the offset of the '\n'
+ -- otherwise off == w and the buffer is now empty.
+ if off /= w
+ then do if (w == off + 1)
+ then writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ else writeIORef ref buf{ bufRPtr = off + 1 }
+ mkBigPS new_len (xs:xss)
+ else do
+ maybe_buf <- maybeFillReadBuffer (haFD handle_) True (haIsStream handle_)
+ buf{ bufWPtr=0, bufRPtr=0 }
+ case maybe_buf of
+ -- Nothing indicates we caught an EOF, and we may have a
+ -- partial line to return.
+ Nothing -> do
+ writeIORef ref buf{ bufRPtr=0, bufWPtr=0 }
+ if new_len > 0
+ then mkBigPS new_len (xs:xss)
+ else ioe_EOF
+ Just new_buf ->
+ hGetLineBufferedLoop handle_ ref new_buf new_len (xs:xss)
+
+ -- find the end-of-line character, if there is one
+ findEOL r w raw
+ | r == w = return w
+ | otherwise = do
+ (c,r') <- readCharFromBuffer raw r
+ if c == '\n'
+ then return r -- NB. not r': don't include the '\n'
+ else findEOL r' w raw
+
+ maybeFillReadBuffer fd is_line is_stream buf = catch
+ (do buf' <- fillReadBuffer fd is_line is_stream buf
+ return (Just buf'))
+ (\e -> if isEOFError e then return Nothing else ioError e)
+
+-- TODO, rewrite to use normal memcpy
+mkPS :: RawBuffer -> Int -> Int -> IO ByteString
+mkPS buf start end =
+ let len = end - start
+ in create len $ \p -> do
+ memcpy_ptr_baoff p buf (fromIntegral start) (fromIntegral len)
+ return ()
+
+#endif
+
+mkBigPS :: Int -> [ByteString] -> IO ByteString
+mkBigPS _ [ps] = return ps
+mkBigPS _ pss = return $! concat (P.reverse pss)
+
+-- ---------------------------------------------------------------------
+-- Block IO
+
+-- | Outputs a 'ByteString' to the specified 'Handle'.
+hPut :: Handle -> ByteString -> IO ()
+hPut _ (PS _ _ 0) = return ()
+hPut h (PS ps s l) = withForeignPtr ps $ \p-> hPutBuf h (p `plusPtr` s) l
+
+-- | Similar to 'hPut' except that it will never block. Instead it returns
+-- any tail that did not get written. This tail may be 'empty' in the case that
+-- the whole string was written, or the whole original string if nothing was
+-- written. Partial writes are also possible.
+--
+-- Note: on Windows and with Haskell implementation other than GHC, this
+-- function does not work correctly; it behaves identically to 'hPut'.
+--
+#if defined(__GLASGOW_HASKELL__)
+hPutNonBlocking :: Handle -> ByteString -> IO ByteString
+hPutNonBlocking h bs@(PS ps s l) = do
+ bytesWritten <- withForeignPtr ps $ \p-> hPutBufNonBlocking h (p `plusPtr` s) l
+ return $! drop bytesWritten bs
+#else
+hPutNonBlocking :: Handle -> B.ByteString -> IO Int
+hPutNonBlocking h bs = hPut h bs >> return empty
+#endif
+
+-- | A synonym for @hPut@, for compatibility
+hPutStr :: Handle -> ByteString -> IO ()
+hPutStr = hPut
+
+-- | Write a ByteString to a handle, appending a newline byte
+hPutStrLn :: Handle -> ByteString -> IO ()
+hPutStrLn h ps
+ | length ps < 1024 = hPut h (ps `snoc` 0x0a)
+ | otherwise = hPut h ps >> hPut h (singleton (0x0a)) -- don't copy
+
+-- | Write a ByteString to stdout
+putStr :: ByteString -> IO ()
+putStr = hPut stdout
+
+-- | Write a ByteString to stdout, appending a newline byte
+putStrLn :: ByteString -> IO ()
+putStrLn = hPutStrLn stdout
+
+{-# DEPRECATED hPutStrLn
+ "Use Data.ByteString.Char8.hPutStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Char8)"
+ #-}
+{-# DEPRECATED putStrLn
+ "Use Data.ByteString.Char8.putStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Char8)"
+ #-}
+
+------------------------------------------------------------------------
+-- 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'. First argument is the Handle to read from,
+-- and the second is the number of bytes to read. It returns the bytes
+-- read, up to n, or 'null' if EOF has been reached.
+--
+-- 'hGet' is implemented in terms of 'hGetBuf'.
+--
+-- If the handle is a pipe or socket, and the writing end
+-- is closed, 'hGet' will behave as if EOF was reached.
+--
+hGet :: Handle -> Int -> IO ByteString
+hGet h i
+ | i > 0 = createAndTrim i $ \p -> hGetBuf h p i
+ | i == 0 = return empty
+ | otherwise = illegalBufferSize h "hGet" i
+
+-- | hGetNonBlocking is similar to 'hGet', except that it will never block
+-- waiting for data to become available, instead it returns only whatever data
+-- is available. If there is no data available to be read, 'hGetNonBlocking'
+-- returns 'empty'.
+--
+-- Note: on Windows and with Haskell implementation other than GHC, this
+-- function does not work correctly; it behaves identically to 'hGet'.
+--
+hGetNonBlocking :: Handle -> Int -> IO ByteString
+#if defined(__GLASGOW_HASKELL__)
+hGetNonBlocking h i
+ | i > 0 = createAndTrim i $ \p -> hGetBufNonBlocking h p i
+ | i == 0 = return empty
+ | otherwise = illegalBufferSize h "hGetNonBlocking" i
+#else
+hGetNonBlocking = hGet
+#endif
+
+-- | Like 'hGet', except that a shorter 'ByteString' may be returned
+-- if there are not enough bytes immediately available to satisfy the
+-- whole request. 'hGetSome' only blocks if there is no data
+-- available, and EOF has not yet been reached.
+--
+hGetSome :: Handle -> Int -> IO ByteString
+hGetSome hh i
+#if MIN_VERSION_base(4,3,0)
+ | i > 0 = createAndTrim i $ \p -> hGetBufSome hh p i
+#else
+ | i > 0 = let
+ loop = do
+ s <- hGetNonBlocking hh i
+ if not (null s)
+ then return s
+ else do eof <- hIsEOF hh
+ if eof then return s
+ else hWaitForInput hh (-1) >> loop
+ -- for this to work correctly, the
+ -- Handle should be in binary mode
+ -- (see GHC ticket #3808)
+ in loop
+#endif
+ | i == 0 = return empty
+ | otherwise = illegalBufferSize hh "hGetSome" i
+
+illegalBufferSize :: Handle -> String -> Int -> IO a
+illegalBufferSize handle fn sz =
+ ioError (mkIOError illegalOperationErrorType msg (Just handle) Nothing)
+ --TODO: System.IO uses InvalidArgument here, but it's not exported :-(
+ where
+ msg = fn ++ ": illegal ByteString size " ++ showsPrec 9 sz []
+
+
+-- | 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.
+-- Consider using 'readFile' in this case.
+--
+-- 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 = always (hClose h) $ do -- strict, so hClose
+ let start_size = 1024
+ p <- mallocBytes start_size
+ i <- hGetBuf h p start_size
+ if i < start_size
+ then do p' <- reallocBytes p i
+ fp <- newForeignPtr finalizerFree p'
+ 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'
+ i <- hGetBuf h (p' `plusPtr` s) s
+ if i < s
+ then do let i' = s + i
+ p'' <- reallocBytes p' i'
+ fp <- newForeignPtr finalizerFree p''
+ return $! PS fp 0 i'
+ else f p' s'
+
+-- | 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.
+--
+interact :: (ByteString -> ByteString) -> IO ()
+interact transformer = putStr . transformer =<< getContents
+
+-- | Read an entire file strictly into a 'ByteString'. This is far more
+-- efficient than reading the characters into a 'String' and then using
+-- '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)
+
+-- | Write a 'ByteString' to a file.
+writeFile :: FilePath -> ByteString -> IO ()
+writeFile f txt = bracket (openBinaryFile f WriteMode) hClose
+ (\h -> hPut h txt)
+
+-- | Append a 'ByteString' to a file.
+appendFile :: FilePath -> ByteString -> IO ()
+appendFile f txt = bracket (openBinaryFile f AppendMode) hClose
+ (\h -> hPut h txt)
+
+-- ---------------------------------------------------------------------
+-- Internal utilities
+
+-- | 'findIndexOrEnd' is a variant of findIndex, that returns the length
+-- of the string if no element is found, rather than Nothing.
+findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int
+findIndexOrEnd k (PS x s l) = inlinePerformIO $ withForeignPtr x $ \f -> go (f `plusPtr` s) 0
+ where
+ STRICT2(go)
+ go ptr n | n >= l = return l
+ | otherwise = do w <- peek ptr
+ if k w
+ then return n
+ else go (ptr `plusPtr` 1) (n+1)
+{-# INLINE findIndexOrEnd #-}
+
+-- | Perform an operation with a temporary ByteString
+withPtr :: ForeignPtr a -> (Ptr a -> IO b) -> b
+withPtr fp io = inlinePerformIO (withForeignPtr fp io)
+{-# INLINE withPtr #-}
+
+-- Common up near identical calls to `error' to reduce the number
+-- constant strings created when compiled:
+errorEmptyList :: String -> a
+errorEmptyList fun = moduleError fun "empty ByteString"
+{-# NOINLINE errorEmptyList #-}
+
+moduleError :: String -> String -> a
+moduleError fun msg = error (moduleErrorMsg fun msg)
+{-# NOINLINE moduleError #-}
+
+moduleErrorIO :: String -> String -> IO a
+moduleErrorIO fun msg =
+#if MIN_VERSION_base(4,0,0)
+ throwIO . userError $ moduleErrorMsg fun msg
+#else
+ throwIO . IOException . userError $ moduleErrorMsg fun msg
+#endif
+{-# NOINLINE moduleErrorIO #-}
+
+moduleErrorMsg :: String -> String -> String
+moduleErrorMsg fun msg = "Data.ByteString." ++ fun ++ ':':' ':msg
+
+-- Find from the end of the string using predicate
+findFromEndUntil :: (Word8 -> Bool) -> ByteString -> Int
+STRICT2(findFromEndUntil)
+findFromEndUntil f ps@(PS x s l) =
+ if null ps then 0
+ else if f (last ps) then l
+ else findFromEndUntil f (PS x s (l-1))
1,019 Data/ByteString/Char8.hs
<
@@ -0,0 +1,1019 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__
+{-# LANGUAGE MagicHash, UnboxedTuples #-}
+#endif
+{-# OPTIONS_HADDOCK prune #-}
+#if __GLASGOW_HASKELL__ >= 701
+{-# LANGUAGE Trustworthy #-}
+#endif
+
+-- |
+-- Module : Data.ByteString.Char8
+-- Copyright : (c) Don Stewart 2006-2008
+-- (c) Duncan Coutts 2006-2011
+-- License : BSD-style
+--
+-- Maintainer : dons00@gmail.com, duncan@community.haskell.org
+-- Stability : stable
+-- Portability : portable
+--
+-- Manipulate 'ByteString's using 'Char' operations. All Chars will be
+-- truncated to 8 bits. It can be expected that these functions will run
+-- at identical speeds to their 'Word8' equivalents in "Data.ByteString".
+--
+-- More specifically these byte strings are taken to be in the
+-- subset of Unicode covered by code points 0-255. This covers
+-- Unicode Basic Latin, Latin-1 Supplement and C0+C1 Controls.
+--
+-- See:
+--
+-- * <http://www.unicode.org/charts/>
+--
+-- * <http://www.unicode.org/charts/PDF/U0000.pdf>
+--
+-- * <http://www.unicode.org/charts/PDF/U0080.pdf>
+--
+-- This module is intended to be imported @qualified@, to avoid name
+-- clashes with "Prelude" functions. eg.
+--
+-- > import qualified Data.ByteString.Char8 as C
+--
+-- The Char8 interface to bytestrings provides an instance of IsString
+-- for the ByteString type, enabling you to use string literals, and
+-- have them implicitly packed to ByteStrings.
+-- Use @{-\# LANGUAGE OverloadedStrings \#-}@ to enable this.
+--
+
+module Data.ByteString.Char8 (
+
+ -- * The @ByteString@ type
+ ByteString, -- abstract, instances: Eq, Ord, Show, Read, Data, Typeable, Monoid
+
+ -- * Introducing and eliminating 'ByteString's
+ empty, -- :: ByteString
+ singleton, -- :: Char -> ByteString
+ pack, -- :: String -> ByteString
+ unpack, -- :: ByteString -> String
+
+ -- * Basic interface
+ cons, -- :: Char -> ByteString -> ByteString
+ snoc, -- :: ByteString -> Char -> ByteString
+ append, -- :: ByteString -> ByteString -> ByteString
+ head, -- :: ByteString -> Char
+ uncons, -- :: ByteString -> Maybe (Char, ByteString)
+ last, -- :: ByteString -> Char
+ tail, -- :: ByteString -> ByteString
+ init, -- :: ByteString -> ByteString
+ null, -- :: ByteString -> Bool
+ length, -- :: ByteString -> Int
+
+ -- * Transformating ByteStrings
+ map, -- :: (Char -> Char) -> ByteString -> ByteString
+ reverse, -- :: ByteString -> ByteString
+ intersperse, -- :: Char -> ByteString -> ByteString
+ intercalate, -- :: ByteString -> [ByteString] -> ByteString
+ transpose, -- :: [ByteString] -> [ByteString]
+
+ -- * Reducing 'ByteString's (folds)
+ foldl, -- :: (a -> Char -> a) -> a -> ByteString -> a
+ foldl', -- :: (a -> Char -> a) -> a -> ByteString -> a
+ foldl1, -- :: (Char -> Char -> Char) -> ByteString -> Char
+ foldl1', -- :: (Char -> Char -> Char) -> ByteString -> Char
+
+ foldr, -- :: (Char -> a -> a) -> a -> ByteString -> a
+ foldr', -- :: (Char -> a -> a) -> a -> ByteString -> a
+ foldr1, -- :: (Char -> Char -> Char) -> ByteString -> Char
+ foldr1', -- :: (Char -> Char -> Char) -> ByteString -> Char
+
+ -- ** Special folds
+ concat, -- :: [ByteString] -> ByteString
+ concatMap, -- :: (Char -> ByteString) -> ByteString -> ByteString
+ any, -- :: (Char -> Bool) -> ByteString -> Bool
+ all, -- :: (Char -> Bool) -> ByteString -> Bool
+ maximum, -- :: ByteString -> Char
+ minimum, -- :: ByteString -> Char
+
+ -- * Building ByteStrings
+ -- ** Scans
+ scanl, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString
+ scanl1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString
+ scanr, -- :: (Char -> Char -> Char) -> Char -> ByteString -> ByteString
+ scanr1, -- :: (Char -> Char -> Char) -> ByteString -> ByteString
+
+ -- ** Accumulating maps
+ mapAccumL, -- :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)
+ mapAccumR, -- :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)
+
+ -- ** Generating and unfolding ByteStrings
+ replicate, -- :: Int -> Char -> ByteString
+ unfoldr, -- :: (a -> Maybe (Char, a)) -> a -> ByteString
+ unfoldrN, -- :: Int -> (a -> Maybe (Char, a)) -> a -> (ByteString, Maybe a)
+
+ -- * Substrings
+
+ -- ** Breaking strings
+ take, -- :: Int -> ByteString -> ByteString
+ drop, -- :: Int -> ByteString -> ByteString
+ splitAt, -- :: Int -> ByteString -> (ByteString, ByteString)
+ takeWhile, -- :: (Char -> Bool) -> ByteString -> ByteString
+ dropWhile, -- :: (Char -> Bool) -> ByteString -> ByteString
+ span, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
+ spanEnd, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
+ break, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
+ breakEnd, -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
+ group, -- :: ByteString -> [ByteString]
+ groupBy, -- :: (Char -> Char -> Bool) -> ByteString -> [ByteString]
+ inits, -- :: ByteString -> [ByteString]
+ tails, -- :: ByteString -> [ByteString]
+
+ -- ** Breaking into many substrings
+ split, -- :: Char -> ByteString -> [ByteString]
+ splitWith, -- :: (Char -> Bool) -> ByteString -> [ByteString]
+
+ -- ** Breaking into lines and words
+ lines, -- :: ByteString -> [ByteString]
+ words, -- :: ByteString -> [ByteString]
+ unlines, -- :: [ByteString] -> ByteString
+ unwords, -- :: ByteString -> [ByteString]
+
+ -- * Predicates
+ isPrefixOf, -- :: ByteString -> ByteString -> Bool
+ isSuffixOf, -- :: ByteString -> ByteString -> Bool
+ isInfixOf, -- :: ByteString -> ByteString -> Bool
+
+ -- ** Search for arbitrary substrings
+ breakSubstring, -- :: ByteString -> ByteString -> (ByteString,ByteString)
+ findSubstring, -- :: ByteString -> ByteString -> Maybe Int
+ findSubstrings, -- :: ByteString -> ByteString -> [Int]
+
+ -- * Searching ByteStrings
+
+ -- ** Searching by equality
+ elem, -- :: Char -> ByteString -> Bool
+ notElem, -- :: Char -> ByteString -> Bool
+
+ -- ** Searching with a predicate
+ find, -- :: (Char -> Bool) -> ByteString -> Maybe Char
+ filter, -- :: (Char -> Bool) -> ByteString -> ByteString
+-- partition -- :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)
+
+ -- * Indexing ByteStrings
+ index, -- :: ByteString -> Int -> Char
+ elemIndex, -- :: Char -> ByteString -> Maybe Int
+ elemIndices, -- :: Char -> ByteString -> [Int]
+ elemIndexEnd, -- :: Char -> ByteString -> Maybe Int
+ findIndex, -- :: (Char -> Bool) -> ByteString -> Maybe Int
+ findIndices, -- :: (Char -> Bool) -> ByteString -> [Int]
+ count, -- :: Char -> ByteString -> Int
+
+ -- * Zipping and unzipping ByteStrings
+ zip, -- :: ByteString -> ByteString -> [(Char,Char)]
+ zipWith, -- :: (Char -> Char -> c) -> ByteString -> ByteString -> [c]
+ unzip, -- :: [(Char,Char)] -> (ByteString,ByteString)
+
+ -- * Ordered ByteStrings
+ sort, -- :: ByteString -> ByteString
+
+ -- * Reading from ByteStrings
+ readInt, -- :: ByteString -> Maybe (Int, ByteString)
+ readInteger, -- :: ByteString -> Maybe (Integer, ByteString)
+
+ -- * Low level CString conversions
+
+ -- ** Copying ByteStrings
+ copy, -- :: ByteString -> ByteString
+
+ -- ** Packing CStrings and pointers
+ packCString, -- :: CString -> IO ByteString
+ packCStringLen, -- :: CStringLen -> IO ByteString
+
+ -- ** Using ByteStrings as CStrings
+ useAsCString, -- :: ByteString -> (CString -> IO a) -> IO a
+ useAsCStringLen, -- :: ByteString -> (CStringLen -> IO a) -> IO a
+
+ -- * I\/O with 'ByteString's
+
+ -- ** Standard input and output
+ getLine, -- :: IO ByteString
+ getContents, -- :: IO ByteString
+ putStr, -- :: ByteString -> IO ()
+ putStrLn, -- :: ByteString -> IO ()
+ interact, -- :: (ByteString -> ByteString) -> IO ()
+
+ -- ** Files
+ readFile, -- :: FilePath -> IO ByteString
+ writeFile, -- :: FilePath -> ByteString -> IO ()
+ appendFile, -- :: FilePath -> ByteString -> IO ()
+-- mmapFile, -- :: FilePath -> IO ByteString
+
+ -- ** I\/O with Handles
+ hGetLine, -- :: Handle -> IO ByteString
+ hGetContents, -- :: Handle -> IO ByteString
+ hGet, -- :: Handle -> Int -> IO ByteString
+ hGetNonBlocking, -- :: Handle -> Int -> IO ByteString
+ hPut, -- :: Handle -> ByteString -> IO ()
+ hPutNonBlocking, -- :: Handle -> ByteString -> IO ByteString
+ hPutStr, -- :: Handle -> ByteString -> IO ()
+ hPutStrLn, -- :: Handle -> ByteString -> IO ()
+
+ ) where
+
+import qualified Prelude as P
+import Prelude hiding (reverse,head,tail,last,init,null
+ ,length,map,lines,foldl,foldr,unlines
+ ,concat,any,take,drop,splitAt,takeWhile
+ ,dropWhile,span,break,elem,filter,unwords
+ ,words,maximum,minimum,all,concatMap
+ ,scanl,scanl1,scanr,scanr1
+ ,appendFile,readFile,writeFile
+ ,foldl1,foldr1,replicate
+ ,getContents,getLine,putStr,putStrLn,interact
+ ,zip,zipWith,unzip,notElem)
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Internal as B
+import qualified Data.ByteString.Unsafe as B
+
+-- Listy functions transparently exported
+import Data.ByteString (empty,null,length,tail,init,append
+ ,inits,tails,reverse,transpose
+ ,concat,take,drop,splitAt,intercalate
+ ,sort,isPrefixOf,isSuffixOf,isInfixOf
+ ,findSubstring,findSubstrings,breakSubstring,copy,group
+
+ ,getLine, getContents, putStr, interact
+ ,hGetContents, hGet, hPut, hPutStr
+ ,hGetLine, hGetNonBlocking, hPutNonBlocking
+ ,packCString,packCStringLen
+ ,useAsCString,useAsCStringLen
+ )
+
+import Data.ByteString.Internal
+
+import Data.Char ( isSpace )
+import qualified Data.List as List (intersperse)
+
+import System.IO (Handle,stdout,openFile,hClose,hFileSize,IOMode(..))
+#ifndef __NHC__
+import Control.Exception (bracket)
+#else
+import IO (bracket)
+#endif
+import Foreign
+
+#define STRICT1(f) f a | a `seq` False = undefined
+#define STRICT2(f) f a b | a `seq` b `seq` False = undefined
+#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
+#define STRICT4(f) f a b c d | a `seq` b `seq` c `seq` d `seq` False = undefined
+
+------------------------------------------------------------------------
+
+-- | /O(1)/ Convert a 'Char' into a 'ByteString'
+singleton :: Char -> ByteString
+singleton = B.singleton . c2w
+{-# INLINE singleton #-}
+
+-- | /O(n)/ Convert a 'String' into a 'ByteString'
+--
+-- For applications with large numbers of string literals, pack can be a
+-- bottleneck.
+pack :: String -> ByteString
+pack = packChars
+
+#if !defined(__GLASGOW_HASKELL__)
+{-# INLINE [1] pack #-}
+
+{-# RULES
+"ByteString pack/packAddress" forall s .
+ pack (unpackCString# s) = inlinePerformIO (B.unsafePackAddress s)
+ #-}
+
+#endif
+
+-- | /O(n)/ Converts a 'ByteString' to a 'String'.
+unpack :: ByteString -> [Char]
+unpack = B.unpackChars
+{-# INLINE unpack #-}
+
+infixr 5 `cons` --same as list (:)
+infixl 5 `snoc`
+
+-- | /O(n)/ 'cons' is analogous to (:) for lists, but of different
+-- complexity, as it requires a memcpy.
+cons :: Char -> ByteString -> ByteString
+cons = B.cons . c2w
+{-# INLINE cons #-}
+
+-- | /O(n)/ Append a Char to the end of a 'ByteString'. Similar to
+-- 'cons', this function performs a memcpy.
+snoc :: ByteString -> Char -> ByteString
+snoc p = B.snoc p . c2w
+{-# INLINE snoc #-}
+
+-- | /O(1)/ Extract the head and tail of a ByteString, returning Nothing
+-- if it is empty.
+uncons :: ByteString -> Maybe (Char, ByteString)
+uncons bs = case B.uncons bs of
+ Nothing -> Nothing
+ Just (w, bs') -> Just (w2c w, bs')
+{-# INLINE uncons #-}
+
+-- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.
+head :: ByteString -> Char
+head = w2c . B.head
+{-# INLINE head #-}
+
+-- | /O(1)/ Extract the last element of a packed string, which must be non-empty.
+last :: ByteString -> Char
+last = w2c . B.last
+{-# INLINE last #-}
+
+-- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each element of @xs@
+map :: (Char -> Char) -> ByteString -> ByteString
+map f = B.map (c2w . f . w2c)
+{-# INLINE map #-}
+
+-- | /O(n)/ The 'intersperse' function takes a Char and a 'ByteString'
+-- and \`intersperses\' that Char between the elements of the
+-- 'ByteString'. It is analogous to the intersperse function on Lists.
+intersperse :: Char -> ByteString -> ByteString
+intersperse = B.intersperse . c2w
+{-# INLINE intersperse #-}
+
+-- | 'foldl', applied to a binary operator, a starting value (typically
+-- the left-identity of the operator), and a ByteString, reduces the
+-- ByteString using the binary operator, from left to right.
+foldl :: (a -> Char -> a) -> a -> ByteString -> a
+foldl f = B.foldl (\a c -> f a (w2c c))
+{-# INLINE foldl #-}
+
+-- | 'foldl\'' is like foldl, but strict in the accumulator.
+foldl' :: (a -> Char -> a) -> a -> ByteString -> a
+foldl' f = B.foldl' (\a c -> f a (w2c c))
+{-# INLINE foldl' #-}
+
+-- | 'foldr', applied to a binary operator, a starting value
+-- (typically the right-identity of the operator), and a packed string,
+-- reduces the packed string using the binary operator, from right to left.
+foldr :: (Char -> a -> a) -> a -> ByteString -> a
+foldr f = B.foldr (\c a -> f (w2c c) a)
+{-# INLINE foldr #-}
+
+-- | 'foldr\'' is a strict variant of foldr
+foldr' :: (Char -> a -> a) -> a -> ByteString -> a
+foldr' f = B.foldr' (\c a -> f (w2c c) a)
+{-# INLINE foldr' #-}
+
+-- | 'foldl1' is a variant of 'foldl' that has no starting value
+-- argument, and thus must be applied to non-empty 'ByteStrings'.
+foldl1 :: (Char -> Char -> Char) -> ByteString -> Char
+foldl1 f ps = w2c (B.foldl1 (\x y -> c2w (f (w2c x) (w2c y))) ps)
+{-# INLINE foldl1 #-}
+
+-- | A strict version of 'foldl1'
+foldl1' :: (Char -> Char -> Char) -> ByteString -> Char
+foldl1' f ps = w2c (B.foldl1' (\x y -> c2w (f (w2c x) (w2c y))) ps)
+{-# INLINE foldl1' #-}
+
+-- | 'foldr1' is a variant of 'foldr' that has no starting value argument,
+-- and thus must be applied to non-empty 'ByteString's
+foldr1 :: (Char -> Char -> Char) -> ByteString -> Char
+foldr1 f ps = w2c (B.foldr1 (\x y -> c2w (f (w2c x) (w2c y))) ps)
+{-# INLINE foldr1 #-}
+
+-- | A strict variant of foldr1
+foldr1' :: (Char -> Char -> Char) -> ByteString -> Char
+foldr1' f ps = w2c (B.foldr1' (\x y -> c2w (f (w2c x) (w2c y))) ps)
+{-# INLINE foldr1' #-}
+
+-- | Map a function over a 'ByteString' and concatenate the results
+concatMap :: (Char -> ByteString) -> ByteString -> ByteString
+concatMap f = B.concatMap (f . w2c)
+{-# INLINE concatMap #-}
+
+-- | Applied to a predicate and a ByteString, 'any' determines if
+-- any element of the 'ByteString' satisfies the predicate.
+any :: (Char -> Bool) -> ByteString -> Bool
+any f = B.any (f . w2c)
+{-# INLINE any #-}
+
+-- | Applied to a predicate and a 'ByteString', 'all' determines if
+-- all elements of the 'ByteString' satisfy the predicate.
+all :: (Char -> Bool) -> ByteString -> Bool
+all f = B.all (f . w2c)
+{-# INLINE all #-}
+
+-- | 'maximum' returns the maximum value from a 'ByteString'
+maximum :: ByteString -> Char
+maximum = w2c . B.maximum
+{-# INLINE maximum #-}
+
+-- | 'minimum' returns the minimum value from a 'ByteString'
+minimum :: ByteString -> Char
+minimum = w2c . B.minimum
+{-# INLINE minimum #-}
+
+-- | The 'mapAccumL' function behaves like a combination of 'map' and
+-- 'foldl'; it applies a function to each element of a ByteString,
+-- passing an accumulating parameter from left to right, and returning a
+-- final value of this accumulator together with the new list.
+mapAccumL :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)
+mapAccumL f = B.mapAccumL (\acc w -> case f acc (w2c w) of (acc', c) -> (acc', c2w c))
+
+-- | The 'mapAccumR' function behaves like a combination of 'map' and
+-- 'foldr'; it applies a function to each element of a ByteString,
+-- passing an accumulating parameter from right to left, and returning a
+-- final value of this accumulator together with the new ByteString.
+mapAccumR :: (acc -> Char -> (acc, Char)) -> acc -> ByteString -> (acc, ByteString)
+mapAccumR f = B.mapAccumR (\acc w -> case f acc (w2c w) of (acc', c) -> (acc', c2w c))