bytestring-plain (empty) → 0.1.0.0
raw patch · 4 files changed
+233/−0 lines, 4 filesdep +basedep +bytestringdep +deepseqsetup-changed
Dependencies added: base, bytestring, deepseq, ghc-prim, hashable
Files
- Data/ByteString/Plain.hs +162/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- bytestring-plain.cabal +39/−0
+ Data/ByteString/Plain.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE MagicHash, DeriveDataTypeable #-}++-- |+-- Stability : experimental+-- Portability : GHC+--+-- This module is intended to be imported @qualified@ in order to+-- avoid name clashes with the "Prelude", "Data.ByteString", and+-- "Data.ByteString.Lazy" modules. E.g.:+--+-- > import qualified Data.ByteString.Plain as PB+--+module Data.ByteString.Plain (+ -- * The plain @ByteString@ type and representation+ ByteString+ -- * Introducing and eliminating 'ByteString's+ , empty+ , fromStrict+ , toStrict+ -- * Basic operations+ , null+ , length+ ) where++import Control.DeepSeq (NFData)+import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B+import Data.Hashable (Hashable(hashWithSalt))+import Data.Typeable (Typeable)+import GHC.ForeignPtr+import GHC.Prim+import GHC.Types+import Prelude hiding (length, null)+import System.IO.Unsafe (unsafePerformIO)++-- |Compact heap representation a (strict) 'B.ByteString' can be (un)wrapped to/from.+--+-- This data type depends on the ordinary 'B.ByteString' type to be+-- useful but comes with a different cost-model.+--+-- This representation avoids the 'ForeignPtr' indirection, and the+-- offset/length slice representation for shared 'B.ByteString's, and+-- is therefore suitable if you need to store many small strings in a+-- data records or for use as keys in container types. On the other+-- hand, string operations on 'ByteString' would require+-- re-allocations, and thus are not supported. If you need to perform+-- such operations convert and operate on conventional 'B.ByteString's+-- instead.+--+-- This structure supports @UNPACK@, and then has an overhead+-- of only 3 words (beyond the word-padded storage of the byte-string+-- payload), as it's basically just a pointer to a+-- 'MutableByteArray#':+--+-- > data ByteString = PBS !(MutableByteArray# RealWorld)+--+-- In contrast, a single non-shared unpacked ('PlainPtr'-backed)+-- 'ByteString' field exhibits an overhead of 8 words:+--+-- > data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload (2 words)+-- > {-# UNPACK #-} !Int -- offset (1 word)+-- > {-# UNPACK #-} !Int -- length (1 word)+-- >+-- > data ForeignPtr a = ForeignPtr Addr# ForeignPtrContents -- 2 words w/o info-ptr+-- >+-- > data ForeignPtrContents -- 1 word needed for info-ptr+-- > = PlainForeignPtr {...}+-- > | MallocPtr {...}+-- > | PlainPtr (MutableByteArray# RealWorld) -- common case (1 word)+-- >+-- > data MutableByteArray# s -- 2 words + payload+--+-- As an optimization, all zero-length strings are mapped to the+-- singleton 'empty' value.+data ByteString = PBS !(MutableByteArray# RealWorld)+ deriving Typeable++-- |Singleton value the 'B.empty' 'B.ByteString' is mapped to/from.+empty :: ByteString+empty = unsafePerformIO $ do+ (ForeignPtr _ (PlainPtr mbarr#)) <- mallocPlainForeignPtrBytes 0+ return $! PBS mbarr#+{-# NOINLINE empty #-}++-- |Extract 'ByteString' from 'ByteString'+--+-- If possible, the internally used 'MutableByteArray#' is shared with+-- the original 'ByteString' in which case the conversion is cheap.+--+-- However, if necessary, a trimmed copy of the original 'ByteString'+-- will be created via 'B.copy' resulting in a newly allocated+-- 'MutableByteArray#'.+--+-- N.B.: Because strict 'B.ByteString's use pinned memory internally+-- also plain 'ByteString's use pinned memory and thereby increase the+-- potential for memory fragmentation as the garbage collector is not+-- allowed to move pinned memory areas.+--+-- Depending on the use case, it might be beneficial to apply some+-- form of memoizing to the 'fromStrict' conversion (also known as+-- <http://en.wikipedia.org/wiki/Hash_consing Hash consing> or+-- <http://en.wikipedia.org/wiki/String_interning String interning>).++fromStrict :: B.ByteString -> ByteString+fromStrict (B.PS _ _ 0) = empty+fromStrict (B.PS (ForeignPtr addr (PlainPtr mbarr#)) 0 l)+ | neAddr# addr' addr = error "internal error" -- sanity check+ | l' == l = PBS mbarr#+ where+ l' = I# (sizeofMutableByteArray# mbarr#)+ addr' = byteArrayContents# (unsafeCoerce# mbarr#)+fromStrict bs = fromStrict (B.copy bs) -- this assumes+ -- ByteString internals return a trimmed+ -- ForeignPtr/PlainPtr string; otherwise there's+ -- risk of infinite looping+{-# INLINE fromStrict #-}++-- |Convert a plain 'ByteString' back into a 'ByteString'.+--+-- This effectively wraps the plain 'ByteString' into a 'ForeignPtr'+-- and a plain 'B.ByteString' type.+toStrict :: ByteString -> B.ByteString+toStrict (PBS mbarr#) | l == 0 = B.empty+ | otherwise = B.PS fp 0 l+ where+ l = I# (sizeofMutableByteArray# mbarr#)+ addr = byteArrayContents# (unsafeCoerce# mbarr#)+ fp = ForeignPtr addr (PlainPtr mbarr#)+{-# INLINE toStrict #-}++null :: ByteString -> Bool+null = (==0) . length+{-# INLINE null #-}++length :: ByteString -> Int+length (PBS mbarr#) = I# (sizeofMutableByteArray# mbarr#)+{-# INLINE length #-}++-- WHNF == NF+instance NFData ByteString++-- the following instances are implement via strict 'B.ByteString's;+-- In the future "native" implementations shall be provided if they+-- result being faster.+instance Eq ByteString where+ x == y = toStrict x == toStrict y+ {-# INLINE (==) #-}++instance Ord ByteString where+ compare x y = compare (toStrict x) (toStrict y)+ {-# INLINE compare #-}++instance Hashable ByteString where+ hashWithSalt salt = hashWithSalt salt . toStrict+ {-# INLINE hashWithSalt #-}++-- Mostly for convenience+instance Show ByteString where+ showsPrec p rbs = showsPrec p (toStrict rbs)++instance Read ByteString where+ readsPrec p str = [ (fromStrict x, y) | (x, y) <- readsPrec p str ]
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Herbert Valerio Riedel++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Herbert Valerio Riedel nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bytestring-plain.cabal view
@@ -0,0 +1,39 @@+name: bytestring-plain+version: 0.1.0.0+synopsis: Plain byte strings ('ForeignPtr'-less 'ByteString's)+homepage: https://github.com/hvr/bytestring-plain+bug-reports: https://github.com/hvr/bytestring-plain/issues+license: BSD3+license-file: LICENSE+author: Herbert Valerio Riedel+maintainer: hvr@gnu.org+copyright: (c) 2013 Herbert Valerio Riedel+category: Data+build-type: Simple+tested-with: GHC ==7.6.3+cabal-version: >=1.14+description:+ More compact representation for strict 'ByteString's avoiding the+ overhead and indirection caused by 'ForeignPtr'.+ .+ This representation is useful to reduce the incurred memory overhead+ when operating with many small, long-lived, distinct byte strings+ (such as keys for containers).+ .+ See documentation in "Data.ByteString.Plain" for more details about+ this representation.++library+ default-language: Haskell2010+ exposed-modules: Data.ByteString.Plain+ other-extensions: MagicHash+ build-depends: base >= 4.6 && <4.7,+ bytestring >= 0.10 && <0.11,+ ghc-prim >= 0.3 && <0.4,+ deepseq >= 1.2 && <1.4,+ hashable >= 1.1.1 && <1.3+ ghc-options: -Wall++Source-Repository head+ Type: git+ Location: https://github.com/hvr/bytestring-plain.git