Data.Attoparsec.ByteString.Buffer

attoparsec-0.14.4: Fast combinator parsing for bytestrings and text

Copyright | Bryan O'Sullivan 2007-2015
License | BSD3
Maintainer | bos@serpentine.com
Stability | experimental
Portability | GHC
Safe Haskell | None
Language | Haskell2010

Data.Attoparsec.ByteString.Buffer

Description

An "immutable" buffer that supports cheap appends.

A Buffer is divided into an immutable read-only zone, followed by a mutable area that we've preallocated, but not yet written to.

We overallocate at the end of a Buffer so that we can cheaply append. Since a user of an existing Buffer cannot see past the end of its immutable zone into the data that will change during an append, this is safe.

Once we run out of space at the end of a Buffer, we do the usual doubling of the buffer size.

The fact of having a mutable buffer really helps with performance, but it does have a consequence: if someone misuses the Partial API that attoparsec uses by calling the same continuation repeatedly (which never makes sense in practice), they could overwrite data.

Since the API *looks* pure, it should *act* pure, too, so we use two generation counters (one mutable, one immutable) to track the number of appends to a mutable buffer. If the counters ever get out of sync, someone is appending twice to a mutable buffer, so we duplicate the entire buffer in order to preserve the immutability of its older self.

While we could go a step further and gain protection against API abuse on a multicore system, by use of an atomic increment instruction to bump the mutable generation counter, that would be very expensive, and feels like it would also be in the realm of the ridiculous. Clients should never call a continuation more than once; we lack a linear type system that could enforce this; and there's only so far we should go to accommodate broken uses.

Synopsis

- data Buffer
- buffer :: ByteString -> Buffer
- unbuffer :: Buffer -> ByteString
- pappend :: Buffer -> ByteString -> Buffer
- length :: Buffer -> Int
- unsafeIndex :: Buffer -> Int -> Word8
- substring :: Int -> Int -> Buffer -> ByteString
- unsafeDrop :: Int -> Buffer -> ByteString

# Documentation

data Buffer #

#### Instances

Instances details

Monoid Buffer # |
Instance details Defined in Data.Attoparsec.ByteString.Buffer Methods mempty :: Buffer # mappend :: Buffer -> Buffer -> Buffer # mconcat :: [Buffer] -> Buffer #
Semigroup Buffer # |
Instance details Defined in Data.Attoparsec.ByteString.Buffer Methods (<>) :: Buffer -> Buffer -> Buffer # sconcat :: NonEmpty Buffer -> Buffer # stimes :: Integral b => b -> Buffer -> Buffer #
Show Buffer # |
Instance details Defined in Data.Attoparsec.ByteString.Buffer Methods showsPrec :: Int -> Buffer -> ShowS # show :: Buffer -> String # showList :: [Buffer] -> ShowS #

buffer :: ByteString -> Buffer #

The initial `Buffer` has no mutable zone, so we can avoid all copies in the (hopefully) common case of no further input being fed to us.

unbuffer :: Buffer -> ByteString #

pappend :: Buffer -> ByteString -> Buffer #

length :: Buffer -> Int #

unsafeIndex :: Buffer -> Int -> Word8 #

substring :: Int -> Int -> Buffer -> ByteString #

unsafeDrop :: Int -> Buffer -> ByteString #