packages feed

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 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