diff --git a/Data/Attoparsec.hs b/Data/Attoparsec.hs
--- a/Data/Attoparsec.hs
+++ b/Data/Attoparsec.hs
@@ -1,221 +1,23 @@
 -- |
 -- Module      :  Data.Attoparsec
--- Copyright   :  Bryan O'Sullivan 2007-2011
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
--- 
+--
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
 --
--- Simple, efficient combinator parsing for 'B.ByteString' strings,
--- loosely based on the Parsec library.
+-- Simple, efficient combinator parsing for
+-- 'Data.ByteString.ByteString' strings, loosely based on the Parsec
+-- library.
+--
+-- This module is deprecated. Use "Data.Attoparsec.ByteString"
+-- instead.
 
 module Data.Attoparsec
+    {-# DEPRECATED "This module will be removed in the next major release." #-}
     (
-    -- * Differences from Parsec
-    -- $parsec
-
-    -- * Incremental input
-    -- $incremental
-
-    -- * Performance considerations
-    -- $performance
-
-    -- * Parser types
-      I.Parser
-    , Result(..)
-
-    -- ** Typeclass instances
-    -- $instances
-
-    -- * Running parsers
-    , parse
-    , feed
-    , I.parseOnly
-    , parseWith
-    , parseTest
-
-    -- ** Result conversion
-    , maybeResult
-    , eitherResult
-
-    -- * Combinators
-    , (I.<?>)
-    , I.try
-    , module Data.Attoparsec.Combinator
-
-    -- * Parsing individual bytes
-    , I.word8
-    , I.anyWord8
-    , I.notWord8
-    , I.satisfy
-    , I.satisfyWith
-    , I.skip
-
-    -- ** Byte classes
-    , I.inClass
-    , I.notInClass
-
-    -- * Efficient string handling
-    , I.string
-    , I.skipWhile
-    , I.take
-    , I.scan
-    , I.takeWhile
-    , I.takeWhile1
-    , I.takeTill
-
-    -- ** Consume all remaining input
-    , I.takeByteString
-    , I.takeLazyByteString
-
-    -- * State observation and manipulation functions
-    , I.endOfInput
-    , I.atEnd
+      module Data.Attoparsec.ByteString
     ) where
 
-import Data.Attoparsec.Combinator
-import qualified Data.Attoparsec.Internal as I
-import qualified Data.ByteString as B
-import Data.Attoparsec.Internal (Result(..), parse)
-
--- $parsec
---
--- Compared to Parsec 3, Attoparsec makes several tradeoffs.  It is
--- not intended for, or ideal for, all possible uses.
---
--- * While Attoparsec can consume input incrementally, Parsec cannot.
---   Incremental input is a huge deal for efficient and secure network
---   and system programming, since it gives much more control to users
---   of the library over matters such as resource usage and the I/O
---   model to use.
---
--- * Much of the performance advantage of Attoparsec is gained via
---   high-performance parsers such as 'I.takeWhile' and 'I.string'.
---   If you use complicated combinators that return lists of bytes or
---   characters, there is less performance difference between the two
---   libraries.
---
--- * Unlike Parsec 3, Attoparsec does not support being used as a
---   monad transformer.
---
--- * Attoparsec is specialised to deal only with strict 'B.ByteString'
---   input.  Efficiency concerns rule out both lists and lazy
---   bytestrings.  The usual use for lazy bytestrings would be to
---   allow consumption of very large input without a large footprint.
---   For this need, Attoparsec's incremental input provides an
---   excellent substitute, with much more control over when input
---   takes place.  If you must use lazy bytestrings, see the 'Lazy'
---   module, which feeds lazy chunks to a regular parser.
---
--- * Parsec parsers can produce more helpful error messages than
---   Attoparsec parsers.  This is a matter of focus: Attoparsec avoids
---   the extra book-keeping in favour of higher performance.
-
--- $incremental
---
--- Attoparsec supports incremental input, meaning that you can feed it
--- a bytestring that represents only part of the expected total amount
--- of data to parse. If your parser reaches the end of a fragment of
--- input and could consume more input, it will suspend parsing and
--- return a 'Partial' continuation.
---
--- Supplying the 'Partial' continuation with another bytestring will
--- resume parsing at the point where it was suspended. You must be
--- prepared for the result of the resumed parse to be another
--- 'Partial' continuation.
---
--- To indicate that you have no more input, supply the 'Partial'
--- continuation with an empty bytestring.
---
--- Remember that some parsing combinators will not return a result
--- until they reach the end of input.  They may thus cause 'Partial'
--- results to be returned.
---
--- If you do not need support for incremental input, consider using
--- the 'I.parseOnly' function to run your parser.  It will never
--- prompt for more input.
-
--- $performance
---
--- If you write an Attoparsec-based parser carefully, it can be
--- realistic to expect it to perform within a factor of 2 of a
--- hand-rolled C parser (measuring megabytes parsed per second).
---
--- To actually achieve high performance, there are a few guidelines
--- that it is useful to follow.
---
--- Use the 'B.ByteString'-oriented parsers whenever possible,
--- e.g. 'I.takeWhile1' instead of 'many1' 'I.anyWord8'.  There is
--- about a factor of 100 difference in performance between the two
--- kinds of parser.
---
--- For very simple byte-testing predicates, write them by hand instead
--- of using 'I.inClass' or 'I.notInClass'.  For instance, both of
--- these predicates test for an end-of-line byte, but the first is
--- much faster than the second:
---
--- >endOfLine_fast w = w == 13 || w == 10
--- >endOfLine_slow   = inClass "\r\n"
---
--- Make active use of benchmarking and profiling tools to measure,
--- find the problems with, and improve the performance of your parser.
-
--- $instances
---
--- The 'I.Parser' type is an instance of the following classes:
---
--- * 'Monad', where 'fail' throws an exception (i.e. fails) with an
---   error message.
---
--- * 'Functor' and 'Applicative', which follow the usual definitions.
---
--- * 'MonadPlus', where 'mzero' fails (with no error message) and
---   'mplus' executes the right-hand parser if the left-hand one
---   fails.
---
--- * 'Alternative', which follows 'MonadPlus'.
---
--- The 'Result' type is an instance of 'Functor', where 'fmap'
--- transforms the value in a 'Done' result.
-
--- | If a parser has returned a 'Partial' result, supply it with more
--- input.
-feed :: Result r -> B.ByteString -> Result r
-feed f@(Fail _ _ _) _ = f
-feed (Partial k) d    = k d
-feed (Done bs r) d    = Done (B.append bs d) r
-{-# INLINE feed #-}
-
--- | Run a parser and print its result to standard output.
-parseTest :: (Show a) => I.Parser a -> B.ByteString -> IO ()
-parseTest p s = print (parse p s)
-
--- | Run a parser with an initial input string, and a monadic action
--- that can supply more input if needed.
-parseWith :: Monad m =>
-             (m B.ByteString)
-          -- ^ An action that will be executed to provide the parser
-          -- with more input, if necessary.  The action must return an
-          -- 'B.empty' string when there is no more input available.
-          -> I.Parser a
-          -> B.ByteString
-          -- ^ Initial input for the parser.
-          -> m (Result a)
-parseWith refill p s = step $ parse p s
-  where step (Partial k) = (step . k) =<< refill
-        step r           = return r
-{-# INLINE parseWith #-}
-
--- | Convert a 'Result' value to a 'Maybe' value. A 'Partial' result
--- is treated as failure.
-maybeResult :: Result r -> Maybe r
-maybeResult (Done _ r) = Just r
-maybeResult _          = Nothing
-
--- | Convert a 'Result' value to an 'Either' value. A 'Partial' result
--- is treated as failure.
-eitherResult :: Result r -> Either String r
-eitherResult (Done _ r)     = Right r
-eitherResult (Fail _ _ msg) = Left msg
-eitherResult _              = Left "Result: incomplete input"
+import Data.Attoparsec.ByteString
diff --git a/Data/Attoparsec/ByteString.hs b/Data/Attoparsec/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/ByteString.hs
@@ -0,0 +1,232 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-- |
+-- Module      :  Data.Attoparsec.ByteString
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient combinator parsing for 'B.ByteString' strings,
+-- loosely based on the Parsec library.
+
+module Data.Attoparsec.ByteString
+    (
+    -- * Differences from Parsec
+    -- $parsec
+
+    -- * Incremental input
+    -- $incremental
+
+    -- * Performance considerations
+    -- $performance
+
+    -- * Parser types
+      I.Parser
+    , Result
+    , T.IResult(..)
+    , I.compareResults
+
+    -- * Running parsers
+    , parse
+    , feed
+    , I.parseOnly
+    , parseWith
+    , parseTest
+
+    -- ** Result conversion
+    , maybeResult
+    , eitherResult
+
+    -- * Parsing individual bytes
+    , I.word8
+    , I.anyWord8
+    , I.notWord8
+    , I.satisfy
+    , I.satisfyWith
+    , I.skip
+
+    -- ** Lookahead
+    , I.peekWord8
+    , I.peekWord8'
+
+    -- ** Byte classes
+    , I.inClass
+    , I.notInClass
+
+    -- * Efficient string handling
+    , I.string
+    , I.skipWhile
+    , I.take
+    , I.scan
+    , I.runScanner
+    , I.takeWhile
+    , I.takeWhile1
+    , I.takeWhileIncluding
+    , I.takeTill
+    , I.getChunk
+
+    -- ** Consume all remaining input
+    , I.takeByteString
+    , I.takeLazyByteString
+
+    -- * Combinators
+    , try
+    , (<?>)
+    , choice
+    , count
+    , option
+    , many'
+    , many1
+    , many1'
+    , manyTill
+    , manyTill'
+    , sepBy
+    , sepBy'
+    , sepBy1
+    , sepBy1'
+    , skipMany
+    , skipMany1
+    , eitherP
+    , I.match
+    -- * State observation and manipulation functions
+    , I.endOfInput
+    , I.atEnd
+    ) where
+
+import Data.Attoparsec.Combinator
+import Data.List (intercalate)
+import qualified Data.Attoparsec.ByteString.Internal as I
+import qualified Data.Attoparsec.Internal as I
+import qualified Data.ByteString as B
+import Data.Attoparsec.ByteString.Internal (Result, parse)
+import qualified Data.Attoparsec.Internal.Types as T
+
+-- $parsec
+--
+-- Compared to Parsec 3, attoparsec makes several tradeoffs.  It is
+-- not intended for, or ideal for, all possible uses.
+--
+-- * While attoparsec can consume input incrementally, Parsec cannot.
+--   Incremental input is a huge deal for efficient and secure network
+--   and system programming, since it gives much more control to users
+--   of the library over matters such as resource usage and the I/O
+--   model to use.
+--
+-- * Much of the performance advantage of attoparsec is gained via
+--   high-performance parsers such as 'I.takeWhile' and 'I.string'.
+--   If you use complicated combinators that return lists of bytes or
+--   characters, there is less performance difference between the two
+--   libraries.
+--
+-- * Unlike Parsec 3, attoparsec does not support being used as a
+--   monad transformer.
+--
+-- * attoparsec is specialised to deal only with strict 'B.ByteString'
+--   input.  Efficiency concerns rule out both lists and lazy
+--   bytestrings.  The usual use for lazy bytestrings would be to
+--   allow consumption of very large input without a large footprint.
+--   For this need, attoparsec's incremental input provides an
+--   excellent substitute, with much more control over when input
+--   takes place.  If you must use lazy bytestrings, see the
+--   "Data.Attoparsec.ByteString.Lazy" module, which feeds lazy chunks
+--   to a regular parser.
+--
+-- * Parsec parsers can produce more helpful error messages than
+--   attoparsec parsers.  This is a matter of focus: attoparsec avoids
+--   the extra book-keeping in favour of higher performance.
+
+-- $incremental
+--
+-- attoparsec supports incremental input, meaning that you can feed it
+-- a bytestring that represents only part of the expected total amount
+-- of data to parse. If your parser reaches the end of a fragment of
+-- input and could consume more input, it will suspend parsing and
+-- return a 'T.Partial' continuation.
+--
+-- Supplying the 'T.Partial' continuation with a bytestring will
+-- resume parsing at the point where it was suspended, with the
+-- bytestring you supplied used as new input at the end of the
+-- existing input. You must be prepared for the result of the resumed
+-- parse to be another 'T.Partial' continuation.
+--
+-- To indicate that you have no more input, supply the 'T.Partial'
+-- continuation with an empty bytestring.
+--
+-- Remember that some parsing combinators will not return a result
+-- until they reach the end of input.  They may thus cause 'T.Partial'
+-- results to be returned.
+--
+-- If you do not need support for incremental input, consider using
+-- the 'I.parseOnly' function to run your parser.  It will never
+-- prompt for more input.
+--
+-- /Note/: incremental input does /not/ imply that attoparsec will
+-- release portions of its internal state for garbage collection as it
+-- proceeds.  Its internal representation is equivalent to a single
+-- 'ByteString': if you feed incremental input to a parser, it will
+-- require memory proportional to the amount of input you supply.
+-- (This is necessary to support arbitrary backtracking.)
+
+-- $performance
+--
+-- If you write an attoparsec-based parser carefully, it can be
+-- realistic to expect it to perform similarly to a hand-rolled C
+-- parser (measuring megabytes parsed per second).
+--
+-- To actually achieve high performance, there are a few guidelines
+-- that it is useful to follow.
+--
+-- Use the 'B.ByteString'-oriented parsers whenever possible,
+-- e.g. 'I.takeWhile1' instead of 'many1' 'I.anyWord8'.  There is
+-- about a factor of 100 difference in performance between the two
+-- kinds of parser.
+--
+-- For very simple byte-testing predicates, write them by hand instead
+-- of using 'I.inClass' or 'I.notInClass'.  For instance, both of
+-- these predicates test for an end-of-line byte, but the first is
+-- much faster than the second:
+--
+-- >endOfLine_fast w = w == 13 || w == 10
+-- >endOfLine_slow   = inClass "\r\n"
+--
+-- Make active use of benchmarking and profiling tools to measure,
+-- find the problems with, and improve the performance of your parser.
+
+-- | Run a parser and print its result to standard output.
+parseTest :: (Show a) => I.Parser a -> B.ByteString -> IO ()
+parseTest p s = print (parse p s)
+
+-- | Run a parser with an initial input string, and a monadic action
+-- that can supply more input if needed.
+parseWith :: Monad m =>
+             (m B.ByteString)
+          -- ^ An action that will be executed to provide the parser
+          -- with more input, if necessary.  The action must return an
+          -- 'B.empty' string when there is no more input available.
+          -> I.Parser a
+          -> B.ByteString
+          -- ^ Initial input for the parser.
+          -> m (Result a)
+parseWith refill p s = step $ parse p s
+  where step (T.Partial k) = (step . k) =<< refill
+        step r             = return r
+{-# INLINE parseWith #-}
+
+-- | Convert a 'Result' value to a 'Maybe' value. A 'T.Partial' result
+-- is treated as failure.
+maybeResult :: Result r -> Maybe r
+maybeResult (T.Done _ r) = Just r
+maybeResult _            = Nothing
+
+-- | Convert a 'Result' value to an 'Either' value. A 'T.Partial'
+-- result is treated as failure.
+eitherResult :: Result r -> Either String r
+eitherResult (T.Done _ r)        = Right r
+eitherResult (T.Fail _ [] msg)   = Left msg
+eitherResult (T.Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)
+eitherResult _                   = Left "Result: incomplete input"
diff --git a/Data/Attoparsec/ByteString/Char8.hs b/Data/Attoparsec/ByteString/Char8.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/ByteString/Char8.hs
@@ -0,0 +1,581 @@
+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, TypeFamilies,
+    TypeSynonymInstances, GADTs #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Imports internal modules
+#endif
+{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-warnings-deprecations #-}
+
+-- |
+-- Module      :  Data.Attoparsec.ByteString.Char8
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient, character-oriented combinator parsing for
+-- 'B.ByteString' strings, loosely based on the Parsec library.
+
+module Data.Attoparsec.ByteString.Char8
+    (
+    -- * Character encodings
+    -- $encodings
+
+    -- * Parser types
+      Parser
+    , A.Result
+    , A.IResult(..)
+    , I.compareResults
+
+    -- * Running parsers
+    , A.parse
+    , A.feed
+    , A.parseOnly
+    , A.parseWith
+    , A.parseTest
+
+    -- ** Result conversion
+    , A.maybeResult
+    , A.eitherResult
+
+    -- * Parsing individual characters
+    , char
+    , char8
+    , anyChar
+    , notChar
+    , satisfy
+
+    -- ** Lookahead
+    , peekChar
+    , peekChar'
+
+    -- ** Special character parsers
+    , digit
+    , letter_iso8859_15
+    , letter_ascii
+    , space
+
+    -- ** Fast predicates
+    , isDigit
+    , isDigit_w8
+    , isAlpha_iso8859_15
+    , isAlpha_ascii
+    , isSpace
+    , isSpace_w8
+
+    -- *** Character classes
+    , inClass
+    , notInClass
+
+    -- * Efficient string handling
+    , I.string
+    , I.stringCI
+    , skipSpace
+    , skipWhile
+    , I.take
+    , scan
+    , takeWhile
+    , takeWhile1
+    , takeTill
+
+    -- ** String combinators
+    -- $specalt
+    , (.*>)
+    , (<*.)
+
+    -- ** Consume all remaining input
+    , I.takeByteString
+    , I.takeLazyByteString
+
+    -- * Text parsing
+    , I.endOfLine
+    , isEndOfLine
+    , isHorizontalSpace
+
+    -- * Numeric parsers
+    , decimal
+    , hexadecimal
+    , signed
+    , double
+    , Number(..)
+    , number
+    , rational
+    , scientific
+
+    -- * Combinators
+    , try
+    , (<?>)
+    , choice
+    , count
+    , option
+    , many'
+    , many1
+    , many1'
+    , manyTill
+    , manyTill'
+    , sepBy
+    , sepBy'
+    , sepBy1
+    , sepBy1'
+    , skipMany
+    , skipMany1
+    , eitherP
+    , I.match
+    -- * State observation and manipulation functions
+    , I.endOfInput
+    , I.atEnd
+    ) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (pure, (*>), (<*), (<$>))
+import Data.Word (Word)
+#endif
+import Control.Applicative ((<|>))
+import Control.Monad (void, when)
+import Data.Attoparsec.ByteString.FastSet (charClass, memberChar)
+import Data.Attoparsec.ByteString.Internal (Parser)
+import Data.Attoparsec.Combinator
+import Data.Attoparsec.Number (Number(..))
+import Data.Bits (Bits, (.|.), shiftL)
+import Data.ByteString.Internal (c2w, w2c)
+import Data.Int (Int8, Int16, Int32, Int64)
+import Data.String (IsString(..))
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
+import Data.Word (Word8, Word16, Word32, Word64)
+import Prelude hiding (takeWhile)
+import qualified Data.Attoparsec.ByteString as A
+import qualified Data.Attoparsec.ByteString.Internal as I
+import qualified Data.Attoparsec.Internal as I
+import qualified Data.ByteString as B8
+import qualified Data.ByteString.Char8 as B
+
+instance (a ~ B.ByteString) => IsString (Parser a) where
+    fromString = I.string . B.pack
+
+-- $encodings
+--
+-- This module is intended for parsing text that is
+-- represented using an 8-bit character set, e.g. ASCII or
+-- ISO-8859-15.  It /does not/ make any attempt to deal with character
+-- encodings, multibyte characters, or wide characters.  In
+-- particular, all attempts to use characters above code point U+00FF
+-- will give wrong answers.
+--
+-- Code points below U+0100 are simply translated to and from their
+-- numeric values, so e.g. the code point U+00A4 becomes the byte
+-- @0xA4@ (which is the Euro symbol in ISO-8859-15, but the generic
+-- currency sign in ISO-8859-1).  Haskell 'Char' values above U+00FF
+-- are truncated, so e.g. U+1D6B7 is truncated to the byte @0xB7@.
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser requires the predicate to succeed on at least one byte
+-- of input: it will fail if the predicate never returns 'True' or if
+-- there is no input left.
+takeWhile1 :: (Char -> Bool) -> Parser B.ByteString
+takeWhile1 p = I.takeWhile1 (p . w2c)
+{-# INLINE takeWhile1 #-}
+
+-- | The parser @satisfy p@ succeeds for any byte for which the
+-- predicate @p@ returns 'True'. Returns the byte that is actually
+-- parsed.
+--
+-- >digit = satisfy isDigit
+-- >    where isDigit c = c >= '0' && c <= '9'
+satisfy :: (Char -> Bool) -> Parser Char
+satisfy = I.satisfyWith w2c
+{-# INLINE satisfy #-}
+
+-- | Match a letter, in the ISO-8859-15 encoding.
+letter_iso8859_15 :: Parser Char
+letter_iso8859_15 = satisfy isAlpha_iso8859_15 <?> "letter_iso8859_15"
+{-# INLINE letter_iso8859_15 #-}
+
+-- | Match a letter, in the ASCII encoding.
+letter_ascii :: Parser Char
+letter_ascii = satisfy isAlpha_ascii <?> "letter_ascii"
+{-# INLINE letter_ascii #-}
+
+-- | A fast alphabetic predicate for the ISO-8859-15 encoding
+--
+-- /Note/: For all character encodings other than ISO-8859-15, and
+-- almost all Unicode code points above U+00A3, this predicate gives
+-- /wrong answers/.
+isAlpha_iso8859_15 :: Char -> Bool
+isAlpha_iso8859_15 c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+                       (c >= '\166' && moby c)
+  where moby = notInClass "\167\169\171-\179\182\183\185\187\191\215\247"
+        {-# NOINLINE moby #-}
+{-# INLINE isAlpha_iso8859_15 #-}
+
+-- | A fast alphabetic predicate for the ASCII encoding
+--
+-- /Note/: For all character encodings other than ASCII, and
+-- almost all Unicode code points above U+007F, this predicate gives
+-- /wrong answers/.
+isAlpha_ascii :: Char -> Bool
+isAlpha_ascii c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+{-# INLINE isAlpha_ascii #-}
+
+-- | Parse a single digit.
+digit :: Parser Char
+digit = satisfy isDigit <?> "digit"
+{-# INLINE digit #-}
+
+-- | A fast digit predicate.
+isDigit :: Char -> Bool
+isDigit c = c >= '0' && c <= '9'
+{-# INLINE isDigit #-}
+
+-- | A fast digit predicate.
+isDigit_w8 :: Word8 -> Bool
+isDigit_w8 w = w - 48 <= 9
+{-# INLINE isDigit_w8 #-}
+
+-- | Match any character.
+anyChar :: Parser Char
+anyChar = satisfy $ const True
+{-# INLINE anyChar #-}
+
+-- | Match any character, to perform lookahead. Returns 'Nothing' if
+-- end of input has been reached. Does not consume any input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+peekChar :: Parser (Maybe Char)
+peekChar = (fmap w2c) `fmap` I.peekWord8
+{-# INLINE peekChar #-}
+
+-- | Match any character, to perform lookahead.  Does not consume any
+-- input, but will fail if end of input has been reached.
+peekChar' :: Parser Char
+peekChar' = w2c `fmap` I.peekWord8'
+{-# INLINE peekChar' #-}
+
+-- | Fast predicate for matching ASCII space characters.
+--
+-- /Note/: This predicate only gives correct answers for the ASCII
+-- encoding.  For instance, it does not recognise U+00A0 (non-breaking
+-- space) as a space character, even though it is a valid ISO-8859-15
+-- byte. For a Unicode-aware and only slightly slower predicate,
+-- use 'Data.Char.isSpace'
+isSpace :: Char -> Bool
+isSpace c = (c == ' ') || ('\t' <= c && c <= '\r')
+{-# INLINE isSpace #-}
+
+-- | Fast 'Word8' predicate for matching ASCII space characters.
+isSpace_w8 :: Word8 -> Bool
+isSpace_w8 w = w == 32 || w - 9 <= 4
+{-# INLINE isSpace_w8 #-}
+
+
+-- | Parse a space character.
+--
+-- /Note/: This parser only gives correct answers for the ASCII
+-- encoding.  For instance, it does not recognise U+00A0 (non-breaking
+-- space) as a space character, even though it is a valid ISO-8859-15
+-- byte.
+space :: Parser Char
+space = satisfy isSpace <?> "space"
+{-# INLINE space #-}
+
+-- | Match a specific character.
+char :: Char -> Parser Char
+char c = satisfy (== c) <?> [c]
+{-# INLINE char #-}
+
+-- | Match a specific character, but return its 'Word8' value.
+char8 :: Char -> Parser Word8
+char8 c = I.satisfy (== c2w c) <?> [c]
+{-# INLINE char8 #-}
+
+-- | Match any character except the given one.
+notChar :: Char -> Parser Char
+notChar c = satisfy (/= c) <?> "not " ++ [c]
+{-# INLINE notChar #-}
+
+-- | Match any character in a set.
+--
+-- >vowel = inClass "aeiou"
+--
+-- Range notation is supported.
+--
+-- >halfAlphabet = inClass "a-nA-N"
+--
+-- To add a literal \'-\' to a set, place it at the beginning or end
+-- of the string.
+inClass :: String -> Char -> Bool
+inClass s = (`memberChar` mySet)
+    where mySet = charClass s
+{-# INLINE inClass #-}
+
+-- | Match any character not in a set.
+notInClass :: String -> Char -> Bool
+notInClass s = not . inClass s
+{-# INLINE notInClass #-}
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'False' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+takeWhile :: (Char -> Bool) -> Parser B.ByteString
+takeWhile p = I.takeWhile (p . w2c)
+{-# INLINE takeWhile #-}
+
+-- | A stateful scanner.  The predicate consumes and transforms a
+-- state argument, and each transformed state is passed to successive
+-- invocations of the predicate on each byte of the input until one
+-- returns 'Nothing' or the input ends.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'Nothing' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+scan :: s -> (s -> Char -> Maybe s) -> Parser B.ByteString
+scan s0 p = I.scan s0 (\s -> p s . w2c)
+{-# INLINE scan #-}
+
+-- | Consume input as long as the predicate returns 'False'
+-- (i.e. until it returns 'True'), and return the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'True' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'many', because such parsers loop until a
+-- failure occurs.  Careless use will thus result in an infinite loop.
+takeTill :: (Char -> Bool) -> Parser B.ByteString
+takeTill p = I.takeTill (p . w2c)
+{-# INLINE takeTill #-}
+
+-- | Skip past input for as long as the predicate returns 'True'.
+skipWhile :: (Char -> Bool) -> Parser ()
+skipWhile p = I.skipWhile (p . w2c)
+{-# INLINE skipWhile #-}
+
+-- | Skip over white space.
+skipSpace :: Parser ()
+skipSpace = I.skipWhile isSpace_w8
+{-# INLINE skipSpace #-}
+
+-- $specalt
+--
+-- If you enable the @OverloadedStrings@ language extension, you can
+-- use the '*>' and '<*' combinators to simplify the common task of
+-- matching a statically known string, then immediately parsing
+-- something else.
+--
+-- Instead of writing something like this:
+--
+-- @
+--'I.string' \"foo\" '*>' wibble
+-- @
+--
+-- Using @OverloadedStrings@, you can omit the explicit use of
+-- 'I.string', and write a more compact version:
+--
+-- @
+-- \"foo\" '*>' wibble
+-- @
+--
+-- (Note: the '.*>' and '<*.' combinators that were originally
+-- provided for this purpose are obsolete and unnecessary, and will be
+-- removed in the next major version.)
+
+-- | /Obsolete/. A type-specialized version of '*>' for
+-- 'B.ByteString'. Use '*>' instead.
+(.*>) :: B.ByteString -> Parser a -> Parser a
+s .*> f = I.string s *> f
+{-# DEPRECATED (.*>) "This is no longer necessary, and will be removed. Use '*>' instead." #-}
+
+-- | /Obsolete/. A type-specialized version of '<*' for
+-- 'B.ByteString'. Use '<*' instead.
+(<*.) :: Parser a -> B.ByteString -> Parser a
+f <*. s = f <* I.string s
+{-# DEPRECATED (<*.) "This is no longer necessary, and will be removed. Use '<*' instead." #-}
+
+-- | A predicate that matches either a carriage return @\'\\r\'@ or
+-- newline @\'\\n\'@ character.
+isEndOfLine :: Word8 -> Bool
+isEndOfLine w = w == 13 || w == 10
+{-# INLINE isEndOfLine #-}
+
+-- | A predicate that matches either a space @\' \'@ or horizontal tab
+-- @\'\\t\'@ character.
+isHorizontalSpace :: Word8 -> Bool
+isHorizontalSpace w = w == 32 || w == 9
+{-# INLINE isHorizontalSpace #-}
+
+-- | Parse and decode an unsigned hexadecimal number.  The hex digits
+-- @\'a\'@ through @\'f\'@ may be upper or lower case.
+--
+-- This parser does not accept a leading @\"0x\"@ string.
+hexadecimal :: (Integral a, Bits a) => Parser a
+hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit
+  where
+    isHexDigit w = (w >= 48 && w <= 57) ||
+                   (w >= 97 && w <= 102) ||
+                   (w >= 65 && w <= 70)
+    step a w | w >= 48 && w <= 57  = (a `shiftL` 4) .|. fromIntegral (w - 48)
+             | w >= 97             = (a `shiftL` 4) .|. fromIntegral (w - 87)
+             | otherwise           = (a `shiftL` 4) .|. fromIntegral (w - 55)
+{-# SPECIALISE hexadecimal :: Parser Int #-}
+{-# SPECIALISE hexadecimal :: Parser Int8 #-}
+{-# SPECIALISE hexadecimal :: Parser Int16 #-}
+{-# SPECIALISE hexadecimal :: Parser Int32 #-}
+{-# SPECIALISE hexadecimal :: Parser Int64 #-}
+{-# SPECIALISE hexadecimal :: Parser Integer #-}
+{-# SPECIALISE hexadecimal :: Parser Word #-}
+{-# SPECIALISE hexadecimal :: Parser Word8 #-}
+{-# SPECIALISE hexadecimal :: Parser Word16 #-}
+{-# SPECIALISE hexadecimal :: Parser Word32 #-}
+{-# SPECIALISE hexadecimal :: Parser Word64 #-}
+
+-- | Parse and decode an unsigned decimal number.
+decimal :: Integral a => Parser a
+decimal = B8.foldl' step 0 `fmap` I.takeWhile1 isDigit_w8
+  where step a w = a * 10 + fromIntegral (w - 48)
+{-# SPECIALISE decimal :: Parser Int #-}
+{-# SPECIALISE decimal :: Parser Int8 #-}
+{-# SPECIALISE decimal :: Parser Int16 #-}
+{-# SPECIALISE decimal :: Parser Int32 #-}
+{-# SPECIALISE decimal :: Parser Int64 #-}
+{-# SPECIALISE decimal :: Parser Integer #-}
+{-# SPECIALISE decimal :: Parser Word #-}
+{-# SPECIALISE decimal :: Parser Word8 #-}
+{-# SPECIALISE decimal :: Parser Word16 #-}
+{-# SPECIALISE decimal :: Parser Word32 #-}
+{-# SPECIALISE decimal :: Parser Word64 #-}
+
+-- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
+-- character.
+signed :: Num a => Parser a -> Parser a
+{-# SPECIALISE signed :: Parser Int -> Parser Int #-}
+{-# SPECIALISE signed :: Parser Int8 -> Parser Int8 #-}
+{-# SPECIALISE signed :: Parser Int16 -> Parser Int16 #-}
+{-# SPECIALISE signed :: Parser Int32 -> Parser Int32 #-}
+{-# SPECIALISE signed :: Parser Int64 -> Parser Int64 #-}
+{-# SPECIALISE signed :: Parser Integer -> Parser Integer #-}
+signed p = (negate <$> (char8 '-' *> p))
+       <|> (char8 '+' *> p)
+       <|> p
+
+-- | Parse a rational number.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+--
+-- /Note/: this parser is not safe for use with inputs from untrusted
+-- sources.  An input with a suitably large exponent such as
+-- @"1e1000000000"@ will cause a huge 'Integer' to be allocated,
+-- resulting in what is effectively a denial-of-service attack.
+--
+-- In most cases, it is better to use 'double' or 'scientific'
+-- instead.
+rational :: Fractional a => Parser a
+{-# SPECIALIZE rational :: Parser Double #-}
+{-# SPECIALIZE rational :: Parser Float #-}
+{-# SPECIALIZE rational :: Parser Rational #-}
+{-# SPECIALIZE rational :: Parser Scientific #-}
+rational = scientifically realToFrac
+
+-- | Parse a 'Double'.
+--
+-- This parser accepts an optional leading sign character, followed by
+-- at most one decimal digit.  The syntax is similar to that accepted by
+-- the 'read' function, with the exception that a trailing @\'.\'@ is
+-- consumed.
+--
+-- === Examples
+--
+-- These examples use this helper:
+--
+-- @
+-- r :: 'Parser' a -> 'Data.ByteString.ByteString' -> 'Data.Attoparsec.ByteString.Result' a
+-- r p s = 'feed' ('Data.Attoparsec.parse' p s) 'mempty'
+-- @
+--
+-- Examples with behaviour identical to 'read', if you feed an empty
+-- continuation to the first result:
+--
+-- > double "3"     == Done "" 3.0
+-- > double "3.1"   == Done "" 3.1
+-- > double "3e4"   == Done "" 30000.0
+-- > double "3.1e4" == Done "" 31000.0
+-- > double "3e"    == Done "e" 3.0
+--
+-- Examples with behaviour identical to 'read':
+--
+-- > double ".3"    == Fail ".3" _ _
+-- > double "e3"    == Fail "e3" _ _
+--
+-- Example of difference from 'read':
+--
+-- > double "3.foo" == Done "foo" 3.0
+--
+-- This function does not accept string representations of \"NaN\" or
+-- \"Infinity\".
+double :: Parser Double
+double = scientifically Sci.toRealFloat
+
+-- | Parse a number, attempting to preserve both speed and precision.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+number :: Parser Number
+number = scientifically $ \s ->
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
+            in if e >= 0
+               then I (c * 10 ^ e)
+               else D (Sci.toRealFloat s)
+{-# DEPRECATED number "Use 'scientific' instead." #-}
+
+-- | Parse a scientific number.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+scientific :: Parser Scientific
+scientific = scientifically id
+
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
+{-# INLINE scientifically #-}
+scientifically :: (Scientific -> a) -> Parser a
+scientifically h = do
+  let minus = 45
+      plus  = 43
+  sign <- I.peekWord8'
+  let !positive = sign == plus || sign /= minus
+  when (sign == plus || sign == minus) $
+    void $ I.anyWord8
+
+  n <- decimal
+
+  let f fracDigits = SP (B8.foldl' step n fracDigits)
+                        (negate $ B8.length fracDigits)
+      step a w = a * 10 + fromIntegral (w - 48)
+
+  dotty <- I.peekWord8
+  -- '.' -> ascii 46
+  SP c e <- case dotty of
+              Just 46 -> I.anyWord8 *> (f <$> I.takeWhile isDigit_w8)
+              _       -> pure (SP n 0)
+
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
+
+  let littleE = 101
+      bigE    = 69
+  (I.satisfy (\ex -> ex == littleE || ex == bigE) *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)
diff --git a/Data/Attoparsec/ByteString/Internal.hs b/Data/Attoparsec/ByteString/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/ByteString/Internal.hs
@@ -0,0 +1,590 @@
+{-# LANGUAGE BangPatterns, CPP, GADTs, OverloadedStrings, RankNTypes,
+    RecordWildCards #-}
+-- |
+-- Module      :  Data.Attoparsec.ByteString.Internal
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient parser combinators for 'ByteString' strings,
+-- loosely based on the Parsec library.
+
+module Data.Attoparsec.ByteString.Internal
+    (
+    -- * Parser types
+      Parser
+    , Result
+
+    -- * Running parsers
+    , parse
+    , parseOnly
+
+    -- * Combinators
+    , module Data.Attoparsec.Combinator
+
+    -- * Parsing individual bytes
+    , satisfy
+    , satisfyWith
+    , anyWord8
+    , skip
+    , word8
+    , notWord8
+
+    -- ** Lookahead
+    , peekWord8
+    , peekWord8'
+
+    -- ** Byte classes
+    , inClass
+    , notInClass
+
+    -- * Parsing more complicated structures
+    , storable
+
+    -- * Efficient string handling
+    , skipWhile
+    , string
+    , stringCI
+    , take
+    , scan
+    , runScanner
+    , takeWhile
+    , takeWhile1
+    , takeWhileIncluding
+    , takeTill
+    , getChunk
+
+    -- ** Consume all remaining input
+    , takeByteString
+    , takeLazyByteString
+
+    -- * Utilities
+    , endOfLine
+    , endOfInput
+    , match
+    , atEnd
+    ) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+import Control.Applicative ((<|>))
+import Control.Monad (when)
+import Data.Attoparsec.ByteString.Buffer (Buffer, buffer)
+import Data.Attoparsec.ByteString.FastSet (charClass, memberWord8)
+import Data.Attoparsec.Combinator ((<?>))
+import Data.Attoparsec.Internal
+import Data.Attoparsec.Internal.Compat
+import Data.Attoparsec.Internal.Fhthagn (inlinePerformIO)
+import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
+import Data.ByteString (ByteString)
+import Data.List (intercalate)
+import Data.Word (Word8)
+import Foreign.ForeignPtr (withForeignPtr)
+import Foreign.Ptr (castPtr, minusPtr, plusPtr)
+import Foreign.Storable (Storable(peek, sizeOf))
+import Prelude hiding (getChar, succ, take, takeWhile)
+import qualified Data.Attoparsec.ByteString.Buffer as Buf
+import qualified Data.Attoparsec.Internal.Types as T
+import qualified Data.ByteString as B8
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Internal as B
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString.Unsafe as B
+
+type Parser = T.Parser ByteString
+type Result = IResult ByteString
+type Failure r = T.Failure ByteString Buffer r
+type Success a r = T.Success ByteString Buffer a r
+
+-- | The parser @satisfy p@ succeeds for any byte for which the
+-- predicate @p@ returns 'True'. Returns the byte that is actually
+-- parsed.
+--
+-- >digit = satisfy isDigit
+-- >    where isDigit w = w >= 48 && w <= 57
+satisfy :: (Word8 -> Bool) -> Parser Word8
+satisfy p = do
+  h <- peekWord8'
+  if p h
+    then advance 1 >> return h
+    else fail "satisfy"
+{-# INLINE satisfy #-}
+
+-- | The parser @skip p@ succeeds for any byte for which the predicate
+-- @p@ returns 'True'.
+--
+-- >skipDigit = skip isDigit
+-- >    where isDigit w = w >= 48 && w <= 57
+skip :: (Word8 -> Bool) -> Parser ()
+skip p = do
+  h <- peekWord8'
+  if p h
+    then advance 1
+    else fail "skip"
+
+-- | The parser @satisfyWith f p@ transforms a byte, and succeeds if
+-- the predicate @p@ returns 'True' on the transformed value. The
+-- parser returns the transformed byte that was parsed.
+satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a
+satisfyWith f p = do
+  h <- peekWord8'
+  let c = f h
+  if p c
+    then advance 1 >> return c
+    else fail "satisfyWith"
+{-# INLINE satisfyWith #-}
+
+storable :: Storable a => Parser a
+storable = hack undefined
+ where
+  hack :: Storable b => b -> Parser b
+  hack dummy = do
+    (fp,o,_) <- B.toForeignPtr `fmap` take (sizeOf dummy)
+    return . inlinePerformIO . withForeignPtr fp $ \p ->
+        peek (castPtr $ p `plusPtr` o)
+
+-- | Consume exactly @n@ bytes of input.
+take :: Int -> Parser ByteString
+take n0 = do
+  let n = max n0 0
+  s <- ensure n
+  advance n >> return s
+{-# INLINE take #-}
+
+-- | @string s@ parses a sequence of bytes that identically match
+-- @s@. Returns the parsed string (i.e. @s@).  This parser consumes no
+-- input if it fails (even if a partial match).
+--
+-- /Note/: The behaviour of this parser is different to that of the
+-- similarly-named parser in Parsec, as this one is all-or-nothing.
+-- To illustrate the difference, the following parser will fail under
+-- Parsec given an input of @\"for\"@:
+--
+-- >string "foo" <|> string "for"
+--
+-- The reason for its failure is that the first branch is a
+-- partial match, and will consume the letters @\'f\'@ and @\'o\'@
+-- before failing.  In attoparsec, the above parser will /succeed/ on
+-- that input, because the failed first branch will consume nothing.
+string :: ByteString -> Parser ByteString
+string s = string_ (stringSuspended id) id s
+{-# INLINE string #-}
+
+-- ASCII-specific but fast, oh yes.
+toLower :: Word8 -> Word8
+toLower w | w >= 65 && w <= 90 = w + 32
+          | otherwise          = w
+
+-- | Satisfy a literal string, ignoring case.
+stringCI :: ByteString -> Parser ByteString
+stringCI s = string_ (stringSuspended lower) lower s
+  where lower = B8.map toLower
+{-# INLINE stringCI #-}
+
+string_ :: (forall r. ByteString -> ByteString -> Buffer -> Pos -> More
+            -> Failure r -> Success ByteString r -> Result r)
+        -> (ByteString -> ByteString)
+        -> ByteString -> Parser ByteString
+string_ suspended f s0 = T.Parser $ \t pos more lose succ ->
+  let n = B.length s
+      s = f s0
+  in if lengthAtLeast pos n t
+     then let t' = substring pos (Pos n) t
+          in if s == f t'
+             then succ t (pos + Pos n) more t'
+             else lose t pos more [] "string"
+     else let t' = Buf.unsafeDrop (fromPos pos) t
+          in if f t' `B.isPrefixOf` s
+             then suspended s (B.drop (B.length t') s) t pos more lose succ
+             else lose t pos more [] "string"
+{-# INLINE string_ #-}
+
+stringSuspended :: (ByteString -> ByteString)
+                -> ByteString -> ByteString -> Buffer -> Pos -> More
+                -> Failure r
+                -> Success ByteString r
+                -> Result r
+stringSuspended f s0 s t pos more lose succ =
+    runParser (demandInput_ >>= go) t pos more lose succ
+  where go s'0   = T.Parser $ \t' pos' more' lose' succ' ->
+          let m  = B.length s
+              s' = f s'0
+              n  = B.length s'
+          in if n >= m
+             then if B.unsafeTake m s' == s
+                  then let o = Pos (B.length s0)
+                       in succ' t' (pos' + o) more'
+                          (substring pos' o t')
+                  else lose' t' pos' more' [] "string"
+             else if s' == B.unsafeTake n s
+                  then stringSuspended f s0 (B.unsafeDrop n s)
+                       t' pos' more' lose' succ'
+                  else lose' t' pos' more' [] "string"
+
+-- | Skip past input for as long as the predicate returns 'True'.
+skipWhile :: (Word8 -> Bool) -> Parser ()
+skipWhile p = go
+ where
+  go = do
+    t <- B8.takeWhile p <$> get
+    continue <- inputSpansChunks (B.length t)
+    when continue go
+{-# INLINE skipWhile #-}
+
+-- | Consume input as long as the predicate returns 'False'
+-- (i.e. until it returns 'True'), and return the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'True' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+takeTill :: (Word8 -> Bool) -> Parser ByteString
+takeTill p = takeWhile (not . p)
+{-# INLINE takeTill #-}
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'False' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+takeWhile :: (Word8 -> Bool) -> Parser ByteString
+takeWhile p = do
+    s <- B8.takeWhile p <$> get
+    continue <- inputSpansChunks (B.length s)
+    if continue
+      then takeWhileAcc p [s]
+      else return s
+{-# INLINE takeWhile #-}
+
+takeWhileAcc :: (Word8 -> Bool) -> [ByteString] -> Parser ByteString
+takeWhileAcc p = go
+ where
+  go acc = do
+    s <- B8.takeWhile p <$> get
+    continue <- inputSpansChunks (B.length s)
+    if continue
+      then go (s:acc)
+      else return $ concatReverse (s:acc)
+{-# INLINE takeWhileAcc #-}
+
+-- | Consume input until immediately after the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser will consume at least one 'Word8' or fail.
+takeWhileIncluding :: (Word8 -> Bool) -> Parser B.ByteString
+takeWhileIncluding p = do
+  (s', t) <- B8.span p <$> get
+  case B8.uncons t of
+    -- Since we reached a break point and managed to get the next byte,
+    -- input can not have been exhausted thus we succed and advance unconditionally.
+    Just (h, _) -> do
+      let s = s' `B8.snoc` h
+      advance (B8.length s)
+      return s
+    -- The above isn't true so either we ran out of input or we need to process the next chunk.
+    Nothing -> do
+      continue <- inputSpansChunks (B8.length s')
+      if continue
+        then takeWhileIncAcc p [s']
+        -- Our spec says that if we run out of input we fail.
+        else fail "takeWhileIncluding reached end of input"
+{-# INLINE takeWhileIncluding #-}
+
+takeWhileIncAcc :: (Word8 -> Bool) -> [B.ByteString] -> Parser B.ByteString
+takeWhileIncAcc p = go
+ where
+   go acc = do
+     (s', t) <- B8.span p <$> get
+     case B8.uncons t of
+       Just (h, _) -> do
+         let s = s' `B8.snoc` h
+         advance (B8.length s)
+         return (concatReverse $ s:acc)
+       Nothing -> do
+         continue <- inputSpansChunks (B8.length s')
+         if continue
+           then go (s':acc)
+           else fail "takeWhileIncAcc reached end of input"
+{-# INLINE takeWhileIncAcc #-}
+
+takeRest :: Parser [ByteString]
+takeRest = go []
+ where
+  go acc = do
+    input <- wantInput
+    if input
+      then do
+        s <- get
+        advance (B.length s)
+        go (s:acc)
+      else return (reverse acc)
+
+-- | Consume all remaining input and return it as a single string.
+takeByteString :: Parser ByteString
+takeByteString = B.concat `fmap` takeRest
+
+-- | Consume all remaining input and return it as a single string.
+takeLazyByteString :: Parser L.ByteString
+takeLazyByteString = L.fromChunks `fmap` takeRest
+
+-- | Return the rest of the current chunk without consuming anything.
+--
+-- If the current chunk is empty, then ask for more input.
+-- If there is no more input, then return 'Nothing'
+getChunk :: Parser (Maybe ByteString)
+getChunk = do
+  input <- wantInput
+  if input
+    then Just <$> get
+    else return Nothing
+
+data T s = T {-# UNPACK #-} !Int s
+
+scan_ :: (s -> [ByteString] -> Parser r) -> s -> (s -> Word8 -> Maybe s)
+         -> Parser r
+scan_ f s0 p = go [] s0
+ where
+  go acc s1 = do
+    let scanner bs = withPS bs $ \fp off len ->
+          withForeignPtr fp $ \ptr0 -> do
+            let start = ptr0 `plusPtr` off
+                end   = start `plusPtr` len
+                inner ptr !s
+                  | ptr < end = do
+                    w <- peek ptr
+                    case p s w of
+                      Just s' -> inner (ptr `plusPtr` 1) s'
+                      _       -> done (ptr `minusPtr` start) s
+                  | otherwise = done (ptr `minusPtr` start) s
+                done !i !s = return (T i s)
+            inner start s1
+    bs <- get
+    let T i s' = inlinePerformIO $ scanner bs
+        !h = B.unsafeTake i bs
+    continue <- inputSpansChunks i
+    if continue
+      then go (h:acc) s'
+      else f s' (h:acc)
+{-# INLINE scan_ #-}
+
+-- | A stateful scanner.  The predicate consumes and transforms a
+-- state argument, and each transformed state is passed to successive
+-- invocations of the predicate on each byte of the input until one
+-- returns 'Nothing' or the input ends.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'Nothing' on the first byte of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+scan :: s -> (s -> Word8 -> Maybe s) -> Parser ByteString
+scan = scan_ $ \_ chunks -> return $! concatReverse chunks
+{-# INLINE scan #-}
+
+-- | Like 'scan', but generalized to return the final state of the
+-- scanner.
+runScanner :: s -> (s -> Word8 -> Maybe s) -> Parser (ByteString, s)
+runScanner = scan_ $ \s xs -> let !sx = concatReverse xs in return (sx, s)
+{-# INLINE runScanner #-}
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser requires the predicate to succeed on at least one byte
+-- of input: it will fail if the predicate never returns 'True' or if
+-- there is no input left.
+takeWhile1 :: (Word8 -> Bool) -> Parser ByteString
+takeWhile1 p = do
+  (`when` demandInput) =<< endOfChunk
+  s <- B8.takeWhile p <$> get
+  let len = B.length s
+  if len == 0
+    then fail "takeWhile1"
+    else do
+      advance len
+      eoc <- endOfChunk
+      if eoc
+        then takeWhileAcc p [s]
+        else return s
+{-# INLINE takeWhile1 #-}
+
+-- | Match any byte in a set.
+--
+-- >vowel = inClass "aeiou"
+--
+-- Range notation is supported.
+--
+-- >halfAlphabet = inClass "a-nA-N"
+--
+-- To add a literal @\'-\'@ to a set, place it at the beginning or end
+-- of the string.
+inClass :: String -> Word8 -> Bool
+inClass s = (`memberWord8` mySet)
+    where mySet = charClass s
+          {-# NOINLINE mySet #-}
+{-# INLINE inClass #-}
+
+-- | Match any byte not in a set.
+notInClass :: String -> Word8 -> Bool
+notInClass s = not . inClass s
+{-# INLINE notInClass #-}
+
+-- | Match any byte.
+anyWord8 :: Parser Word8
+anyWord8 = satisfy $ const True
+{-# INLINE anyWord8 #-}
+
+-- | Match a specific byte.
+word8 :: Word8 -> Parser Word8
+word8 c = satisfy (== c) <?> show c
+{-# INLINE word8 #-}
+
+-- | Match any byte except the given one.
+notWord8 :: Word8 -> Parser Word8
+notWord8 c = satisfy (/= c) <?> "not " ++ show c
+{-# INLINE notWord8 #-}
+
+-- | Match any byte, to perform lookahead. Returns 'Nothing' if end of
+-- input has been reached. Does not consume any input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+peekWord8 :: Parser (Maybe Word8)
+peekWord8 = T.Parser $ \t pos@(Pos pos_) more _lose succ ->
+  case () of
+    _| pos_ < Buf.length t ->
+       let !w = Buf.unsafeIndex t pos_
+       in succ t pos more (Just w)
+     | more == Complete ->
+       succ t pos more Nothing
+     | otherwise ->
+       let succ' t' pos' more' = let !w = Buf.unsafeIndex t' pos_
+                                 in succ t' pos' more' (Just w)
+           lose' t' pos' more' = succ t' pos' more' Nothing
+       in prompt t pos more lose' succ'
+{-# INLINE peekWord8 #-}
+
+-- | Match any byte, to perform lookahead.  Does not consume any
+-- input, but will fail if end of input has been reached.
+peekWord8' :: Parser Word8
+peekWord8' = T.Parser $ \t pos more lose succ ->
+    if lengthAtLeast pos 1 t
+    then succ t pos more (Buf.unsafeIndex t (fromPos pos))
+    else let succ' t' pos' more' bs' = succ t' pos' more' $! B.unsafeHead bs'
+         in ensureSuspended 1 t pos more lose succ'
+{-# INLINE peekWord8' #-}
+
+-- | Match either a single newline character @\'\\n\'@, or a carriage
+-- return followed by a newline character @\"\\r\\n\"@.
+endOfLine :: Parser ()
+endOfLine = (word8 10 >> return ()) <|> (string "\r\n" >> return ())
+
+-- | Terminal failure continuation.
+failK :: Failure a
+failK t (Pos pos) _more stack msg = Fail (Buf.unsafeDrop pos t) stack msg
+{-# INLINE failK #-}
+
+-- | Terminal success continuation.
+successK :: Success a a
+successK t (Pos pos) _more a = Done (Buf.unsafeDrop pos t) a
+{-# INLINE successK #-}
+
+-- | Run a parser.
+parse :: Parser a -> ByteString -> Result a
+parse m s = T.runParser m (buffer s) (Pos 0) Incomplete failK successK
+{-# INLINE parse #-}
+
+-- | Run a parser that cannot be resupplied via a 'Partial' result.
+--
+-- This function does not force a parser to consume all of its input.
+-- Instead, any residual input will be discarded.  To force a parser
+-- to consume all of its input, use something like this:
+--
+-- @
+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')
+-- @
+parseOnly :: Parser a -> ByteString -> Either String a
+parseOnly m s = case T.runParser m (buffer s) (Pos 0) Complete failK successK of
+                  Fail _ [] err   -> Left err
+                  Fail _ ctxs err -> Left (intercalate " > " ctxs ++ ": " ++ err)
+                  Done _ a        -> Right a
+                  _               -> error "parseOnly: impossible error!"
+{-# INLINE parseOnly #-}
+
+get :: Parser ByteString
+get = T.Parser $ \t pos more _lose succ ->
+  succ t pos more (Buf.unsafeDrop (fromPos pos) t)
+{-# INLINE get #-}
+
+endOfChunk :: Parser Bool
+endOfChunk = T.Parser $ \t pos more _lose succ ->
+  succ t pos more (fromPos pos == Buf.length t)
+{-# INLINE endOfChunk #-}
+
+inputSpansChunks :: Int -> Parser Bool
+inputSpansChunks i = T.Parser $ \t pos_ more _lose succ ->
+  let pos = pos_ + Pos i
+  in if fromPos pos < Buf.length t || more == Complete
+     then succ t pos more False
+     else let lose' t' pos' more' = succ t' pos' more' False
+              succ' t' pos' more' = succ t' pos' more' True
+          in prompt t pos more lose' succ'
+{-# INLINE inputSpansChunks #-}
+
+advance :: Int -> Parser ()
+advance n = T.Parser $ \t pos more _lose succ ->
+  succ t (pos + Pos n) more ()
+{-# INLINE advance #-}
+
+ensureSuspended :: Int -> Buffer -> Pos -> More
+                -> Failure r
+                -> Success ByteString r
+                -> Result r
+ensureSuspended n t pos more lose succ =
+    runParser (demandInput >> go) t pos more lose succ
+  where go = T.Parser $ \t' pos' more' lose' succ' ->
+          if lengthAtLeast pos' n t'
+          then succ' t' pos' more' (substring pos (Pos n) t')
+          else runParser (demandInput >> go) t' pos' more' lose' succ'
+
+-- | If at least @n@ elements of input are available, return the
+-- current input, otherwise fail.
+ensure :: Int -> Parser ByteString
+ensure n = T.Parser $ \t pos more lose succ ->
+    if lengthAtLeast pos n t
+    then succ t pos more (substring pos (Pos n) t)
+    -- The uncommon case is kept out-of-line to reduce code size:
+    else ensureSuspended n t pos more lose succ
+{-# INLINE ensure #-}
+
+-- | Return both the result of a parse and the portion of the input
+-- that was consumed while it was being parsed.
+match :: Parser a -> Parser (ByteString, a)
+match p = T.Parser $ \t pos more lose succ ->
+  let succ' t' pos' more' a =
+        succ t' pos' more' (substring pos (pos'-pos) t', a)
+  in runParser p t pos more lose succ'
+
+lengthAtLeast :: Pos -> Int -> Buffer -> Bool
+lengthAtLeast (Pos pos) n bs = Buf.length bs >= pos + n
+{-# INLINE lengthAtLeast #-}
+
+substring :: Pos -> Pos -> Buffer -> ByteString
+substring (Pos pos) (Pos n) = Buf.substring pos n
+{-# INLINE substring #-}
diff --git a/Data/Attoparsec/ByteString/Lazy.hs b/Data/Attoparsec/ByteString/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/ByteString/Lazy.hs
@@ -0,0 +1,124 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Imports internal modules
+#endif
+
+-- |
+-- Module      :  Data.Attoparsec.ByteString.Lazy
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient combinator parsing that can consume lazy
+-- 'ByteString' strings, loosely based on the Parsec library.
+--
+-- This is essentially the same code as in the 'Data.Attoparsec'
+-- module, only with a 'parse' function that can consume a lazy
+-- 'ByteString' incrementally, and a 'Result' type that does not allow
+-- more input to be fed in.  Think of this as suitable for use with a
+-- lazily read file, e.g. via 'L.readFile' or 'L.hGetContents'.
+--
+-- /Note:/ The various parser functions and combinators such as
+-- 'string' still expect /strict/ 'B.ByteString' parameters, and
+-- return strict 'B.ByteString' results.  Behind the scenes, strict
+-- 'B.ByteString' values are still used internally to store parser
+-- input and manipulate it efficiently.
+
+module Data.Attoparsec.ByteString.Lazy
+    (
+      Result(..)
+    , module Data.Attoparsec.ByteString
+    -- * Running parsers
+    , parse
+    , parseOnly
+    , parseTest
+    -- ** Result conversion
+    , maybeResult
+    , eitherResult
+    ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.ByteString.Lazy.Internal (ByteString(..), chunk)
+import Data.List (intercalate)
+import qualified Data.ByteString as B
+import qualified Data.Attoparsec.ByteString as A
+import qualified Data.Attoparsec.Internal.Types as T
+import Data.Attoparsec.ByteString
+    hiding (IResult(..), Result, eitherResult, maybeResult,
+            parse, parseOnly, parseWith, parseTest)
+
+-- | The result of a parse.
+data Result r = Fail ByteString [String] String
+              -- ^ The parse failed.  The 'ByteString' is the input
+              -- that had not yet been consumed when the failure
+              -- occurred.  The @[@'String'@]@ is a list of contexts
+              -- in which the error occurred.  The 'String' is the
+              -- message describing the error, if any.
+              | Done ByteString r
+              -- ^ The parse succeeded.  The 'ByteString' is the
+              -- input that had not yet been consumed (if any) when
+              -- the parse succeeded.
+
+instance NFData r => NFData (Result r) where
+    rnf (Fail bs ctxs msg) = rnfBS bs `seq` rnf ctxs `seq` rnf msg
+    rnf (Done bs r)        = rnfBS bs `seq` rnf r
+    {-# INLINE rnf #-}
+
+rnfBS :: ByteString -> ()
+rnfBS (Chunk _ xs) = rnfBS xs
+rnfBS Empty        = ()
+{-# INLINE rnfBS #-}
+
+instance Show r => Show (Result r) where
+    show (Fail bs stk msg) =
+        "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg
+    show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r
+
+fmapR :: (a -> b) -> Result a -> Result b
+fmapR _ (Fail st stk msg) = Fail st stk msg
+fmapR f (Done bs r)       = Done bs (f r)
+
+instance Functor Result where
+    fmap = fmapR
+
+-- | Run a parser and return its result.
+parse :: A.Parser a -> ByteString -> Result a
+parse p s = case s of
+              Chunk x xs -> go (A.parse p x) xs
+              empty      -> go (A.parse p B.empty) empty
+  where
+    go (T.Fail x stk msg) ys      = Fail (chunk x ys) stk msg
+    go (T.Done x r) ys            = Done (chunk x ys) r
+    go (T.Partial k) (Chunk y ys) = go (k y) ys
+    go (T.Partial k) empty        = go (k B.empty) empty
+
+-- | Run a parser and print its result to standard output.
+parseTest :: (Show a) => A.Parser a -> ByteString -> IO ()
+parseTest p s = print (parse p s)
+
+-- | Convert a 'Result' value to a 'Maybe' value.
+maybeResult :: Result r -> Maybe r
+maybeResult (Done _ r) = Just r
+maybeResult _          = Nothing
+
+-- | Convert a 'Result' value to an 'Either' value.
+eitherResult :: Result r -> Either String r
+eitherResult (Done _ r)        = Right r
+eitherResult (Fail _ [] msg)   = Left msg
+eitherResult (Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)
+
+-- | Run a parser that cannot be resupplied via a 'T.Partial' result.
+--
+-- This function does not force a parser to consume all of its input.
+-- Instead, any residual input will be discarded.  To force a parser
+-- to consume all of its input, use something like this:
+--
+-- @
+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')
+-- @
+parseOnly :: A.Parser a -> ByteString -> Either String a
+parseOnly p = eitherResult . parse p
+{-# INLINE parseOnly #-}
diff --git a/Data/Attoparsec/Char8.hs b/Data/Attoparsec/Char8.hs
--- a/Data/Attoparsec/Char8.hs
+++ b/Data/Attoparsec/Char8.hs
@@ -1,502 +1,23 @@
-{-# LANGUAGE BangPatterns, FlexibleInstances #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
 -- |
 -- Module      :  Data.Attoparsec.Char8
--- Copyright   :  Bryan O'Sullivan 2007-2010
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
--- 
+--
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
 --
 -- Simple, efficient, character-oriented combinator parsing for
--- 'B.ByteString' strings, loosely based on the Parsec library.
+-- 'Data.ByteString.ByteString' strings, loosely based on the Parsec
+-- library.
+--
+-- This module is deprecated. Use "Data.Attoparsec.ByteString.Char8"
+-- instead.
 
 module Data.Attoparsec.Char8
+    {-# DEPRECATED "This module will be removed in the next major release." #-}
     (
-    -- * Character encodings
-    -- $encodings
-
-    -- * Parser types
-      Parser
-    , A.Result(..)
-
-    -- * Running parsers
-    , A.parse
-    , A.feed
-    , A.parseOnly
-    , A.parseTest
-    , A.parseWith
-
-    -- ** Result conversion
-    , A.maybeResult
-    , A.eitherResult
-
-    -- * Combinators
-    , (I.<?>)
-    , I.try
-    , module Data.Attoparsec.Combinator
-
-    -- * Parsing individual characters
-    , char
-    , char8
-    , anyChar
-    , notChar
-    , satisfy
-
-    -- ** Special character parsers
-    , digit
-    , letter_iso8859_15
-    , letter_ascii
-    , space
-
-    -- ** Fast predicates
-    , isDigit
-    , isDigit_w8
-    , isAlpha_iso8859_15
-    , isAlpha_ascii
-    , isSpace
-    , isSpace_w8
-
-    -- *** Character classes
-    , inClass
-    , notInClass
-
-    -- * Efficient string handling
-    , I.string
-    , stringCI
-    , skipSpace
-    , skipWhile
-    , I.take
-    , scan
-    , takeWhile
-    , takeWhile1
-    , takeTill
-
-    -- ** Consume all remaining input
-    , I.takeByteString
-    , I.takeLazyByteString
-
-    -- * Text parsing
-    , I.endOfLine
-    , isEndOfLine
-    , isHorizontalSpace
-
-    -- * Numeric parsers
-    , decimal
-    , hexadecimal
-    , signed
-    , double
-    , Number(..)
-    , number
-    , rational
-
-    -- * State observation and manipulation functions
-    , I.endOfInput
-    , I.atEnd
+      module Data.Attoparsec.ByteString.Char8
     ) where
 
-import Control.Applicative ((*>), (<$>), (<|>))
-import Data.Attoparsec.Combinator
-import Data.Attoparsec.FastSet (charClass, memberChar)
-import Data.Attoparsec.Internal (Parser, (<?>))
-import Data.Attoparsec.Number (Number(..))
-import Data.Bits (Bits, (.|.), shiftL)
-import Data.ByteString.Internal (c2w, w2c)
-import Data.Int (Int8, Int16, Int32, Int64)
-import Data.Ratio ((%))
-import Data.String (IsString(..))
-import Data.Word (Word8, Word16, Word32, Word64, Word)
-import Prelude hiding (takeWhile)
-import qualified Data.Attoparsec as A
-import qualified Data.Attoparsec.Internal as I
-import qualified Data.ByteString as B8
-import qualified Data.ByteString.Char8 as B
-
-instance IsString (Parser B.ByteString) where
-    fromString = I.string . B.pack
-
--- $encodings
---
--- This module is intended for parsing text that is
--- represented using an 8-bit character set, e.g. ASCII or
--- ISO-8859-15.  It /does not/ make any attempt to deal with character
--- encodings, multibyte characters, or wide characters.  In
--- particular, all attempts to use characters above code point U+00FF
--- will give wrong answers.
---
--- Code points below U+0100 are simply translated to and from their
--- numeric values, so e.g. the code point U+00A4 becomes the byte
--- @0xA4@ (which is the Euro symbol in ISO-8859-15, but the generic
--- currency sign in ISO-8859-1).  Haskell 'Char' values above U+00FF
--- are truncated, so e.g. U+1D6B7 is truncated to the byte @0xB7@.
-
--- ASCII-specific but fast, oh yes.
-toLower :: Word8 -> Word8
-toLower w | w >= 65 && w <= 90 = w + 32
-          | otherwise          = w
-
--- | Satisfy a literal string, ignoring case.
-stringCI :: B.ByteString -> Parser B.ByteString
-stringCI = I.stringTransform (B8.map toLower)
-{-# INLINE stringCI #-}
-
--- | Consume input as long as the predicate returns 'True', and return
--- the consumed input.
---
--- This parser requires the predicate to succeed on at least one byte
--- of input: it will fail if the predicate never returns 'True' or if
--- there is no input left.
-takeWhile1 :: (Char -> Bool) -> Parser B.ByteString
-takeWhile1 p = I.takeWhile1 (p . w2c)
-{-# INLINE takeWhile1 #-}
-
--- | The parser @satisfy p@ succeeds for any byte for which the
--- predicate @p@ returns 'True'. Returns the byte that is actually
--- parsed.
---
--- >digit = satisfy isDigit
--- >    where isDigit c = c >= '0' && c <= '9'
-satisfy :: (Char -> Bool) -> Parser Char
-satisfy = I.satisfyWith w2c
-{-# INLINE satisfy #-}
-
--- | Match a letter, in the ISO-8859-15 encoding.
-letter_iso8859_15 :: Parser Char
-letter_iso8859_15 = satisfy isAlpha_iso8859_15 <?> "letter_iso8859_15"
-{-# INLINE letter_iso8859_15 #-}
-
--- | Match a letter, in the ASCII encoding.
-letter_ascii :: Parser Char
-letter_ascii = satisfy isAlpha_ascii <?> "letter_ascii"
-{-# INLINE letter_ascii #-}
-
--- | A fast alphabetic predicate for the ISO-8859-15 encoding
---
--- /Note/: For all character encodings other than ISO-8859-15, and
--- almost all Unicode code points above U+00A3, this predicate gives
--- /wrong answers/.
-isAlpha_iso8859_15 :: Char -> Bool
-isAlpha_iso8859_15 c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
-                       (c >= '\166' && moby c)
-  where moby = notInClass "\167\169\171-\179\182\183\185\187\191\215\247"
-        {-# NOINLINE moby #-}
-{-# INLINE isAlpha_iso8859_15 #-}
-
--- | A fast alphabetic predicate for the ASCII encoding
---
--- /Note/: For all character encodings other than ASCII, and
--- almost all Unicode code points above U+007F, this predicate gives
--- /wrong answers/.
-isAlpha_ascii :: Char -> Bool
-isAlpha_ascii c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-{-# INLINE isAlpha_ascii #-}
-
--- | Parse a single digit.
-digit :: Parser Char
-digit = satisfy isDigit <?> "digit"
-{-# INLINE digit #-}
-
--- | A fast digit predicate.
-isDigit :: Char -> Bool
-isDigit c = c >= '0' && c <= '9'
-{-# INLINE isDigit #-}
-
--- | A fast digit predicate.
-isDigit_w8 :: Word8 -> Bool
-isDigit_w8 w = w >= 48 && w <= 57
-{-# INLINE isDigit_w8 #-}
-
--- | Match any character.
-anyChar :: Parser Char
-anyChar = satisfy $ const True
-{-# INLINE anyChar #-}
-
--- | Fast predicate for matching ASCII space characters.
---
--- /Note/: This predicate only gives correct answers for the ASCII
--- encoding.  For instance, it does not recognise U+00A0 (non-breaking
--- space) as a space character, even though it is a valid ISO-8859-15
--- byte. For a Unicode-aware and only slightly slower predicate,
--- use 'Data.Char.isSpace'
-isSpace :: Char -> Bool
-isSpace c = (c == ' ') || ('\t' <= c && c <= '\r')
-{-# INLINE isSpace #-}
-
--- | Fast 'Word8' predicate for matching ASCII space characters.
-isSpace_w8 :: Word8 -> Bool
-isSpace_w8 w = (w == 32) || (9 <= w && w <= 13)
-{-# INLINE isSpace_w8 #-}
-
-
--- | Parse a space character.
---
--- /Note/: This parser only gives correct answers for the ASCII
--- encoding.  For instance, it does not recognise U+00A0 (non-breaking
--- space) as a space character, even though it is a valid ISO-8859-15
--- byte.
-space :: Parser Char
-space = satisfy isSpace <?> "space"
-{-# INLINE space #-}
-
--- | Match a specific character.
-char :: Char -> Parser Char
-char c = satisfy (== c) <?> [c]
-{-# INLINE char #-}
-
--- | Match a specific character, but return its 'Word8' value.
-char8 :: Char -> Parser Word8
-char8 c = I.satisfy (== c2w c) <?> [c]
-{-# INLINE char8 #-}
-
--- | Match any character except the given one.
-notChar :: Char -> Parser Char
-notChar c = satisfy (/= c) <?> "not " ++ [c]
-{-# INLINE notChar #-}
-
--- | Match any character in a set.
---
--- >vowel = inClass "aeiou"
---
--- Range notation is supported.
---
--- >halfAlphabet = inClass "a-nA-N"
---
--- To add a literal \'-\' to a set, place it at the beginning or end
--- of the string.
-inClass :: String -> Char -> Bool
-inClass s = (`memberChar` mySet)
-    where mySet = charClass s
-{-# INLINE inClass #-}
-
--- | Match any character not in a set.
-notInClass :: String -> Char -> Bool
-notInClass s = not . inClass s
-{-# INLINE notInClass #-}
-
--- | Consume input as long as the predicate returns 'True', and return
--- the consumed input.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'False' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-takeWhile :: (Char -> Bool) -> Parser B.ByteString
-takeWhile p = I.takeWhile (p . w2c)
-{-# INLINE takeWhile #-}
-
--- | A stateful scanner.  The predicate consumes and transforms a
--- state argument, and each transformed state is passed to successive
--- invocations of the predicate on each byte of the input until one
--- returns 'Nothing' or the input ends.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'Nothing' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-scan :: s -> (s -> Char -> Maybe s) -> Parser B.ByteString
-scan s0 p = I.scan s0 (\s -> p s . w2c)
-{-# INLINE scan #-}
-
--- | Consume input as long as the predicate returns 'False'
--- (i.e. until it returns 'True'), and return the consumed input.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'True' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-takeTill :: (Char -> Bool) -> Parser B.ByteString
-takeTill p = I.takeTill (p . w2c)
-{-# INLINE takeTill #-}
-
--- | Skip past input for as long as the predicate returns 'True'.
-skipWhile :: (Char -> Bool) -> Parser ()
-skipWhile p = I.skipWhile (p . w2c)
-{-# INLINE skipWhile #-}
-
--- | Skip over white space.
-skipSpace :: Parser ()
-skipSpace = I.skipWhile isSpace_w8
-{-# INLINE skipSpace #-}
-
--- | A predicate that matches either a carriage return @\'\\r\'@ or
--- newline @\'\\n\'@ character.
-isEndOfLine :: Word8 -> Bool
-isEndOfLine w = w == 13 || w == 10
-{-# INLINE isEndOfLine #-}
-
--- | A predicate that matches either a space @\' \'@ or horizontal tab
--- @\'\\t\'@ character.
-isHorizontalSpace :: Word8 -> Bool
-isHorizontalSpace w = w == 32 || w == 9
-{-# INLINE isHorizontalSpace #-}
-
--- | Parse and decode an unsigned hexadecimal number.  The hex digits
--- @\'a\'@ through @\'f\'@ may be upper or lower case.
---
--- This parser does not accept a leading @\"0x\"@ string.
-hexadecimal :: (Integral a, Bits a) => Parser a
-hexadecimal = B8.foldl' step 0 `fmap` I.takeWhile1 isHexDigit
-  where
-    isHexDigit w = (w >= 48 && w <= 57) ||
-                   (w >= 97 && w <= 102) ||
-                   (w >= 65 && w <= 90)
-    step a w | w >= 48 && w <= 57  = (a `shiftL` 4) .|. fromIntegral (w - 48)
-             | w >= 97             = (a `shiftL` 4) .|. fromIntegral (w - 87)
-             | otherwise           = (a `shiftL` 4) .|. fromIntegral (w - 55)
-{-# SPECIALISE hexadecimal :: Parser Int #-}
-{-# SPECIALISE hexadecimal :: Parser Int8 #-}
-{-# SPECIALISE hexadecimal :: Parser Int16 #-}
-{-# SPECIALISE hexadecimal :: Parser Int32 #-}
-{-# SPECIALISE hexadecimal :: Parser Int64 #-}
-{-# SPECIALISE hexadecimal :: Parser Integer #-}
-{-# SPECIALISE hexadecimal :: Parser Word #-}
-{-# SPECIALISE hexadecimal :: Parser Word8 #-}
-{-# SPECIALISE hexadecimal :: Parser Word16 #-}
-{-# SPECIALISE hexadecimal :: Parser Word32 #-}
-{-# SPECIALISE hexadecimal :: Parser Word64 #-}
-
--- | Parse and decode an unsigned decimal number.
-decimal :: Integral a => Parser a
-decimal = B8.foldl' step 0 `fmap` I.takeWhile1 isDig
-  where isDig w  = w >= 48 && w <= 57
-        step a w = a * 10 + fromIntegral (w - 48)
-{-# SPECIALISE decimal :: Parser Int #-}
-{-# SPECIALISE decimal :: Parser Int8 #-}
-{-# SPECIALISE decimal :: Parser Int16 #-}
-{-# SPECIALISE decimal :: Parser Int32 #-}
-{-# SPECIALISE decimal :: Parser Int64 #-}
-{-# SPECIALISE decimal :: Parser Integer #-}
-{-# SPECIALISE decimal :: Parser Word #-}
-{-# SPECIALISE decimal :: Parser Word8 #-}
-{-# SPECIALISE decimal :: Parser Word16 #-}
-{-# SPECIALISE decimal :: Parser Word32 #-}
-{-# SPECIALISE decimal :: Parser Word64 #-}
-
--- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
--- character.
-signed :: Num a => Parser a -> Parser a
-{-# SPECIALISE signed :: Parser Int -> Parser Int #-}
-{-# SPECIALISE signed :: Parser Int8 -> Parser Int8 #-}
-{-# SPECIALISE signed :: Parser Int16 -> Parser Int16 #-}
-{-# SPECIALISE signed :: Parser Int32 -> Parser Int32 #-}
-{-# SPECIALISE signed :: Parser Int64 -> Parser Int64 #-}
-{-# SPECIALISE signed :: Parser Integer -> Parser Integer #-}
-signed p = (negate <$> (char8 '-' *> p))
-       <|> (char8 '+' *> p)
-       <|> p
-
--- | Parse a rational number.
---
--- This parser accepts an optional leading sign character, followed by
--- at least one decimal digit.  The syntax similar to that accepted by
--- the 'read' function, with the exception that a trailing @\'.\'@ or
--- @\'e\'@ /not/ followed by a number is not consumed.
---
--- Examples with behaviour identical to 'read', if you feed an empty
--- continuation to the first result:
---
--- >rational "3"     == Done 3.0 ""
--- >rational "3.1"   == Done 3.1 ""
--- >rational "3e4"   == Done 30000.0 ""
--- >rational "3.1e4" == Done 31000.0, ""
-
--- Examples with behaviour identical to 'read':
---
--- >rational ".3"    == Fail "input does not start with a digit"
--- >rational "e3"    == Fail "input does not start with a digit"
---
--- Examples of differences from 'read':
---
--- >rational "3.foo" == Done 3.0 ".foo"
--- >rational "3e"    == Done 3.0 "e"
---
--- This function does not accept string representations of \"NaN\" or
--- \"Infinity\".
-rational :: Fractional a => Parser a
-{-# SPECIALIZE rational :: Parser Double #-}
-{-# SPECIALIZE rational :: Parser Float #-}
-{-# SPECIALIZE rational :: Parser Rational #-}
-rational = floaty $ \real frac fracDenom -> fromRational $
-                     real % 1 + frac % fracDenom
-
--- | Parse a rational number.
---
--- The syntax accepted by this parser is the same as for 'rational'.
---
--- /Note/: This function is almost ten times faster than 'rational',
--- but is slightly less accurate.
---
--- The 'Double' type supports about 16 decimal places of accuracy.
--- For 94.2% of numbers, this function and 'rational' give identical
--- results, but for the remaining 5.8%, this function loses precision
--- around the 15th decimal place.  For 0.001% of numbers, this
--- function will lose precision at the 13th or 14th decimal place.
---
--- This function does not accept string representations of \"NaN\" or
--- \"Infinity\".
-double :: Parser Double
-double = floaty asDouble
-
-asDouble :: Integer -> Integer -> Integer -> Double
-asDouble real frac fracDenom =
-    fromIntegral real + fromIntegral frac / fromIntegral fracDenom
-{-# INLINE asDouble #-}
-
--- | Parse a number, attempting to preserve both speed and precision.
---
--- The syntax accepted by this parser is the same as for 'rational'.
---
--- /Note/: This function is almost ten times faster than 'rational'.
--- On integral inputs, it gives perfectly accurate answers, and on
--- floating point inputs, it is slightly less accurate than
--- 'rational'.
---
--- This function does not accept string representations of \"NaN\" or
--- \"Infinity\".
-number :: Parser Number
-number = floaty $ \real frac fracDenom ->
-         if frac == 0 && fracDenom == 0
-         then I real
-         else D (asDouble real frac fracDenom)
-{-# INLINE number #-}
-
-data T = T !Integer !Int
-
-floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Parser a
-{-# INLINE floaty #-}
-floaty f = do
-  let minus = 45
-      plus  = 43
-  !positive <- ((== plus) <$> I.satisfy (\c -> c == minus || c == plus)) <|>
-               return True
-  real <- decimal
-  let tryFraction = do
-        let dot = 46
-        _ <- I.satisfy (==dot)
-        ds <- I.takeWhile isDigit_w8
-        case I.parseOnly decimal ds of
-                Right n -> return $ T n (B.length ds)
-                _       -> fail "no digits after decimal"
-  T fraction fracDigits <- tryFraction <|> return (T 0 0)
-  let littleE = 101
-      bigE    = 69
-      e w = w == littleE || w == bigE
-  power <- (I.satisfy e *> signed decimal) <|> return (0::Int)
-  let n = if fracDigits == 0
-          then if power == 0
-               then fromIntegral real
-               else fromIntegral real * (10 ^^ power)
-          else if power == 0
-               then f real fraction (10 ^ fracDigits)
-               else f real fraction (10 ^ fracDigits) * (10 ^^ power)
-  return $ if positive
-           then n
-           else -n
+import Data.Attoparsec.ByteString.Char8
diff --git a/Data/Attoparsec/Combinator.hs b/Data/Attoparsec/Combinator.hs
--- a/Data/Attoparsec/Combinator.hs
+++ b/Data/Attoparsec/Combinator.hs
@@ -1,9 +1,12 @@
 {-# LANGUAGE BangPatterns, CPP #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Imports internal modules
+#endif
 -- |
 -- Module      :  Data.Attoparsec.Combinator
--- Copyright   :  Daan Leijen 1999-2001, Bryan O'Sullivan 2009-2010
+-- Copyright   :  Daan Leijen 1999-2001, Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
--- 
+--
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  portable
@@ -11,42 +14,73 @@
 -- Useful parser combinators, similar to those provided by Parsec.
 module Data.Attoparsec.Combinator
     (
-      choice
+    -- * Combinators
+      try
+    , (<?>)
+    , choice
     , count
     , option
+    , many'
     , many1
+    , many1'
     , manyTill
+    , manyTill'
     , sepBy
+    , sepBy'
     , sepBy1
+    , sepBy1'
     , skipMany
     , skipMany1
     , eitherP
-
-    -- * Inlined implementations of existing functions
-    --
-    -- These are exact duplicates of functions already exported by the
-    -- 'Control.Applicative' module, but whose definitions are
-    -- inlined.  In many cases, this leads to 2x performance
-    -- improvements.
-    , many
+    , feed
+    , satisfyElem
+    , endOfInput
+    , atEnd
+    , lookAhead
     ) where
 
-import Control.Applicative (Alternative, Applicative(..), empty, liftA2,
-                            (<|>), (*>), (<$>))
-#if __GLASGOW_HASKELL__ >= 700
-import Data.Attoparsec.Internal.Types (Parser)
-import qualified Data.Attoparsec.Zepto as Z
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (Applicative(..), (<$>))
+import Data.Monoid (Monoid(mappend))
 #endif
+import Control.Applicative (Alternative(..), liftA2, many, (<|>))
+import Control.Monad (MonadPlus(..))
+import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
+import Data.Attoparsec.Internal (endOfInput, atEnd, satisfyElem)
+import Data.ByteString (ByteString)
+import Data.Foldable (asum)
+import Data.Text (Text)
+import qualified Data.Attoparsec.Zepto as Z
+import Prelude hiding (succ)
 
+-- | Attempt a parse, and if it fails, rewind the input so that no
+-- input appears to have been consumed.
+--
+-- This combinator is provided for compatibility with Parsec.
+-- attoparsec parsers always backtrack on failure.
+try :: Parser i a -> Parser i a
+try = id
+{-# INLINE try #-}
+
+-- | Name the parser, in case failure occurs.
+(<?>) :: Parser i a
+      -> String                 -- ^ the name to use if parsing fails
+      -> Parser i a
+p <?> msg0 = Parser $ \t pos more lose succ ->
+             let lose' t' pos' more' strs msg = lose t' pos' more' (msg0:strs) msg
+             in runParser p t pos more lose' succ
+{-# INLINE (<?>) #-}
+infix 0 <?>
+
 -- | @choice ps@ tries to apply the actions in the list @ps@ in order,
 -- until one of them succeeds. Returns the value of the succeeding
 -- action.
 choice :: Alternative f => [f a] -> f a
-choice = foldr (<|>) empty
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE choice :: [Parser a] -> Parser a #-}
+choice = asum
+{-# SPECIALIZE choice :: [Parser ByteString a]
+                      -> Parser ByteString a #-}
+{-# SPECIALIZE choice :: [Parser Text a] -> Parser Text a #-}
 {-# SPECIALIZE choice :: [Z.Parser a] -> Z.Parser a #-}
-#endif
 
 -- | @option x p@ tries to apply action @p@. If @p@ fails without
 -- consuming input, it returns the value @x@, otherwise the value
@@ -55,11 +89,30 @@
 -- > priority  = option 0 (digitToInt <$> digit)
 option :: Alternative f => a -> f a -> f a
 option x p = p <|> pure x
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE option :: a -> Parser a -> Parser a #-}
+{-# SPECIALIZE option :: a -> Parser ByteString a -> Parser ByteString a #-}
+{-# SPECIALIZE option :: a -> Parser Text a -> Parser Text a #-}
 {-# SPECIALIZE option :: a -> Z.Parser a -> Z.Parser a #-}
-#endif
 
+-- | A version of 'liftM2' that is strict in the result of its first
+-- action.
+liftM2' :: (Monad m) => (a -> b -> c) -> m a -> m b -> m c
+liftM2' f a b = do
+  !x <- a
+  y <- b
+  return (f x y)
+{-# INLINE liftM2' #-}
+
+-- | @many' p@ applies the action @p@ /zero/ or more times. Returns a
+-- list of the returned values of @p@. The value returned by @p@ is
+-- forced to WHNF.
+--
+-- >  word  = many' letter
+many' :: (MonadPlus m) => m a -> m [a]
+many' p = many_p
+  where many_p = some_p `mplus` return []
+        some_p = liftM2' (:) p many_p
+{-# INLINE many' #-}
+
 -- | @many1 p@ applies the action @p@ /one/ or more times. Returns a
 -- list of the returned values of @p@.
 --
@@ -68,61 +121,114 @@
 many1 p = liftA2 (:) p (many p)
 {-# INLINE many1 #-}
 
+-- | @many1' p@ applies the action @p@ /one/ or more times. Returns a
+-- list of the returned values of @p@. The value returned by @p@ is
+-- forced to WHNF.
+--
+-- >  word  = many1' letter
+many1' :: (MonadPlus m) => m a -> m [a]
+many1' p = liftM2' (:) p (many' p)
+{-# INLINE many1' #-}
+
 -- | @sepBy p sep@ applies /zero/ or more occurrences of @p@, separated
 -- by @sep@. Returns a list of the values returned by @p@.
 --
--- > commaSep p  = p `sepBy` (symbol ",")
+-- > commaSep p  = p `sepBy` (char ',')
 sepBy :: Alternative f => f a -> f s -> f [a]
 sepBy p s = liftA2 (:) p ((s *> sepBy1 p s) <|> pure []) <|> pure []
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE sepBy :: Parser a -> Parser s -> Parser [a] #-}
+{-# SPECIALIZE sepBy :: Parser ByteString a -> Parser ByteString s
+                     -> Parser ByteString [a] #-}
+{-# SPECIALIZE sepBy :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
 {-# SPECIALIZE sepBy :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
-#endif
 
+-- | @sepBy' p sep@ applies /zero/ or more occurrences of @p@, separated
+-- by @sep@. Returns a list of the values returned by @p@. The value
+-- returned by @p@ is forced to WHNF.
+--
+-- > commaSep p  = p `sepBy'` (char ',')
+sepBy' :: (MonadPlus m) => m a -> m s -> m [a]
+sepBy' p s = scan `mplus` return []
+  where scan = liftM2' (:) p ((s >> sepBy1' p s) `mplus` return [])
+{-# SPECIALIZE sepBy' :: Parser ByteString a -> Parser ByteString s
+                      -> Parser ByteString [a] #-}
+{-# SPECIALIZE sepBy' :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
+{-# SPECIALIZE sepBy' :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
+
 -- | @sepBy1 p sep@ applies /one/ or more occurrences of @p@, separated
 -- by @sep@. Returns a list of the values returned by @p@.
 --
--- > commaSep p  = p `sepBy` (symbol ",")
+-- > commaSep p  = p `sepBy1` (char ',')
 sepBy1 :: Alternative f => f a -> f s -> f [a]
 sepBy1 p s = scan
     where scan = liftA2 (:) p ((s *> scan) <|> pure [])
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE sepBy1 :: Parser a -> Parser s -> Parser [a] #-}
+{-# SPECIALIZE sepBy1 :: Parser ByteString a -> Parser ByteString s
+                      -> Parser ByteString [a] #-}
+{-# SPECIALIZE sepBy1 :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
 {-# SPECIALIZE sepBy1 :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
-#endif
 
+-- | @sepBy1' p sep@ applies /one/ or more occurrences of @p@, separated
+-- by @sep@. Returns a list of the values returned by @p@. The value
+-- returned by @p@ is forced to WHNF.
+--
+-- > commaSep p  = p `sepBy1'` (char ',')
+sepBy1' :: (MonadPlus m) => m a -> m s -> m [a]
+sepBy1' p s = scan
+    where scan = liftM2' (:) p ((s >> scan) `mplus` return [])
+{-# SPECIALIZE sepBy1' :: Parser ByteString a -> Parser ByteString s
+                       -> Parser ByteString [a] #-}
+{-# SPECIALIZE sepBy1' :: Parser Text a -> Parser Text s -> Parser Text [a] #-}
+{-# SPECIALIZE sepBy1' :: Z.Parser a -> Z.Parser s -> Z.Parser [a] #-}
+
 -- | @manyTill p end@ applies action @p@ /zero/ or more times until
 -- action @end@ succeeds, and returns the list of values returned by
 -- @p@.  This can be used to scan comments:
 --
--- >  simpleComment   = string "<!--" *> manyTill anyChar (try (string "-->"))
+-- >  simpleComment   = string "<!--" *> manyTill anyChar (string "-->")
 --
--- Note the overlapping parsers @anyChar@ and @string \"<!--\"@, and
--- therefore the use of the 'try' combinator.
+-- (Note the overlapping parsers @anyChar@ and @string \"-->\"@.
+-- While this will work, it is not very efficient, as it will cause a
+-- lot of backtracking.)
 manyTill :: Alternative f => f a -> f b -> f [a]
 manyTill p end = scan
     where scan = (end *> pure []) <|> liftA2 (:) p scan
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE manyTill :: Parser a -> Parser b -> Parser [a] #-}
+{-# SPECIALIZE manyTill :: Parser ByteString a -> Parser ByteString b
+                        -> Parser ByteString [a] #-}
+{-# SPECIALIZE manyTill :: Parser Text a -> Parser Text b -> Parser Text [a] #-}
 {-# SPECIALIZE manyTill :: Z.Parser a -> Z.Parser b -> Z.Parser [a] #-}
-#endif
 
+-- | @manyTill' p end@ applies action @p@ /zero/ or more times until
+-- action @end@ succeeds, and returns the list of values returned by
+-- @p@.  This can be used to scan comments:
+--
+-- >  simpleComment   = string "<!--" *> manyTill' anyChar (string "-->")
+--
+-- (Note the overlapping parsers @anyChar@ and @string \"-->\"@.
+-- While this will work, it is not very efficient, as it will cause a
+-- lot of backtracking.)
+--
+-- The value returned by @p@ is forced to WHNF.
+manyTill' :: (MonadPlus m) => m a -> m b -> m [a]
+manyTill' p end = scan
+    where scan = (end >> return []) `mplus` liftM2' (:) p scan
+{-# SPECIALIZE manyTill' :: Parser ByteString a -> Parser ByteString b
+                         -> Parser ByteString [a] #-}
+{-# SPECIALIZE manyTill' :: Parser Text a -> Parser Text b -> Parser Text [a] #-}
+{-# SPECIALIZE manyTill' :: Z.Parser a -> Z.Parser b -> Z.Parser [a] #-}
+
 -- | Skip zero or more instances of an action.
 skipMany :: Alternative f => f a -> f ()
 skipMany p = scan
     where scan = (p *> scan) <|> pure ()
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE skipMany :: Parser a -> Parser () #-}
+{-# SPECIALIZE skipMany :: Parser ByteString a -> Parser ByteString () #-}
+{-# SPECIALIZE skipMany :: Parser Text a -> Parser Text () #-}
 {-# SPECIALIZE skipMany :: Z.Parser a -> Z.Parser () #-}
-#endif
 
 -- | Skip one or more instances of an action.
 skipMany1 :: Alternative f => f a -> f ()
 skipMany1 p = p *> skipMany p
-#if __GLASGOW_HASKELL__ >= 700
-{-# SPECIALIZE skipMany1 :: Parser a -> Parser () #-}
+{-# SPECIALIZE skipMany1 :: Parser ByteString a -> Parser ByteString () #-}
+{-# SPECIALIZE skipMany1 :: Parser Text a -> Parser Text () #-}
 {-# SPECIALIZE skipMany1 :: Z.Parser a -> Z.Parser () #-}
-#endif
 
 -- | Apply the given action repeatedly, returning every result.
 count :: Monad m => Int -> m a -> m [a]
@@ -134,9 +240,17 @@
 eitherP a b = (Left <$> a) <|> (Right <$> b)
 {-# INLINE eitherP #-}
 
--- | Zero or more.
-many :: (Alternative f) => f a -> f [a]
-many v = many_v
-    where many_v = some_v <|> pure []
-	  some_v = (:) <$> v <*> many_v
-{-# INLINE many #-}
+-- | If a parser has returned a 'T.Partial' result, supply it with more
+-- input.
+feed :: Monoid i => IResult i r -> i -> IResult i r
+feed (Fail t ctxs msg) d = Fail (mappend t d) ctxs msg
+feed (Partial k) d    = k d
+feed (Done t r) d     = Done (mappend t d) r
+{-# INLINE feed #-}
+
+-- | Apply a parser without consuming any input.
+lookAhead :: Parser i a -> Parser i a
+lookAhead p = Parser $ \t pos more lose succ ->
+  let succ' t' _pos' more' = succ t' pos more'
+  in runParser p t pos more lose succ'
+{-# INLINE lookAhead #-}
diff --git a/Data/Attoparsec/FastSet.hs b/Data/Attoparsec/FastSet.hs
deleted file mode 100644
--- a/Data/Attoparsec/FastSet.hs
+++ /dev/null
@@ -1,115 +0,0 @@
-{-# LANGUAGE BangPatterns, MagicHash #-}
-
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Attoparsec.FastSet
--- Copyright   :  Bryan O'Sullivan 2008
--- License     :  BSD3
--- 
--- Maintainer  :  bos@serpentine.com
--- Stability   :  experimental
--- Portability :  unknown
---
--- Fast set membership tests for 'Word8' and 8-bit 'Char' values.  The
--- set representation is unboxed for efficiency.  For small sets, we
--- test for membership using a binary search.  For larger sets, we use
--- a lookup table.
--- 
------------------------------------------------------------------------------
-module Data.Attoparsec.FastSet
-    (
-    -- * Data type
-      FastSet
-    -- * Construction
-    , fromList
-    , set
-    -- * Lookup
-    , memberChar
-    , memberWord8
-    -- * Debugging
-    , fromSet
-    -- * Handy interface
-    , charClass
-    ) where
-
-import Data.Bits ((.&.), (.|.))
-import Foreign.Storable (peekByteOff, pokeByteOff)
-import GHC.Base (Int(I#), iShiftRA#, narrow8Word#, shiftL#)
-import GHC.Word (Word8(W8#))
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as B8
-import qualified Data.ByteString.Internal as I
-import qualified Data.ByteString.Unsafe as U
-
-data FastSet = Sorted { fromSet :: !B.ByteString }
-             | Table  { fromSet :: !B.ByteString }
-    deriving (Eq, Ord)
-
-instance Show FastSet where
-    show (Sorted s) = "FastSet Sorted " ++ show (B8.unpack s)
-    show (Table _) = "FastSet Table"
-
--- | The lower bound on the size of a lookup table.  We choose this to
--- balance table density against performance.
-tableCutoff :: Int
-tableCutoff = 8
-
--- | Create a set.
-set :: B.ByteString -> FastSet
-set s | B.length s < tableCutoff = Sorted . B.sort $ s
-      | otherwise                = Table . mkTable $ s
-
-fromList :: [Word8] -> FastSet
-fromList = set . B.pack
-
-data I = I {-# UNPACK #-} !Int {-# UNPACK #-} !Word8
-
-shiftR :: Int -> Int -> Int
-shiftR (I# x#) (I# i#) = I# (x# `iShiftRA#` i#)
-
-shiftL :: Word8 -> Int -> Word8
-shiftL (W8# x#) (I# i#) = W8# (narrow8Word# (x# `shiftL#` i#))
-
-index :: Int -> I
-index i = I (i `shiftR` 3) (1 `shiftL` (i .&. 7))
-{-# INLINE index #-}
-
--- | Check the set for membership.
-memberWord8 :: Word8 -> FastSet -> Bool
-memberWord8 w (Table t)  =
-    let I byte bit = index (fromIntegral w)
-    in  U.unsafeIndex t byte .&. bit /= 0
-memberWord8 w (Sorted s) = search 0 (B.length s - 1)
-    where search lo hi
-              | hi < lo = False
-              | otherwise =
-                  let mid = (lo + hi) `div` 2
-                  in case compare w (U.unsafeIndex s mid) of
-                       GT -> search (mid + 1) hi
-                       LT -> search lo (mid - 1)
-                       _ -> True
-
--- | Check the set for membership.  Only works with 8-bit characters:
--- characters above code point 255 will give wrong answers.
-memberChar :: Char -> FastSet -> Bool
-memberChar c = memberWord8 (I.c2w c)
-{-# INLINE memberChar #-}
-
-mkTable :: B.ByteString -> B.ByteString
-mkTable s = I.unsafeCreate 32 $ \t -> do
-            _ <- I.memset t 0 32
-            U.unsafeUseAsCStringLen s $ \(p, l) ->
-              let loop n | n == l = return ()
-                         | otherwise = do
-                    c <- peekByteOff p n :: IO Word8
-                    let I byte bit = index (fromIntegral c)
-                    prev <- peekByteOff t byte :: IO Word8
-                    pokeByteOff t byte (prev .|. bit)
-                    loop (n + 1)
-              in loop 0
-
-charClass :: String -> FastSet
-charClass = set . B8.pack . go
-    where go (a:'-':b:xs) = [a..b] ++ go xs
-          go (x:xs) = x : go xs
-          go _ = ""
diff --git a/Data/Attoparsec/Internal.hs b/Data/Attoparsec/Internal.hs
--- a/Data/Attoparsec/Internal.hs
+++ b/Data/Attoparsec/Internal.hs
@@ -1,453 +1,171 @@
-{-# LANGUAGE BangPatterns, Rank2Types, OverloadedStrings, RecordWildCards #-}
+{-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables #-}
 -- |
 -- Module      :  Data.Attoparsec.Internal
--- Copyright   :  Bryan O'Sullivan 2007-2011
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
 --
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
 --
--- Simple, efficient parser combinators for 'B.ByteString' strings,
--- loosely based on the Parsec library.
+-- Simple, efficient parser combinators, loosely based on the Parsec
+-- library.
 
 module Data.Attoparsec.Internal
-    (
-    -- * Parser types
-      Parser
-    , Result(..)
-
-    -- * Running parsers
-    , parse
-    , parseOnly
-
-    -- * Combinators
-    , (<?>)
-    , try
-    , module Data.Attoparsec.Combinator
-
-    -- * Parsing individual bytes
-    , satisfy
-    , satisfyWith
-    , anyWord8
-    , skip
-    , word8
-    , notWord8
-
-    -- ** Byte classes
-    , inClass
-    , notInClass
-
-    -- * Parsing more complicated structures
-    , storable
-
-    -- * Efficient string handling
-    , skipWhile
-    , string
-    , stringTransform
-    , take
-    , scan
-    , takeWhile
-    , takeWhile1
-    , takeTill
-
-    -- ** Consume all remaining input
-    , takeByteString
-    , takeLazyByteString
-
-    -- * State observation and manipulation functions
+    ( compareResults
+    , prompt
+    , demandInput
+    , demandInput_
+    , wantInput
     , endOfInput
     , atEnd
-    , ensure
-
-    -- * Utilities
-    , endOfLine
+    , satisfyElem
+    , concatReverse
     ) where
 
-import Control.Applicative ((<|>), (<$>))
-import Control.Monad (when)
-import Data.Attoparsec.Combinator
-import Data.Attoparsec.FastSet (charClass, memberWord8)
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+import Data.Monoid (Monoid, mconcat)
+#endif
 import Data.Attoparsec.Internal.Types
-import Data.Word (Word8)
-import Foreign.ForeignPtr (withForeignPtr)
-import Foreign.Ptr (castPtr, minusPtr, plusPtr)
-import Foreign.Storable (Storable(peek, sizeOf))
-import Prelude hiding (getChar, take, takeWhile)
-import System.IO.Unsafe (unsafePerformIO)
-import qualified Data.ByteString as B8
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Internal as B
-import qualified Data.ByteString.Lazy as L
-import qualified Data.ByteString.Unsafe as B
+import Data.ByteString (ByteString)
+import Data.Text (Text)
+import Prelude hiding (succ)
 
--- | If at least @n@ bytes of input are available, return the current
--- input, otherwise fail.
-ensure :: Int -> Parser B.ByteString
-ensure !n = Parser $ \i0 a0 m0 kf ks ->
-    if B.length (unI i0) >= n
-    then ks i0 a0 m0 (unI i0)
-    else runParser (demandInput >> ensure n) i0 a0 m0 kf ks
+-- | Compare two 'IResult' values for equality.
+--
+-- If both 'IResult's are 'Partial', the result will be 'Nothing', as
+-- they are incomplete and hence their equality cannot be known.
+-- (This is why there is no 'Eq' instance for 'IResult'.)
+compareResults :: (Eq i, Eq r) => IResult i r -> IResult i r -> Maybe Bool
+compareResults (Fail t0 ctxs0 msg0) (Fail t1 ctxs1 msg1) =
+    Just (t0 == t1 && ctxs0 == ctxs1 && msg0 == msg1)
+compareResults (Done t0 r0) (Done t1 r1) =
+    Just (t0 == t1 && r0 == r1)
+compareResults (Partial _) (Partial _) = Nothing
+compareResults _ _ = Just False
 
--- | Ask for input.  If we receive any, pass it to a success
--- continuation, otherwise to a failure continuation.
-prompt :: Input -> Added -> More
-       -> (Input -> Added -> More -> Result r)
-       -> (Input -> Added -> More -> Result r)
-       -> Result r
-prompt i0 a0 _m0 kf ks = Partial $ \s ->
-    if B.null s
-    then kf i0 a0 Complete
-    else ks (I (unI i0 +++ s)) (A (unA a0 +++ s)) Incomplete
+-- | Ask for input.  If we receive any, pass the augmented input to a
+-- success continuation, otherwise to a failure continuation.
+prompt :: Chunk t
+       => State t -> Pos -> More
+       -> (State t -> Pos -> More -> IResult t r)
+       -> (State t -> Pos -> More -> IResult t r)
+       -> IResult t r
+prompt t pos _more lose succ = Partial $ \s ->
+  if nullChunk s
+  then lose t pos Complete
+  else succ (pappendChunk t s) pos Incomplete
+{-# SPECIALIZE prompt :: State ByteString -> Pos -> More
+                      -> (State ByteString -> Pos -> More
+                          -> IResult ByteString r)
+                      -> (State ByteString -> Pos -> More
+                          -> IResult ByteString r)
+                      -> IResult ByteString r #-}
+{-# SPECIALIZE prompt :: State Text -> Pos -> More
+                      -> (State Text -> Pos -> More -> IResult Text r)
+                      -> (State Text -> Pos -> More -> IResult Text r)
+                      -> IResult Text r #-}
 
 -- | Immediately demand more input via a 'Partial' continuation
 -- result.
-demandInput :: Parser ()
-demandInput = Parser $ \i0 a0 m0 kf ks ->
-    if m0 == Complete
-    then kf i0 a0 m0 ["demandInput"] "not enough bytes"
-    else let kf' i a m = kf i a m ["demandInput"] "not enough bytes"
-             ks' i a m = ks i a m ()
-         in prompt i0 a0 m0 kf' ks'
+demandInput :: Chunk t => Parser t ()
+demandInput = Parser $ \t pos more lose succ ->
+  case more of
+    Complete -> lose t pos more [] "not enough input"
+    _ -> let lose' _ pos' more' = lose t pos' more' [] "not enough input"
+             succ' t' pos' more' = succ t' pos' more' ()
+         in prompt t pos more lose' succ'
+{-# SPECIALIZE demandInput :: Parser ByteString () #-}
+{-# SPECIALIZE demandInput :: Parser Text () #-}
 
+-- | Immediately demand more input via a 'Partial' continuation
+-- result.  Return the new input.
+demandInput_ :: Chunk t => Parser t t
+demandInput_ = Parser $ \t pos more lose succ ->
+  case more of
+    Complete -> lose t pos more [] "not enough input"
+    _ -> Partial $ \s ->
+         if nullChunk s
+         then lose t pos Complete [] "not enough input"
+         else succ (pappendChunk t s) pos more s
+{-# SPECIALIZE demandInput_ :: Parser ByteString ByteString #-}
+{-# SPECIALIZE demandInput_ :: Parser Text Text #-}
+
 -- | This parser always succeeds.  It returns 'True' if any input is
 -- available either immediately or on demand, and 'False' if the end
 -- of all input has been reached.
-wantInput :: Parser Bool
-wantInput = Parser $ \i0 a0 m0 _kf ks ->
+wantInput :: forall t . Chunk t => Parser t Bool
+wantInput = Parser $ \t pos more _lose succ ->
   case () of
-    _ | not (B.null (unI i0)) -> ks i0 a0 m0 True
-      | m0 == Complete  -> ks i0 a0 m0 False
-      | otherwise       -> let kf' i a m = ks i a m False
-                               ks' i a m = ks i a m True
-                           in prompt i0 a0 m0 kf' ks'
-
-get :: Parser B.ByteString
-get  = Parser $ \i0 a0 m0 _kf ks -> ks i0 a0 m0 (unI i0)
-
-put :: B.ByteString -> Parser ()
-put s = Parser $ \_i0 a0 m0 _kf ks -> ks (I s) a0 m0 ()
-
--- | Attempt a parse, and if it fails, rewind the input so that no
--- input appears to have been consumed.
---
--- This combinator is useful in cases where a parser might consume
--- some input before failing, i.e. the parser needs arbitrary
--- lookahead.  The downside to using this combinator is that it can
--- retain input for longer than is desirable.
-try :: Parser a -> Parser a
-try p = Parser $ \i0 a0 m0 kf ks ->
-        noAdds i0 a0 m0 $ \i1 a1 m1 ->
-            let kf' i2 a2 m2 = addS i0 a0 m0 i2 a2 m2 kf
-            in runParser p i1 a1 m1 kf' ks
-
--- | The parser @satisfy p@ succeeds for any byte for which the
--- predicate @p@ returns 'True'. Returns the byte that is actually
--- parsed.
---
--- >digit = satisfy isDigit
--- >    where isDigit w = w >= 48 && w <= 57
-satisfy :: (Word8 -> Bool) -> Parser Word8
-satisfy p = do
-  s <- ensure 1
-  let w = B.unsafeHead s
-  if p w
-    then put (B.unsafeTail s) >> return w
-    else fail "satisfy"
-
--- | The parser @skip p@ succeeds for any byte for which the predicate
--- @p@ returns 'True'.
---
--- >skipDigit = skip isDigit
--- >    where isDigit w = w >= 48 && w <= 57
-skip :: (Word8 -> Bool) -> Parser ()
-skip p = do
-  s <- ensure 1
-  if p (B.unsafeHead s)
-    then put (B.unsafeTail s)
-    else fail "skip"
-
--- | The parser @satisfyWith f p@ transforms a byte, and succeeds if
--- the predicate @p@ returns 'True' on the transformed value. The
--- parser returns the transformed byte that was parsed.
-satisfyWith :: (Word8 -> a) -> (a -> Bool) -> Parser a
-satisfyWith f p = do
-  s <- ensure 1
-  let c = f (B.unsafeHead s)
-  if p c
-    then put (B.unsafeTail s) >> return c
-    else fail "satisfyWith"
-
-storable :: Storable a => Parser a
-storable = hack undefined
- where
-  hack :: Storable b => b -> Parser b
-  hack dummy = do
-    (fp,o,_) <- B.toForeignPtr `fmap` take (sizeOf dummy)
-    return . B.inlinePerformIO . withForeignPtr fp $ \p ->
-        peek (castPtr $ p `plusPtr` o)
-
--- | Consume @n@ bytes of input, but succeed only if the predicate
--- returns 'True'.
-takeWith :: Int -> (B.ByteString -> Bool) -> Parser B.ByteString
-takeWith n p = do
-  s <- ensure n
-  let h = B.unsafeTake n s
-      t = B.unsafeDrop n s
-  if p h
-    then put t >> return h
-    else fail "takeWith"
-
--- | Consume exactly @n@ bytes of input.
-take :: Int -> Parser B.ByteString
-take n = takeWith n (const True)
-{-# INLINE take #-}
-
--- | @string s@ parses a sequence of bytes that identically match
--- @s@. Returns the parsed string (i.e. @s@).  This parser consumes no
--- input if it fails (even if a partial match).
---
--- /Note/: The behaviour of this parser is different to that of the
--- similarly-named parser in Parsec, as this one is all-or-nothing.
--- To illustrate the difference, the following parser will fail under
--- Parsec given an input of @"for"@:
---
--- >string "foo" <|> string "for"
---
--- The reason for its failure is that that the first branch is a
--- partial match, and will consume the letters @\'f\'@ and @\'o\'@
--- before failing.  In Attoparsec, the above parser will /succeed/ on
--- that input, because the failed first branch will consume nothing.
-string :: B.ByteString -> Parser B.ByteString
-string s = takeWith (B.length s) (==s)
-{-# INLINE string #-}
-
-stringTransform :: (B.ByteString -> B.ByteString) -> B.ByteString
-                -> Parser B.ByteString
-stringTransform f s = takeWith (B.length s) ((==f s) . f)
-{-# INLINE stringTransform #-}
-
--- | Skip past input for as long as the predicate returns 'True'.
-skipWhile :: (Word8 -> Bool) -> Parser ()
-skipWhile p = go
- where
-  go = do
-    t <- B8.dropWhile p <$> get
-    put t
-    when (B.null t) $ do
-      input <- wantInput
-      when input go
-{-# INLINE skipWhile #-}
-
--- | Consume input as long as the predicate returns 'False'
--- (i.e. until it returns 'True'), and return the consumed input.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'True' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-takeTill :: (Word8 -> Bool) -> Parser B.ByteString
-takeTill p = takeWhile (not . p)
-{-# INLINE takeTill #-}
-
--- | Consume input as long as the predicate returns 'True', and return
--- the consumed input.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'False' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-takeWhile :: (Word8 -> Bool) -> Parser B.ByteString
-takeWhile p = (B.concat . reverse) `fmap` go []
- where
-  go acc = do
-    (h,t) <- B8.span p <$> get
-    put t
-    if B.null t
-      then do
-        input <- wantInput
-        if input
-          then go (h:acc)
-          else return (h:acc)
-      else return (h:acc)
-
-takeRest :: Parser [B.ByteString]
-takeRest = go []
- where
-  go acc = do
-    input <- wantInput
-    if input
-      then do
-        s <- get
-        put B.empty
-        go (s:acc)
-      else return (reverse acc)
-
--- | Consume all remaining input and return it as a single string.
-takeByteString :: Parser B.ByteString
-takeByteString = B.concat `fmap` takeRest
-
--- | Consume all remaining input and return it as a single string.
-takeLazyByteString :: Parser L.ByteString
-takeLazyByteString = L.fromChunks `fmap` takeRest
-
-data T s = T {-# UNPACK #-} !Int s
-
--- | A stateful scanner.  The predicate consumes and transforms a
--- state argument, and each transformed state is passed to successive
--- invocations of the predicate on each byte of the input until one
--- returns 'Nothing' or the input ends.
---
--- This parser does not fail.  It will return an empty string if the
--- predicate returns 'Nothing' on the first byte of input.
---
--- /Note/: Because this parser does not fail, do not use it with
--- combinators such as 'many', because such parsers loop until a
--- failure occurs.  Careless use will thus result in an infinite loop.
-scan :: s -> (s -> Word8 -> Maybe s) -> Parser B.ByteString
-scan s0 p = do
-  chunks <- go [] s0
-  case chunks of
-    [x] -> return x
-    xs  -> return . B.concat . reverse $ xs
- where
-  go acc s1 = do
-    let scanner (B.PS fp off len) =
-          withForeignPtr fp $ \ptr0 -> do
-            let start = ptr0 `plusPtr` off
-                end   = start `plusPtr` len
-                inner ptr !s
-                  | ptr < end = do
-                    w <- peek ptr
-                    case p s w of
-                      Just s' -> inner (ptr `plusPtr` 1) s'
-                      _       -> done (ptr `minusPtr` start) s
-                  | otherwise = done (ptr `minusPtr` start) s
-                done !i !s = return (T i s)
-            inner start s1
-    bs <- get
-    let T i s' = unsafePerformIO $ scanner bs
-        h = B.unsafeTake i bs
-        t = B.unsafeDrop i bs
-    put t
-    if B.null t
-      then do
-        input <- wantInput
-        if input
-          then go (h:acc) s'
-          else return (h:acc)
-      else return (h:acc)
-{-# INLINE scan #-}
-
--- | Consume input as long as the predicate returns 'True', and return
--- the consumed input.
---
--- This parser requires the predicate to succeed on at least one byte
--- of input: it will fail if the predicate never returns 'True' or if
--- there is no input left.
-takeWhile1 :: (Word8 -> Bool) -> Parser B.ByteString
-takeWhile1 p = do
-  (`when` demandInput) =<< B.null <$> get
-  (h,t) <- B8.span p <$> get
-  when (B.null h) $ fail "takeWhile1"
-  put t
-  if B.null t
-    then (h+++) `fmap` takeWhile p
-    else return h
-
--- | Match any byte in a set.
---
--- >vowel = inClass "aeiou"
---
--- Range notation is supported.
---
--- >halfAlphabet = inClass "a-nA-N"
---
--- To add a literal @\'-\'@ to a set, place it at the beginning or end
--- of the string.
-inClass :: String -> Word8 -> Bool
-inClass s = (`memberWord8` mySet)
-    where mySet = charClass s
-{-# INLINE inClass #-}
-
--- | Match any byte not in a set.
-notInClass :: String -> Word8 -> Bool
-notInClass s = not . inClass s
-{-# INLINE notInClass #-}
-
--- | Match any byte.
-anyWord8 :: Parser Word8
-anyWord8 = satisfy $ const True
-{-# INLINE anyWord8 #-}
-
--- | Match a specific byte.
-word8 :: Word8 -> Parser Word8
-word8 c = satisfy (== c) <?> show c
-{-# INLINE word8 #-}
-
--- | Match any byte except the given one.
-notWord8 :: Word8 -> Parser Word8
-notWord8 c = satisfy (/= c) <?> "not " ++ show c
-{-# INLINE notWord8 #-}
+    _ | pos < atBufferEnd (undefined :: t) t -> succ t pos more True
+      | more == Complete -> succ t pos more False
+      | otherwise       -> let lose' t' pos' more' = succ t' pos' more' False
+                               succ' t' pos' more' = succ t' pos' more' True
+                           in prompt t pos more lose' succ'
+{-# INLINE wantInput #-}
 
 -- | Match only if all input has been consumed.
-endOfInput :: Parser ()
-endOfInput = Parser $ \i0 a0 m0 kf ks ->
-             if B.null (unI i0)
-             then if m0 == Complete
-                  then ks i0 a0 m0 ()
-                  else let kf' i1 a1 m1 _ _ = addS i0 a0 m0 i1 a1 m1 $
-                                              \ i2 a2 m2 -> ks i2 a2 m2 ()
-                           ks' i1 a1 m1 _   = addS i0 a0 m0 i1 a1 m1 $
-                                              \ i2 a2 m2 -> kf i2 a2 m2 []
-                                                            "endOfInput"
-                       in  runParser demandInput i0 a0 m0 kf' ks'
-             else kf i0 a0 m0 [] "endOfInput"
+endOfInput :: forall t . Chunk t => Parser t ()
+endOfInput = Parser $ \t pos more lose succ ->
+  case () of
+    _| pos < atBufferEnd (undefined :: t) t -> lose t pos more [] "endOfInput"
+     | more == Complete -> succ t pos more ()
+     | otherwise ->
+       let lose' t' pos' more' _ctx _msg = succ t' pos' more' ()
+           succ' t' pos' more' _a = lose t' pos' more' [] "endOfInput"
+       in  runParser demandInput t pos more lose' succ'
+{-# SPECIALIZE endOfInput :: Parser ByteString () #-}
+{-# SPECIALIZE endOfInput :: Parser Text () #-}
 
 -- | Return an indication of whether the end of input has been
 -- reached.
-atEnd :: Parser Bool
+atEnd :: Chunk t => Parser t Bool
 atEnd = not <$> wantInput
 {-# INLINE atEnd #-}
 
--- | Match either a single newline character @\'\\n\'@, or a carriage
--- return followed by a newline character @\"\\r\\n\"@.
-endOfLine :: Parser ()
-endOfLine = (word8 10 >> return ()) <|> (string "\r\n" >> return ())
-
---- | Name the parser, in case failure occurs.
-(<?>) :: Parser a
-      -> String                 -- ^ the name to use if parsing fails
-      -> Parser a
-p <?> msg0 = Parser $ \i0 a0 m0 kf ks ->
-             let kf' i a m strs msg = kf i a m (msg0:strs) msg
-             in runParser p i0 a0 m0 kf' ks
-{-# INLINE (<?>) #-}
-infix 0 <?>
-
--- | Terminal failure continuation.
-failK :: Failure a
-failK i0 _a0 _m0 stack msg = Fail (unI i0) stack msg
-{-# INLINE failK #-}
-
--- | Terminal success continuation.
-successK :: Success a a
-successK i0 _a0 _m0 a = Done (unI i0) a
-{-# INLINE successK #-}
+satisfySuspended :: forall t r . Chunk t
+                 => (ChunkElem t -> Bool)
+                 -> State t -> Pos -> More
+                 -> Failure t (State t) r
+                 -> Success t (State t) (ChunkElem t) r
+                 -> IResult t r
+satisfySuspended p t pos more lose succ =
+    runParser (demandInput >> go) t pos more lose succ
+  where go = Parser $ \t' pos' more' lose' succ' ->
+          case bufferElemAt (undefined :: t) pos' t' of
+            Just (e, l) | p e -> succ' t' (pos' + Pos l) more' e
+                        | otherwise -> lose' t' pos' more' [] "satisfyElem"
+            Nothing -> runParser (demandInput >> go) t' pos' more' lose' succ'
+{-# SPECIALIZE satisfySuspended :: (ChunkElem ByteString -> Bool)
+                                -> State ByteString -> Pos -> More
+                                -> Failure ByteString (State ByteString) r
+                                -> Success ByteString (State ByteString)
+                                           (ChunkElem ByteString) r
+                                -> IResult ByteString r #-}
+{-# SPECIALIZE satisfySuspended :: (ChunkElem Text -> Bool)
+                                -> State Text -> Pos -> More
+                                -> Failure Text (State Text) r
+                                -> Success Text (State Text)
+                                           (ChunkElem Text) r
+                                -> IResult Text r #-}
 
--- | Run a parser.
-parse :: Parser a -> B.ByteString -> Result a
-parse m s = runParser m (I s) (A B.empty) Incomplete failK successK
-{-# INLINE parse #-}
+-- | The parser @satisfyElem p@ succeeds for any chunk element for which the
+-- predicate @p@ returns 'True'. Returns the element that is
+-- actually parsed.
+satisfyElem :: forall t . Chunk t
+            => (ChunkElem t -> Bool) -> Parser t (ChunkElem t)
+satisfyElem p = Parser $ \t pos more lose succ ->
+    case bufferElemAt (undefined :: t) pos t of
+      Just (e, l) | p e -> succ t (pos + Pos l) more e
+                  | otherwise -> lose t pos more [] "satisfyElem"
+      Nothing -> satisfySuspended p t pos more lose succ
+{-# INLINE satisfyElem #-}
 
--- | Run a parser that cannot be resupplied via a 'Partial' result.
-parseOnly :: Parser a -> B.ByteString -> Either String a
-parseOnly m s = case runParser m (I s) (A B.empty) Complete failK successK of
-                  Fail _ _ err -> Left err
-                  Done _ a     -> Right a
-                  _            -> error "parseOnly: impossible error!"
-{-# INLINE parseOnly #-}
+-- | Concatenate a monoid after reversing its elements.  Used to
+-- glue together a series of textual chunks that have been accumulated
+-- \"backwards\".
+concatReverse :: Monoid m => [m] -> m
+concatReverse [x] = x
+concatReverse xs  = mconcat (reverse xs)
+{-# INLINE concatReverse #-}
diff --git a/Data/Attoparsec/Internal/Types.hs b/Data/Attoparsec/Internal/Types.hs
--- a/Data/Attoparsec/Internal/Types.hs
+++ b/Data/Attoparsec/Internal/Types.hs
@@ -1,185 +1,266 @@
-{-# LANGUAGE BangPatterns, Rank2Types, OverloadedStrings, RecordWildCards #-}
+{-# LANGUAGE CPP, BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
+    Rank2Types, RecordWildCards, TypeFamilies #-}
 -- |
 -- Module      :  Data.Attoparsec.Internal.Types
--- Copyright   :  Bryan O'Sullivan 2007-2011
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
 --
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
 --
--- Simple, efficient parser combinators for 'B.ByteString' strings,
--- loosely based on the Parsec library.
+-- Simple, efficient parser combinators, loosely based on the Parsec
+-- library.
 
 module Data.Attoparsec.Internal.Types
     (
       Parser(..)
+    , State
     , Failure
     , Success
-    , Result(..)
-    , Input(..)
-    , Added(..)
+    , Pos(..)
+    , IResult(..)
     , More(..)
-    , addS
-    , noAdds
-    , (+++)
+    , (<>)
+    , Chunk(..)
     ) where
 
-import Control.Applicative (Alternative(..), Applicative(..))
+import Control.Applicative as App (Applicative(..), (<$>))
+import Control.Applicative (Alternative(..))
 import Control.DeepSeq (NFData(rnf))
 import Control.Monad (MonadPlus(..))
-import Data.Monoid (Monoid(..))
-import Prelude hiding (getChar, take, takeWhile)
-import qualified Data.ByteString.Char8 as B
+import qualified Control.Monad.Fail as Fail (MonadFail(..))
+import Data.Monoid as Mon (Monoid(..))
+import Data.Semigroup  (Semigroup(..))
+import Data.Word (Word8)
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as BS
+import Data.ByteString.Internal (w2c)
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Data.Text.Unsafe (Iter(..))
+import Prelude hiding (succ)
+import qualified Data.Attoparsec.ByteString.Buffer as B
+import qualified Data.Attoparsec.Text.Buffer as T
 
--- | The result of a parse.
-data Result r = Fail B.ByteString [String] String
-              -- ^ The parse failed.  The 'B.ByteString' is the input
-              -- that had not yet been consumed when the failure
-              -- occurred.  The @[@'String'@]@ is a list of contexts
-              -- in which the error occurred.  The 'String' is the
-              -- message describing the error, if any.
-              | Partial (B.ByteString -> Result r)
-              -- ^ Supply this continuation with more input so that
-              -- the parser can resume.  To indicate that no more
-              -- input is available, use an 'B.empty' string.
-              | Done B.ByteString r
-              -- ^ The parse succeeded.  The 'B.ByteString' is the
-              -- input that had not yet been consumed (if any) when
-              -- the parse succeeded.
+newtype Pos = Pos { fromPos :: Int }
+            deriving (Eq, Ord, Show, Num)
 
-instance Show r => Show (Result r) where
-    show (Fail bs stk msg) =
-        "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg
-    show (Partial _)       = "Partial _"
-    show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r
+-- | The result of a parse.  This is parameterised over the type @i@
+-- of string that was processed.
+--
+-- This type is an instance of 'Functor', where 'fmap' transforms the
+-- value in a 'Done' result.
+data IResult i r =
+    Fail i [String] String
+    -- ^ The parse failed.  The @i@ parameter is the input that had
+    -- not yet been consumed when the failure occurred.  The
+    -- @[@'String'@]@ is a list of contexts in which the error
+    -- occurred.  The 'String' is the message describing the error, if
+    -- any.
+  | Partial (i -> IResult i r)
+    -- ^ Supply this continuation with more input so that the parser
+    -- can resume.  To indicate that no more input is available, pass
+    -- an empty string to the continuation.
+    --
+    -- __Note__: if you get a 'Partial' result, do not call its
+    -- continuation more than once.
+  | Done i r
+    -- ^ The parse succeeded.  The @i@ parameter is the input that had
+    -- not yet been consumed (if any) when the parse succeeded.
 
-instance (NFData r) => NFData (Result r) where
-    rnf (Fail _ _ _) = ()
+instance (Show i, Show r) => Show (IResult i r) where
+    showsPrec d ir = showParen (d > 10) $
+      case ir of
+        (Fail t stk msg) -> showString "Fail" . f t . f stk . f msg
+        (Partial _)      -> showString "Partial _"
+        (Done t r)       -> showString "Done" . f t . f r
+      where f :: Show a => a -> ShowS
+            f x = showChar ' ' . showsPrec 11 x
+
+instance (NFData i, NFData r) => NFData (IResult i r) where
+    rnf (Fail t stk msg) = rnf t `seq` rnf stk `seq` rnf msg
     rnf (Partial _)  = ()
-    rnf (Done _ r)   = rnf r
+    rnf (Done t r)   = rnf t `seq` rnf r
     {-# INLINE rnf #-}
 
-fmapR :: (a -> b) -> Result a -> Result b
-fmapR _ (Fail st stk msg) = Fail st stk msg
-fmapR f (Partial k)       = Partial (fmapR f . k)
-fmapR f (Done bs r)       = Done bs (f r)
-
-instance Functor Result where
-    fmap = fmapR
-    {-# INLINE fmap #-}
-
-newtype Input = I {unI :: B.ByteString}
-newtype Added = A {unA :: B.ByteString}
+instance Functor (IResult i) where
+    fmap _ (Fail t stk msg) = Fail t stk msg
+    fmap f (Partial k)      = Partial (fmap f . k)
+    fmap f (Done t r)   = Done t (f r)
 
--- | The 'Parser' type is a monad.
-newtype Parser a = Parser {
-      runParser :: forall r. Input -> Added -> More
-                -> Failure   r
-                -> Success a r
-                -> Result r
+-- | The core parser type.  This is parameterised over the type @i@
+-- of string being processed.
+--
+-- This type is an instance of the following classes:
+--
+-- * 'Monad', where 'fail' throws an exception (i.e. fails) with an
+--   error message.
+--
+-- * 'Functor' and 'Applicative', which follow the usual definitions.
+--
+-- * 'MonadPlus', where 'mzero' fails (with no error message) and
+--   'mplus' executes the right-hand parser if the left-hand one
+--   fails.  When the parser on the right executes, the input is reset
+--   to the same state as the parser on the left started with. (In
+--   other words, attoparsec is a backtracking parser that supports
+--   arbitrary lookahead.)
+--
+-- * 'Alternative', which follows 'MonadPlus'.
+newtype Parser i a = Parser {
+      runParser :: forall r.
+                   State i -> Pos -> More
+                -> Failure i (State i)   r
+                -> Success i (State i) a r
+                -> IResult i r
     }
 
-type Failure   r = Input -> Added -> More -> [String] -> String -> Result r
-type Success a r = Input -> Added -> More -> a -> Result r
+type family State i
+type instance State ByteString = B.Buffer
+type instance State Text = T.Buffer
 
+type Failure i t   r = t -> Pos -> More -> [String] -> String
+                       -> IResult i r
+type Success i t a r = t -> Pos -> More -> a -> IResult i r
+
 -- | Have we read all available input?
 data More = Complete | Incomplete
             deriving (Eq, Show)
 
-addS :: Input -> Added -> More
-     -> Input -> Added -> More
-     -> (Input -> Added -> More -> r) -> r
-addS i0 a0 m0 _i1 a1 m1 f =
-    let !i = I (unI i0 +++ unA a1)
-        a  = A (unA a0 +++ unA a1)
-        !m = m0 <> m1
-    in f i a m
-  where
-    Complete <> _ = Complete
-    _ <> Complete = Complete
-    _ <> _        = Incomplete
-{-# INLINE addS #-}
+instance Semigroup More where
+    c@Complete <> _ = c
+    _          <> m = m
 
-bindP :: Parser a -> (a -> Parser b) -> Parser b
-bindP m g =
-    Parser $ \i0 a0 m0 kf ks -> runParser m i0 a0 m0 kf $
-                                \i1 a1 m1 a -> runParser (g a) i1 a1 m1 kf ks
-{-# INLINE bindP #-}
+instance Mon.Monoid More where
+    mappend = (<>)
+    mempty  = Incomplete
 
-returnP :: a -> Parser a
-returnP a = Parser (\i0 a0 m0 _kf ks -> ks i0 a0 m0 a)
-{-# INLINE returnP #-}
+instance Monad (Parser i) where
+#if !(MIN_VERSION_base(4,13,0))
+    fail = Fail.fail
+    {-# INLINE fail #-}
+#endif
 
-instance Monad Parser where
-    return = returnP
-    (>>=)  = bindP
-    fail   = failDesc
+    return = App.pure
+    {-# INLINE return #-}
 
-noAdds :: Input -> Added -> More
-       -> (Input -> Added -> More -> r) -> r
-noAdds i0 _a0 m0 f = f i0 (A B.empty) m0
-{-# INLINE noAdds #-}
+    m >>= k = Parser $ \t !pos more lose succ ->
+        let succ' t' !pos' more' a = runParser (k a) t' pos' more' lose succ
+        in runParser m t pos more lose succ'
+    {-# INLINE (>>=) #-}
 
-plus :: Parser a -> Parser a -> Parser a
-plus a b = Parser $ \i0 a0 m0 kf ks ->
-           let kf' i1 a1 m1 _ _ = addS i0 a0 m0 i1 a1 m1 $
-                                  \ i2 a2 m2 -> runParser b i2 a2 m2 kf ks
-           in  noAdds i0 a0 m0 $ \i2 a2 m2 -> runParser a i2 a2 m2 kf' ks
-{-# INLINE plus #-}
+    (>>) = (*>)
+    {-# INLINE (>>) #-}
 
-instance MonadPlus Parser where
-    mzero = failDesc "mzero"
+
+instance Fail.MonadFail (Parser i) where
+    fail err = Parser $ \t pos more lose _succ -> lose t pos more [] msg
+      where msg = "Failed reading: " ++ err
+    {-# INLINE fail #-}
+
+plus :: Parser i a -> Parser i a -> Parser i a
+plus f g = Parser $ \t pos more lose succ ->
+  let lose' t' _pos' more' _ctx _msg = runParser g t' pos more' lose succ
+  in runParser f t pos more lose' succ
+
+instance MonadPlus (Parser i) where
+    mzero = fail "mzero"
     {-# INLINE mzero #-}
     mplus = plus
 
-fmapP :: (a -> b) -> Parser a -> Parser b
-fmapP p m = Parser $ \i0 a0 m0 f k ->
-            runParser m i0 a0 m0 f $ \i1 a1 s1 a -> k i1 a1 s1 (p a)
-{-# INLINE fmapP #-}
-
-instance Functor Parser where
-    fmap = fmapP
+instance Functor (Parser i) where
+    fmap f p = Parser $ \t pos more lose succ ->
+      let succ' t' pos' more' a = succ t' pos' more' (f a)
+      in runParser p t pos more lose succ'
     {-# INLINE fmap #-}
 
-apP :: Parser (a -> b) -> Parser a -> Parser b
+apP :: Parser i (a -> b) -> Parser i a -> Parser i b
 apP d e = do
   b <- d
   a <- e
   return (b a)
 {-# INLINE apP #-}
 
-instance Applicative Parser where
-    pure   = returnP
+instance Applicative (Parser i) where
+    pure v = Parser $ \t !pos more _lose succ -> succ t pos more v
     {-# INLINE pure #-}
     (<*>)  = apP
     {-# INLINE (<*>) #-}
-
-    -- These definitions are equal to the defaults, but this
-    -- way the optimizer doesn't have to work so hard to figure
-    -- that out.
-    (*>)   = (>>)
+    m *> k = m >>= \_ -> k
     {-# INLINE (*>) #-}
-    x <* y = x >>= \a -> y >> return a
+    x <* y = x >>= \a -> y >> pure a
     {-# INLINE (<*) #-}
 
-instance Monoid (Parser a) where
-    mempty  = failDesc "mempty"
+instance Semigroup (Parser i a) where
+    (<>) = plus
+    {-# INLINE (<>) #-}
+
+instance Monoid (Parser i a) where
+    mempty  = fail "mempty"
     {-# INLINE mempty #-}
-    mappend = plus
+    mappend = (<>)
     {-# INLINE mappend #-}
 
-instance Alternative Parser where
-    empty = failDesc "empty"
+instance Alternative (Parser i) where
+    empty = fail "empty"
     {-# INLINE empty #-}
+
     (<|>) = plus
     {-# INLINE (<|>) #-}
 
-failDesc :: String -> Parser a
-failDesc err = Parser (\i0 a0 m0 kf _ks -> kf i0 a0 m0 [] msg)
-    where msg = "Failed reading: " ++ err
-{-# INLINE failDesc #-}
+    many v = many_v
+      where
+        many_v = some_v <|> pure []
+        some_v = (:) <$> v <*> many_v
+    {-# INLINE many #-}
 
-(+++) :: B.ByteString -> B.ByteString -> B.ByteString
-(+++) = B.append
-{-# INLINE (+++) #-}
+    some v = some_v
+      where
+        many_v = some_v <|> pure []
+        some_v = (:) <$> v <*> many_v
+    {-# INLINE some #-}
+
+-- | A common interface for input chunks.
+class Monoid c => Chunk c where
+  type ChunkElem c
+  -- | Test if the chunk is empty.
+  nullChunk :: c -> Bool
+  -- | Append chunk to a buffer.
+  pappendChunk :: State c -> c -> State c
+  -- | Position at the end of a buffer. The first argument is ignored.
+  atBufferEnd :: c -> State c -> Pos
+  -- | Return the buffer element at the given position along with its length.
+  bufferElemAt :: c -> Pos -> State c -> Maybe (ChunkElem c, Int)
+  -- | Map an element to the corresponding character.
+  --   The first argument is ignored.
+  chunkElemToChar :: c -> ChunkElem c -> Char
+
+instance Chunk ByteString where
+  type ChunkElem ByteString = Word8
+  nullChunk = BS.null
+  {-# INLINE nullChunk #-}
+  pappendChunk = B.pappend
+  {-# INLINE pappendChunk #-}
+  atBufferEnd _ = Pos . B.length
+  {-# INLINE atBufferEnd #-}
+  bufferElemAt _ (Pos i) buf
+    | i < B.length buf = Just (B.unsafeIndex buf i, 1)
+    | otherwise = Nothing
+  {-# INLINE bufferElemAt #-}
+  chunkElemToChar _ = w2c
+  {-# INLINE chunkElemToChar #-}
+
+instance Chunk Text where
+  type ChunkElem Text = Char
+  nullChunk = Text.null
+  {-# INLINE nullChunk #-}
+  pappendChunk = T.pappend
+  {-# INLINE pappendChunk #-}
+  atBufferEnd _ = Pos . T.length
+  {-# INLINE atBufferEnd #-}
+  bufferElemAt _ (Pos i) buf
+    | i < T.length buf = let Iter c l = T.iter buf i in Just (c, l)
+    | otherwise = Nothing
+  {-# INLINE bufferElemAt #-}
+  chunkElemToChar _ = id
+  {-# INLINE chunkElemToChar #-}
diff --git a/Data/Attoparsec/Lazy.hs b/Data/Attoparsec/Lazy.hs
--- a/Data/Attoparsec/Lazy.hs
+++ b/Data/Attoparsec/Lazy.hs
@@ -1,8 +1,8 @@
 -- |
 -- Module      :  Data.Attoparsec.Lazy
--- Copyright   :  Bryan O'Sullivan 2010
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
--- 
+--
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
@@ -23,67 +23,7 @@
 
 module Data.Attoparsec.Lazy
     (
-      Result(..)
-    , module Data.Attoparsec
-    -- * Running parsers
-    , parse
-    , parseTest
-    -- ** Result conversion
-    , maybeResult
-    , eitherResult
+      module Data.Attoparsec.ByteString.Lazy
     ) where
 
-import Data.ByteString.Lazy.Internal (ByteString(..), chunk)
-import qualified Data.ByteString as B
-import qualified Data.Attoparsec as A
-import Data.Attoparsec hiding (Result(..), eitherResult, maybeResult,
-                               parse, parseWith, parseTest)
-
--- | The result of a parse.
-data Result r = Fail ByteString [String] String
-              -- ^ The parse failed.  The 'ByteString' is the input
-              -- that had not yet been consumed when the failure
-              -- occurred.  The @[@'String'@]@ is a list of contexts
-              -- in which the error occurred.  The 'String' is the
-              -- message describing the error, if any.
-              | Done ByteString r
-              -- ^ The parse succeeded.  The 'ByteString' is the
-              -- input that had not yet been consumed (if any) when
-              -- the parse succeeded.
-
-instance Show r => Show (Result r) where
-    show (Fail bs stk msg) =
-        "Fail " ++ show bs ++ " " ++ show stk ++ " " ++ show msg
-    show (Done bs r)       = "Done " ++ show bs ++ " " ++ show r
-
-fmapR :: (a -> b) -> Result a -> Result b
-fmapR _ (Fail st stk msg) = Fail st stk msg
-fmapR f (Done bs r)       = Done bs (f r)
-
-instance Functor Result where
-    fmap = fmapR
-
--- | Run a parser and return its result.
-parse :: A.Parser a -> ByteString -> Result a
-parse p s = case s of
-              Chunk x xs -> go (A.parse p x) xs
-              empty      -> go (A.parse p B.empty) empty
-  where
-    go (A.Fail x stk msg) ys      = Fail (chunk x ys) stk msg
-    go (A.Done x r) ys            = Done (chunk x ys) r
-    go (A.Partial k) (Chunk y ys) = go (k y) ys
-    go (A.Partial k) empty        = go (k B.empty) empty
-
--- | Run a parser and print its result to standard output.
-parseTest :: (Show a) => A.Parser a -> ByteString -> IO ()
-parseTest p s = print (parse p s)
-
--- | Convert a 'Result' value to a 'Maybe' value.
-maybeResult :: Result r -> Maybe r
-maybeResult (Done _ r) = Just r
-maybeResult _          = Nothing
-
--- | Convert a 'Result' value to an 'Either' value.
-eitherResult :: Result r -> Either String r
-eitherResult (Done _ r)     = Right r
-eitherResult (Fail _ _ msg) = Left msg
+import Data.Attoparsec.ByteString.Lazy
diff --git a/Data/Attoparsec/Number.hs b/Data/Attoparsec/Number.hs
--- a/Data/Attoparsec/Number.hs
+++ b/Data/Attoparsec/Number.hs
@@ -1,16 +1,22 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 -- |
 -- Module      :  Data.Attoparsec.Number
--- Copyright   :  Bryan O'Sullivan 2011
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
 --
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
 --
+-- This module is deprecated, and both the module and 'Number' type
+-- will be removed in the next major release.  Use the
+-- <http://hackage.haskell.org/package/scientific scientific> package
+-- and the 'Data.Scientific.Scientific' type instead.
+--
 -- A simple number type, useful for parsing both exact and inexact
 -- quantities without losing much precision.
 module Data.Attoparsec.Number
+    {-# DEPRECATED "This module will be removed in the next major release." #-}
     (
       Number(..)
     ) where
@@ -22,9 +28,13 @@
 
 -- | A numeric type that can represent integers accurately, and
 -- floating point numbers to the precision of a 'Double'.
+--
+-- /Note/: this type is deprecated, and will be removed in the next
+-- major release.  Use the 'Data.Scientific.Scientific' type instead.
 data Number = I !Integer
             | D {-# UNPACK #-} !Double
               deriving (Typeable, Data)
+{-# DEPRECATED Number "Use Scientific instead." #-}
 
 instance Show Number where
     show (I a) = show a
@@ -54,8 +64,17 @@
     (<) = binop (<) (<)
     {-# INLINE (<) #-}
 
+    (<=) = binop (<=) (<=)
+    {-# INLINE (<=) #-}
+
     (>) = binop (>) (>)
     {-# INLINE (>) #-}
+
+    (>=) = binop (>=) (>=)
+    {-# INLINE (>=) #-}
+
+    compare = binop compare compare
+    {-# INLINE compare #-}
 
 instance Num Number where
     (+) = binop (((I$!).) . (+)) (((D$!).) . (+))
diff --git a/Data/Attoparsec/Text.hs b/Data/Attoparsec/Text.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/Text.hs
@@ -0,0 +1,502 @@
+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, TypeSynonymInstances #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Imports internal modules
+#endif
+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+
+-- |
+-- Module      :  Data.Attoparsec.Text
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient combinator parsing for 'Text' strings,
+-- loosely based on the Parsec library.
+
+module Data.Attoparsec.Text
+    (
+    -- * Differences from Parsec
+    -- $parsec
+
+    -- * Incremental input
+    -- $incremental
+
+    -- * Performance considerations
+    -- $performance
+
+    -- * Parser types
+      Parser
+    , Result
+    , T.IResult(..)
+    , I.compareResults
+
+    -- * Running parsers
+    , parse
+    , feed
+    , I.parseOnly
+    , parseWith
+    , parseTest
+
+    -- ** Result conversion
+    , maybeResult
+    , eitherResult
+
+    -- * Parsing individual characters
+    , I.char
+    , I.anyChar
+    , I.notChar
+    , I.satisfy
+    , I.satisfyWith
+    , I.skip
+
+    -- ** Lookahead
+    , I.peekChar
+    , I.peekChar'
+
+    -- ** Special character parsers
+    , digit
+    , letter
+    , space
+
+    -- ** Character classes
+    , I.inClass
+    , I.notInClass
+
+    -- * Efficient string handling
+    , I.string
+    , I.stringCI
+    , I.asciiCI
+    , skipSpace
+    , I.skipWhile
+    , I.scan
+    , I.runScanner
+    , I.take
+    , I.takeWhile
+    , I.takeWhile1
+    , I.takeTill
+
+    -- ** String combinators
+    -- $specalt
+    , (.*>)
+    , (<*.)
+
+    -- ** Consume all remaining input
+    , I.takeText
+    , I.takeLazyText
+
+    -- * Text parsing
+    , I.endOfLine
+    , isEndOfLine
+    , isHorizontalSpace
+
+    -- * Numeric parsers
+    , decimal
+    , hexadecimal
+    , signed
+    , double
+    , Number(..)
+    , number
+    , rational
+    , scientific
+
+    -- * Combinators
+    , try
+    , (<?>)
+    , choice
+    , count
+    , option
+    , many'
+    , many1
+    , many1'
+    , manyTill
+    , manyTill'
+    , sepBy
+    , sepBy'
+    , sepBy1
+    , sepBy1'
+    , skipMany
+    , skipMany1
+    , eitherP
+    , I.match
+    -- * State observation and manipulation functions
+    , I.endOfInput
+    , I.atEnd
+    ) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (pure, (*>), (<*), (<$>))
+import Data.Word (Word)
+#endif
+import Control.Applicative ((<|>))
+import Data.Attoparsec.Combinator
+import Data.Attoparsec.Number (Number(..))
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
+import Data.Attoparsec.Text.Internal (Parser, Result, parse, takeWhile1)
+import Data.Bits (Bits, (.|.), shiftL)
+import Data.Char (isAlpha, isDigit, isSpace, ord)
+import Data.Int (Int8, Int16, Int32, Int64)
+import Data.List (intercalate)
+import Data.Text (Text)
+import Data.Word (Word8, Word16, Word32, Word64)
+import qualified Data.Attoparsec.Internal as I
+import qualified Data.Attoparsec.Internal.Types as T
+import qualified Data.Attoparsec.Text.Internal as I
+import qualified Data.Text as T
+
+-- $parsec
+--
+-- Compared to Parsec 3, attoparsec makes several tradeoffs.  It is
+-- not intended for, or ideal for, all possible uses.
+--
+-- * While attoparsec can consume input incrementally, Parsec cannot.
+--   Incremental input is a huge deal for efficient and secure network
+--   and system programming, since it gives much more control to users
+--   of the library over matters such as resource usage and the I/O
+--   model to use.
+--
+-- * Much of the performance advantage of attoparsec is gained via
+--   high-performance parsers such as 'I.takeWhile' and 'I.string'.
+--   If you use complicated combinators that return lists of
+--   characters, there is less performance difference between the two
+--   libraries.
+--
+-- * Unlike Parsec 3, attoparsec does not support being used as a
+--   monad transformer.
+--
+-- * attoparsec is specialised to deal only with strict 'Text'
+--   input.  Efficiency concerns rule out both lists and lazy text.
+--   The usual use for lazy text would be to allow consumption of very
+--   large input without a large footprint.  For this need,
+--   attoparsec's incremental input provides an excellent substitute,
+--   with much more control over when input takes place.  If you must
+--   use lazy text, see the 'Lazy' module, which feeds lazy chunks to
+--   a regular parser.
+--
+-- * Parsec parsers can produce more helpful error messages than
+--   attoparsec parsers.  This is a matter of focus: attoparsec avoids
+--   the extra book-keeping in favour of higher performance.
+
+-- $incremental
+--
+-- attoparsec supports incremental input, meaning that you can feed it
+-- a 'Text' that represents only part of the expected total amount
+-- of data to parse. If your parser reaches the end of a fragment of
+-- input and could consume more input, it will suspend parsing and
+-- return a 'T.Partial' continuation.
+--
+-- Supplying the 'T.Partial' continuation with another string will
+-- resume parsing at the point where it was suspended, with the string
+-- you supplied used as new input at the end of the existing
+-- input. You must be prepared for the result of the resumed parse to
+-- be another 'Partial' continuation.
+--
+-- To indicate that you have no more input, supply the 'Partial'
+-- continuation with an 'T.empty' 'Text'.
+--
+-- Remember that some parsing combinators will not return a result
+-- until they reach the end of input.  They may thus cause 'T.Partial'
+-- results to be returned.
+--
+-- If you do not need support for incremental input, consider using
+-- the 'I.parseOnly' function to run your parser.  It will never
+-- prompt for more input.
+--
+-- /Note/: incremental input does /not/ imply that attoparsec will
+-- release portions of its internal state for garbage collection as it
+-- proceeds.  Its internal representation is equivalent to a single
+-- 'Text': if you feed incremental input to an a parser, it will
+-- require memory proportional to the amount of input you supply.
+-- (This is necessary to support arbitrary backtracking.)
+
+-- $performance
+--
+-- If you write an attoparsec-based parser carefully, it can be
+-- realistic to expect it to perform similarly to a hand-rolled C
+-- parser (measuring megabytes parsed per second).
+--
+-- To actually achieve high performance, there are a few guidelines
+-- that it is useful to follow.
+--
+-- Use the 'Text'-oriented parsers whenever possible,
+-- e.g. 'I.takeWhile1' instead of 'many1' 'I.anyChar'.  There is
+-- about a factor of 100 difference in performance between the two
+-- kinds of parser.
+--
+-- For very simple character-testing predicates, write them by hand
+-- instead of using 'I.inClass' or 'I.notInClass'.  For instance, both
+-- of these predicates test for an end-of-line character, but the
+-- first is much faster than the second:
+--
+-- >endOfLine_fast c = c == '\r' || c == '\n'
+-- >endOfLine_slow   = inClass "\r\n"
+--
+-- Make active use of benchmarking and profiling tools to measure,
+-- find the problems with, and improve the performance of your parser.
+
+-- | Run a parser and print its result to standard output.
+parseTest :: (Show a) => I.Parser a -> Text -> IO ()
+parseTest p s = print (parse p s)
+
+-- | Run a parser with an initial input string, and a monadic action
+-- that can supply more input if needed.
+parseWith :: Monad m =>
+             (m Text)
+          -- ^ An action that will be executed to provide the parser
+          -- with more input, if necessary.  The action must return an
+          -- 'T.empty' string when there is no more input available.
+          -> I.Parser a
+          -> Text
+          -- ^ Initial input for the parser.
+          -> m (Result a)
+parseWith refill p s = step $ parse p s
+  where step (T.Partial k) = (step . k) =<< refill
+        step r           = return r
+{-# INLINE parseWith #-}
+
+-- | Convert a 'Result' value to a 'Maybe' value. A 'Partial' result
+-- is treated as failure.
+maybeResult :: Result r -> Maybe r
+maybeResult (T.Done _ r) = Just r
+maybeResult _            = Nothing
+
+-- | Convert a 'Result' value to an 'Either' value. A 'Partial' result
+-- is treated as failure.
+eitherResult :: Result r -> Either String r
+eitherResult (T.Done _ r)        = Right r
+eitherResult (T.Fail _ [] msg)   = Left msg
+eitherResult (T.Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)
+eitherResult _                   = Left "Result: incomplete input"
+
+-- | A predicate that matches either a carriage return @\'\\r\'@ or
+-- newline @\'\\n\'@ character.
+isEndOfLine :: Char -> Bool
+isEndOfLine c = c == '\n' || c == '\r'
+{-# INLINE isEndOfLine #-}
+
+-- | A predicate that matches either a space @\' \'@ or horizontal tab
+-- @\'\\t\'@ character.
+isHorizontalSpace :: Char -> Bool
+isHorizontalSpace c = c == ' ' || c == '\t'
+{-# INLINE isHorizontalSpace #-}
+
+-- | Parse and decode an unsigned hexadecimal number.  The hex digits
+-- @\'a\'@ through @\'f\'@ may be upper or lower case.
+--
+-- This parser does not accept a leading @\"0x\"@ string.
+hexadecimal :: (Integral a, Bits a) => Parser a
+hexadecimal = T.foldl' step 0 `fmap` takeWhile1 isHexDigit
+  where
+    isHexDigit c = (c >= '0' && c <= '9') ||
+                   (c >= 'a' && c <= 'f') ||
+                   (c >= 'A' && c <= 'F')
+    step a c | w >= 48 && w <= 57  = (a `shiftL` 4) .|. fromIntegral (w - 48)
+             | w >= 97             = (a `shiftL` 4) .|. fromIntegral (w - 87)
+             | otherwise           = (a `shiftL` 4) .|. fromIntegral (w - 55)
+      where w = ord c
+{-# SPECIALISE hexadecimal :: Parser Int #-}
+{-# SPECIALISE hexadecimal :: Parser Int8 #-}
+{-# SPECIALISE hexadecimal :: Parser Int16 #-}
+{-# SPECIALISE hexadecimal :: Parser Int32 #-}
+{-# SPECIALISE hexadecimal :: Parser Int64 #-}
+{-# SPECIALISE hexadecimal :: Parser Integer #-}
+{-# SPECIALISE hexadecimal :: Parser Word #-}
+{-# SPECIALISE hexadecimal :: Parser Word8 #-}
+{-# SPECIALISE hexadecimal :: Parser Word16 #-}
+{-# SPECIALISE hexadecimal :: Parser Word32 #-}
+{-# SPECIALISE hexadecimal :: Parser Word64 #-}
+
+-- | Parse and decode an unsigned decimal number.
+decimal :: Integral a => Parser a
+decimal = T.foldl' step 0 `fmap` takeWhile1 isDecimal
+  where step a c = a * 10 + fromIntegral (ord c - 48)
+{-# SPECIALISE decimal :: Parser Int #-}
+{-# SPECIALISE decimal :: Parser Int8 #-}
+{-# SPECIALISE decimal :: Parser Int16 #-}
+{-# SPECIALISE decimal :: Parser Int32 #-}
+{-# SPECIALISE decimal :: Parser Int64 #-}
+{-# SPECIALISE decimal :: Parser Integer #-}
+{-# SPECIALISE decimal :: Parser Word #-}
+{-# SPECIALISE decimal :: Parser Word8 #-}
+{-# SPECIALISE decimal :: Parser Word16 #-}
+{-# SPECIALISE decimal :: Parser Word32 #-}
+{-# SPECIALISE decimal :: Parser Word64 #-}
+
+isDecimal :: Char -> Bool
+isDecimal c = c >= '0' && c <= '9'
+{-# INLINE isDecimal #-}
+
+-- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
+-- character.
+signed :: Num a => Parser a -> Parser a
+{-# SPECIALISE signed :: Parser Int -> Parser Int #-}
+{-# SPECIALISE signed :: Parser Int8 -> Parser Int8 #-}
+{-# SPECIALISE signed :: Parser Int16 -> Parser Int16 #-}
+{-# SPECIALISE signed :: Parser Int32 -> Parser Int32 #-}
+{-# SPECIALISE signed :: Parser Int64 -> Parser Int64 #-}
+{-# SPECIALISE signed :: Parser Integer -> Parser Integer #-}
+signed p = (negate <$> (I.char '-' *> p))
+       <|> (I.char '+' *> p)
+       <|> p
+
+-- | Parse a rational number.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+--
+-- /Note/: this parser is not safe for use with inputs from untrusted
+-- sources.  An input with a suitably large exponent such as
+-- @"1e1000000000"@ will cause a huge 'Integer' to be allocated,
+-- resulting in what is effectively a denial-of-service attack.
+--
+-- In most cases, it is better to use 'double' or 'scientific'
+-- instead.
+rational :: Fractional a => Parser a
+{-# SPECIALIZE rational :: Parser Double #-}
+{-# SPECIALIZE rational :: Parser Float #-}
+{-# SPECIALIZE rational :: Parser Rational #-}
+{-# SPECIALIZE rational :: Parser Scientific #-}
+rational = scientifically realToFrac
+
+-- | Parse a 'Double'.
+--
+-- This parser accepts an optional leading sign character, followed by
+-- at most one decimal digit.  The syntax is similar to that accepted by
+-- the 'read' function, with the exception that a trailing @\'.\'@ is
+-- consumed.
+--
+-- === Examples
+--
+-- These examples use this helper:
+--
+-- @
+-- r :: 'Parser' a -> 'Data.Text.Text' -> 'Data.Attoparsec.Text.Result' a
+-- r p s = 'feed' ('Data.Attoparsec.parse' p s) 'mempty'
+-- @
+--
+-- Examples with behaviour identical to 'read', if you feed an empty
+-- continuation to the first result:
+--
+-- > r double "3"     == Done "" 3.0
+-- > r double "3.1"   == Done "" 3.1
+-- > r double "3e4"   == Done "" 30000.0
+-- > r double "3.1e4" == Done "" 31000.0
+-- > r double "3e"    == Done "e" 3.0
+--
+-- Examples with behaviour identical to 'read':
+--
+-- > r double ".3"    == Fail ".3" _ _
+-- > r double "e3"    == Fail "e3" _ _
+--
+-- Example of difference from 'read':
+--
+-- > r double "3.foo" == Done "foo" 3.0
+--
+-- This function does not accept string representations of \"NaN\" or
+-- \"Infinity\".
+double :: Parser Double
+double = scientifically Sci.toRealFloat
+
+-- | Parse a number, attempting to preserve both speed and precision.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+--
+-- This function does not accept string representations of \"NaN\" or
+-- \"Infinity\".
+number :: Parser Number
+number = scientifically $ \s ->
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
+            in if e >= 0
+               then I (c * 10 ^ e)
+               else D (Sci.toRealFloat s)
+{-# DEPRECATED number "Use 'scientific' instead." #-}
+
+-- | Parse a scientific number.
+--
+-- The syntax accepted by this parser is the same as for 'double'.
+scientific :: Parser Scientific
+scientific = scientifically id
+
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
+{-# INLINE scientifically #-}
+scientifically :: (Scientific -> a) -> Parser a
+scientifically h = do
+  !positive <- ((== '+') <$> I.satisfy (\c -> c == '-' || c == '+')) <|>
+               pure True
+
+  n <- decimal
+
+  let f fracDigits = SP (T.foldl' step n fracDigits)
+                        (negate $ T.length fracDigits)
+      step a c = a * 10 + fromIntegral (ord c - 48)
+
+  SP c e <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>
+            pure (SP n 0)
+
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
+
+  (I.satisfy (\w -> w == 'e' || w == 'E') *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)
+
+-- | Parse a single digit, as recognised by 'isDigit'.
+digit :: Parser Char
+digit = I.satisfy isDigit <?> "digit"
+{-# INLINE digit #-}
+
+-- | Parse a letter, as recognised by 'isAlpha'.
+letter :: Parser Char
+letter = I.satisfy isAlpha <?> "letter"
+{-# INLINE letter #-}
+
+-- | Parse a space character, as recognised by 'isSpace'.
+space :: Parser Char
+space = I.satisfy isSpace <?> "space"
+{-# INLINE space #-}
+
+-- | Skip over white space.
+skipSpace :: Parser ()
+skipSpace = I.skipWhile isSpace
+{-# INLINE skipSpace #-}
+
+-- $specalt
+--
+-- If you enable the @OverloadedStrings@ language extension, you can
+-- use the '*>' and '<*' combinators to simplify the common task of
+-- matching a statically known string, then immediately parsing
+-- something else.
+--
+-- Instead of writing something like this:
+--
+-- @
+--'I.string' \"foo\" '*>' wibble
+-- @
+--
+-- Using @OverloadedStrings@, you can omit the explicit use of
+-- 'I.string', and write a more compact version:
+--
+-- @
+-- \"foo\" '*>' wibble
+-- @
+--
+-- (Note: the '.*>' and '<*.' combinators that were originally
+-- provided for this purpose are obsolete and unnecessary, and will be
+-- removed in the next major version.)
+
+-- | /Obsolete/. A type-specialized version of '*>' for 'Text'. Use
+-- '*>' instead.
+(.*>) :: Text -> Parser a -> Parser a
+s .*> f = I.string s *> f
+{-# DEPRECATED (.*>) "This is no longer necessary, and will be removed. Use '*>' instead." #-}
+
+-- | /Obsolete/. A type-specialized version of '<*' for 'Text'. Use
+-- '*>' instead.
+(<*.) :: Parser a -> Text -> Parser a
+f <*. s = f <* I.string s
+{-# DEPRECATED (<*.) "This is no longer necessary, and will be removed. Use '<*' instead." #-}
diff --git a/Data/Attoparsec/Text/Internal.hs b/Data/Attoparsec/Text/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/Text/Internal.hs
@@ -0,0 +1,549 @@
+{-# LANGUAGE BangPatterns, FlexibleInstances, GADTs, OverloadedStrings,
+    Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+-- |
+-- Module      :  Data.Attoparsec.Text.Internal
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient parser combinators for 'Text' strings, loosely
+-- based on the Parsec library.
+
+module Data.Attoparsec.Text.Internal
+    (
+    -- * Parser types
+      Parser
+    , Result
+
+    -- * Running parsers
+    , parse
+    , parseOnly
+
+    -- * Combinators
+    , module Data.Attoparsec.Combinator
+
+    -- * Parsing individual characters
+    , satisfy
+    , satisfyWith
+    , anyChar
+    , skip
+    , char
+    , notChar
+
+    -- ** Lookahead
+    , peekChar
+    , peekChar'
+
+    -- ** Character classes
+    , inClass
+    , notInClass
+
+    -- * Efficient string handling
+    , skipWhile
+    , string
+    , stringCI
+    , asciiCI
+    , take
+    , scan
+    , runScanner
+    , takeWhile
+    , takeWhile1
+    , takeTill
+
+    -- ** Consume all remaining input
+    , takeText
+    , takeLazyText
+
+    -- * Utilities
+    , endOfLine
+    , endOfInput
+    , match
+    , atEnd
+    ) where
+
+import Control.Applicative ((<|>), (<$>), pure, (*>))
+import Control.Monad (when)
+import Data.Attoparsec.Combinator ((<?>))
+import Data.Attoparsec.Internal
+import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
+import qualified Data.Attoparsec.Text.Buffer as Buf
+import Data.Attoparsec.Text.Buffer (Buffer, buffer)
+import Data.Char (isAsciiUpper, isAsciiLower, toUpper, toLower)
+import Data.List (intercalate)
+import Data.String (IsString(..))
+import Data.Text.Internal (Text(..))
+import Prelude hiding (getChar, succ, take, takeWhile)
+import qualified Data.Attoparsec.Internal.Types as T
+import qualified Data.Attoparsec.Text.FastSet as Set
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as L
+import qualified Data.Text.Unsafe as T
+
+type Parser = T.Parser Text
+type Result = IResult Text
+type Failure r = T.Failure Text Buffer r
+type Success a r = T.Success Text Buffer a r
+
+instance (a ~ Text) => IsString (Parser a) where
+    fromString = string . T.pack
+
+-- | The parser @satisfy p@ succeeds for any character for which the
+-- predicate @p@ returns 'True'. Returns the character that is
+-- actually parsed.
+--
+-- >digit = satisfy isDigit
+-- >    where isDigit c = c >= '0' && c <= '9'
+satisfy :: (Char -> Bool) -> Parser Char
+satisfy p = do
+  (k,c) <- ensure 1
+  let !h = T.unsafeHead c
+  if p h
+    then advance k >> return h
+    else fail "satisfy"
+{-# INLINE satisfy #-}
+
+-- | The parser @skip p@ succeeds for any character for which the
+-- predicate @p@ returns 'True'.
+--
+-- >skipDigit = skip isDigit
+-- >    where isDigit c = c >= '0' && c <= '9'
+skip :: (Char -> Bool) -> Parser ()
+skip p = do
+  (k,s) <- ensure 1
+  if p (T.unsafeHead s)
+    then advance k
+    else fail "skip"
+
+-- | The parser @satisfyWith f p@ transforms a character, and succeeds
+-- if the predicate @p@ returns 'True' on the transformed value. The
+-- parser returns the transformed character that was parsed.
+satisfyWith :: (Char -> a) -> (a -> Bool) -> Parser a
+satisfyWith f p = do
+  (k,s) <- ensure 1
+  let c = f $! T.unsafeHead s
+  if p c
+    then advance k >> return c
+    else fail "satisfyWith"
+{-# INLINE satisfyWith #-}
+
+-- | Consume @n@ characters of input, but succeed only if the
+-- predicate returns 'True'.
+takeWith :: Int -> (Text -> Bool) -> Parser Text
+takeWith n p = do
+  (k,s) <- ensure n
+  if p s
+    then advance k >> return s
+    else fail "takeWith"
+
+-- | Consume exactly @n@ characters of input.
+take :: Int -> Parser Text
+take n = takeWith (max n 0) (const True)
+{-# INLINE take #-}
+
+-- | @string s@ parses a sequence of characters that identically match
+-- @s@. Returns the parsed string (i.e. @s@).  This parser consumes no
+-- input if it fails (even if a partial match).
+--
+-- /Note/: The behaviour of this parser is different to that of the
+-- similarly-named parser in Parsec, as this one is all-or-nothing.
+-- To illustrate the difference, the following parser will fail under
+-- Parsec given an input of @\"for\"@:
+--
+-- >string "foo" <|> string "for"
+--
+-- The reason for its failure is that the first branch is a
+-- partial match, and will consume the letters @\'f\'@ and @\'o\'@
+-- before failing.  In attoparsec, the above parser will /succeed/ on
+-- that input, because the failed first branch will consume nothing.
+string :: Text -> Parser Text
+string s = string_ (stringSuspended id) id s
+{-# INLINE string #-}
+
+string_ :: (forall r. Text -> Text -> Buffer -> Pos -> More
+            -> Failure r -> Success Text r -> Result r)
+        -> (Text -> Text)
+        -> Text -> Parser Text
+string_ suspended f s0 = T.Parser $ \t pos more lose succ ->
+  let s  = f s0
+      ft = f (Buf.unbufferAt (fromPos pos) t)
+  in case T.commonPrefixes s ft of
+       Nothing
+         | T.null s          -> succ t pos more T.empty
+         | T.null ft         -> suspended s s t pos more lose succ
+         | otherwise         -> lose t pos more [] "string"
+       Just (pfx,ssfx,tsfx)
+         | T.null ssfx       -> let l = Pos (Buf.lengthCodeUnits pfx)
+                                in succ t (pos + l) more (substring pos l t)
+         | not (T.null tsfx) -> lose t pos more [] "string"
+         | otherwise         -> suspended s ssfx t pos more lose succ
+{-# INLINE string_ #-}
+
+stringSuspended :: (Text -> Text)
+                -> Text -> Text -> Buffer -> Pos -> More
+                -> Failure r
+                -> Success Text r
+                -> Result r
+stringSuspended f s000 s0 t0 pos0 more0 lose0 succ0 =
+    runParser (demandInput_ >>= go) t0 pos0 more0 lose0 succ0
+  where
+    go s' = T.Parser $ \t pos more lose succ ->
+      let s = f s'
+      in case T.commonPrefixes s0 s of
+        Nothing         -> lose t pos more [] "string"
+        Just (_pfx,ssfx,tsfx)
+          | T.null ssfx -> let l = Pos (Buf.lengthCodeUnits s000)
+                           in succ t (pos + l) more (substring pos l t)
+          | T.null tsfx -> stringSuspended f s000 ssfx t pos more lose succ
+          | otherwise   -> lose t pos more [] "string"
+
+-- | Satisfy a literal string, ignoring case.
+--
+-- Note: this function is currently quite inefficient. Unicode case
+-- folding can change the length of a string (\"&#223;\" becomes
+-- "ss"), which makes a simple, efficient implementation tricky.  We
+-- have (for now) chosen simplicity over efficiency.
+stringCI :: Text -> Parser Text
+stringCI s = go 0
+  where
+    go !n
+      | n > T.length fs = fail "stringCI"
+      | otherwise = do
+      (k,t) <- ensure n
+      if T.toCaseFold t == fs
+        then advance k >> return t
+        else go (n+1)
+    fs = T.toCaseFold s
+{-# INLINE stringCI #-}
+{-# DEPRECATED stringCI "this is very inefficient, use asciiCI instead" #-}
+
+-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
+asciiCI :: Text -> Parser Text
+asciiCI s = fmap fst $ match $ T.foldr ((*>) . asciiCharCI) (pure ()) s
+{-# INLINE asciiCI #-}
+
+asciiCharCI :: Char -> Parser Char
+asciiCharCI c
+  | isAsciiUpper c = char c <|> char (toLower c)
+  | isAsciiLower c = char c <|> char (toUpper c)
+  | otherwise = char c
+{-# INLINE asciiCharCI #-}
+
+-- | Skip past input for as long as the predicate returns 'True'.
+skipWhile :: (Char -> Bool) -> Parser ()
+skipWhile p = go
+ where
+  go = do
+    t <- T.takeWhile p <$> get
+    continue <- inputSpansChunks (size t)
+    when continue go
+{-# INLINE skipWhile #-}
+
+-- | Consume input as long as the predicate returns 'False'
+-- (i.e. until it returns 'True'), and return the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'True' on the first character of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+takeTill :: (Char -> Bool) -> Parser Text
+takeTill p = takeWhile (not . p)
+{-# INLINE takeTill #-}
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'False' on the first character of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+takeWhile :: (Char -> Bool) -> Parser Text
+takeWhile p = do
+    h <- T.takeWhile p <$> get
+    continue <- inputSpansChunks (size h)
+    -- only use slow concat path if necessary
+    if continue
+      then takeWhileAcc p [h]
+      else return h
+{-# INLINE takeWhile #-}
+
+takeWhileAcc :: (Char -> Bool) -> [Text] -> Parser Text
+takeWhileAcc p = go
+ where
+  go acc = do
+    h <- T.takeWhile p <$> get
+    continue <- inputSpansChunks (size h)
+    if continue
+      then go (h:acc)
+      else return $ concatReverse (h:acc)
+{-# INLINE takeWhileAcc #-}
+
+takeRest :: Parser [Text]
+takeRest = go []
+ where
+  go acc = do
+    input <- wantInput
+    if input
+      then do
+        s <- get
+        advance (size s)
+        go (s:acc)
+      else return (reverse acc)
+
+-- | Consume all remaining input and return it as a single string.
+takeText :: Parser Text
+takeText = T.concat `fmap` takeRest
+
+-- | Consume all remaining input and return it as a single string.
+takeLazyText :: Parser L.Text
+takeLazyText = L.fromChunks `fmap` takeRest
+
+data Scan s = Continue s
+            | Finished s {-# UNPACK #-} !Int Text
+
+scan_ :: (s -> [Text] -> Parser r) -> s -> (s -> Char -> Maybe s) -> Parser r
+scan_ f s0 p = go [] s0
+ where
+  scanner s !n t =
+    case T.uncons t of
+      Just (c,t') -> case p s c of
+                       Just s' -> scanner s' (n+1) t'
+                       Nothing -> Finished s n t
+      Nothing     -> Continue s
+  go acc s = do
+    input <- get
+    case scanner s 0 input of
+      Continue s'  -> do continue <- inputSpansChunks (size input)
+                         if continue
+                           then go (input : acc) s'
+                           else f s' (input : acc)
+      Finished s' n t -> do advance (size input - size t)
+                            f s' (T.take n input : acc)
+{-# INLINE scan_ #-}
+
+-- | A stateful scanner.  The predicate consumes and transforms a
+-- state argument, and each transformed state is passed to successive
+-- invocations of the predicate on each character of the input until one
+-- returns 'Nothing' or the input ends.
+--
+-- This parser does not fail.  It will return an empty string if the
+-- predicate returns 'Nothing' on the first character of input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+scan :: s -> (s -> Char -> Maybe s) -> Parser Text
+scan = scan_ $ \_ chunks -> return $! concatReverse chunks
+{-# INLINE scan #-}
+
+-- | Like 'scan', but generalized to return the final state of the
+-- scanner.
+runScanner :: s -> (s -> Char -> Maybe s) -> Parser (Text, s)
+runScanner = scan_ $ \s xs -> let !sx = concatReverse xs in return (sx, s)
+{-# INLINE runScanner #-}
+
+-- | Consume input as long as the predicate returns 'True', and return
+-- the consumed input.
+--
+-- This parser requires the predicate to succeed on at least one
+-- character of input: it will fail if the predicate never returns
+-- 'True' or if there is no input left.
+takeWhile1 :: (Char -> Bool) -> Parser Text
+takeWhile1 p = do
+  (`when` demandInput) =<< endOfChunk
+  h <- T.takeWhile p <$> get
+  let size' = size h
+  when (size' == 0) $ fail "takeWhile1"
+  advance size'
+  eoc <- endOfChunk
+  if eoc
+    then takeWhileAcc p [h]
+    else return h
+{-# INLINE takeWhile1 #-}
+
+-- | Match any character in a set.
+--
+-- >vowel = inClass "aeiou"
+--
+-- Range notation is supported.
+--
+-- >halfAlphabet = inClass "a-nA-N"
+--
+-- To add a literal @\'-\'@ to a set, place it at the beginning or end
+-- of the string.
+inClass :: String -> Char -> Bool
+inClass s = (`Set.member` mySet)
+    where mySet = Set.charClass s
+          {-# NOINLINE mySet #-}
+{-# INLINE inClass #-}
+
+-- | Match any character not in a set.
+notInClass :: String -> Char -> Bool
+notInClass s = not . inClass s
+{-# INLINE notInClass #-}
+
+-- | Match any character.
+anyChar :: Parser Char
+anyChar = satisfy $ const True
+{-# INLINE anyChar #-}
+
+-- | Match a specific character.
+char :: Char -> Parser Char
+char c = satisfy (== c) <?> show c
+{-# INLINE char #-}
+
+-- | Match any character except the given one.
+notChar :: Char -> Parser Char
+notChar c = satisfy (/= c) <?> "not " ++ show c
+{-# INLINE notChar #-}
+
+-- | Match any character, to perform lookahead. Returns 'Nothing' if
+-- end of input has been reached. Does not consume any input.
+--
+-- /Note/: Because this parser does not fail, do not use it with
+-- combinators such as 'Control.Applicative.many', because such
+-- parsers loop until a failure occurs.  Careless use will thus result
+-- in an infinite loop.
+peekChar :: Parser (Maybe Char)
+peekChar = T.Parser $ \t pos more _lose succ ->
+  case () of
+    _| pos < lengthOf t ->
+       let T.Iter !c _ = Buf.iter t (fromPos pos)
+       in succ t pos more (Just c)
+     | more == Complete ->
+       succ t pos more Nothing
+     | otherwise ->
+       let succ' t' pos' more' =
+             let T.Iter !c _ = Buf.iter t' (fromPos pos')
+             in succ t' pos' more' (Just c)
+           lose' t' pos' more' = succ t' pos' more' Nothing
+       in prompt t pos more lose' succ'
+{-# INLINE peekChar #-}
+
+-- | Match any character, to perform lookahead.  Does not consume any
+-- input, but will fail if end of input has been reached.
+peekChar' :: Parser Char
+peekChar' = do
+  (_,s) <- ensure 1
+  return $! T.unsafeHead s
+{-# INLINE peekChar' #-}
+
+-- | Match either a single newline character @\'\\n\'@, or a carriage
+-- return followed by a newline character @\"\\r\\n\"@.
+endOfLine :: Parser ()
+endOfLine = (char '\n' >> return ()) <|> (string "\r\n" >> return ())
+
+-- | Terminal failure continuation.
+failK :: Failure a
+failK t (Pos pos) _more stack msg = Fail (Buf.dropCodeUnits pos t) stack msg
+{-# INLINE failK #-}
+
+-- | Terminal success continuation.
+successK :: Success a a
+successK t (Pos pos) _more a = Done (Buf.dropCodeUnits pos t) a
+{-# INLINE successK #-}
+
+-- | Run a parser.
+parse :: Parser a -> Text -> Result a
+parse m s = runParser m (buffer s) 0 Incomplete failK successK
+{-# INLINE parse #-}
+
+-- | Run a parser that cannot be resupplied via a 'Partial' result.
+--
+-- This function does not force a parser to consume all of its input.
+-- Instead, any residual input will be discarded.  To force a parser
+-- to consume all of its input, use something like this:
+--
+-- @
+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')
+-- @
+parseOnly :: Parser a -> Text -> Either String a
+parseOnly m s = case runParser m (buffer s) 0 Complete failK successK of
+                  Fail _ [] err   -> Left err
+                  Fail _ ctxs err -> Left (intercalate " > " ctxs ++ ": " ++ err)
+                  Done _ a        -> Right a
+                  _               -> error "parseOnly: impossible error!"
+{-# INLINE parseOnly #-}
+
+get :: Parser Text
+get = T.Parser $ \t pos more _lose succ ->
+  succ t pos more (Buf.dropCodeUnits (fromPos pos) t)
+{-# INLINE get #-}
+
+endOfChunk :: Parser Bool
+endOfChunk = T.Parser $ \t pos more _lose succ ->
+  succ t pos more (pos == lengthOf t)
+{-# INLINE endOfChunk #-}
+
+inputSpansChunks :: Pos -> Parser Bool
+inputSpansChunks i = T.Parser $ \t pos_ more _lose succ ->
+  let pos = pos_ + i
+  in if pos < lengthOf t || more == Complete
+     then succ t pos more False
+     else let lose' t' pos' more' = succ t' pos' more' False
+              succ' t' pos' more' = succ t' pos' more' True
+          in prompt t pos more lose' succ'
+{-# INLINE inputSpansChunks #-}
+
+advance :: Pos -> Parser ()
+advance n = T.Parser $ \t pos more _lose succ -> succ t (pos+n) more ()
+{-# INLINE advance #-}
+
+ensureSuspended :: Int -> Buffer -> Pos -> More
+                -> Failure r -> Success (Pos, Text) r
+                -> Result r
+ensureSuspended n t pos more lose succ =
+    runParser (demandInput >> go) t pos more lose succ
+  where go = T.Parser $ \t' pos' more' lose' succ' ->
+          case lengthAtLeast pos' n t' of
+            Just n' -> succ' t' pos' more' (n', substring pos n' t')
+            Nothing -> runParser (demandInput >> go) t' pos' more' lose' succ'
+
+-- | If at least @n@ elements of input are available, return the
+-- current input, otherwise fail.
+ensure :: Int -> Parser (Pos, Text)
+ensure n = T.Parser $ \t pos more lose succ ->
+    case lengthAtLeast pos n t of
+      Just n' -> succ t pos more (n', substring pos n' t)
+      -- The uncommon case is kept out-of-line to reduce code size:
+      Nothing -> ensureSuspended n t pos more lose succ
+{-# INLINE ensure #-}
+
+-- | Return both the result of a parse and the portion of the input
+-- that was consumed while it was being parsed.
+match :: Parser a -> Parser (Text, a)
+match p = T.Parser $ \t pos more lose succ ->
+  let succ' t' pos' more' a = succ t' pos' more'
+                              (substring pos (pos'-pos) t', a)
+  in runParser p t pos more lose succ'
+
+-- | Ensure that at least @n@ code points of input are available.
+-- Returns the number of words consumed while traversing.
+lengthAtLeast :: Pos -> Int -> Buffer -> Maybe Pos
+lengthAtLeast pos n t = go 0 (fromPos pos)
+  where go i !p
+          | i == n    = Just (Pos p - pos)
+          | p == len  = Nothing
+          | otherwise = go (i+1) (p + Buf.iter_ t p)
+        Pos len = lengthOf t
+{-# INLINE lengthAtLeast #-}
+
+substring :: Pos -> Pos -> Buffer -> Text
+substring (Pos pos) (Pos n) = Buf.substring pos n
+{-# INLINE substring #-}
+
+lengthOf :: Buffer -> Pos
+lengthOf = Pos . Buf.length
+
+size :: Text -> Pos
+size (Text _ _ l) = Pos l
diff --git a/Data/Attoparsec/Text/Lazy.hs b/Data/Attoparsec/Text/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/Text/Lazy.hs
@@ -0,0 +1,115 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Imports internal modules
+#endif
+
+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+-- |
+-- Module      :  Data.Attoparsec.Text.Lazy
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient combinator parsing that can consume lazy 'Text'
+-- strings, loosely based on the Parsec library.
+--
+-- This is essentially the same code as in the 'Data.Attoparsec.Text'
+-- module, only with a 'parse' function that can consume a lazy
+-- 'Text' incrementally, and a 'Result' type that does not allow
+-- more input to be fed in.  Think of this as suitable for use with a
+-- lazily read file, e.g. via 'L.readFile' or 'L.hGetContents'.
+--
+-- /Note:/ The various parser functions and combinators such as
+-- 'string' still expect /strict/ 'T.Text' parameters, and return
+-- strict 'T.Text' results.  Behind the scenes, strict 'T.Text' values
+-- are still used internally to store parser input and manipulate it
+-- efficiently.
+
+module Data.Attoparsec.Text.Lazy
+    (
+      Result(..)
+    , module Data.Attoparsec.Text
+    -- * Running parsers
+    , parse
+    , parseOnly
+    , parseTest
+    -- ** Result conversion
+    , maybeResult
+    , eitherResult
+    ) where
+
+import Control.DeepSeq (NFData(rnf))
+import Data.List (intercalate)
+import Data.Text.Lazy.Internal (Text(..), chunk)
+import qualified Data.Attoparsec.Internal.Types as T
+import qualified Data.Attoparsec.Text as A
+import qualified Data.Text as T
+import Data.Attoparsec.Text hiding (IResult(..), Result, eitherResult,
+                                    maybeResult, parse, parseOnly, parseWith, parseTest)
+
+-- | The result of a parse.
+data Result r = Fail Text [String] String
+              -- ^ The parse failed.  The 'Text' is the input
+              -- that had not yet been consumed when the failure
+              -- occurred.  The @[@'String'@]@ is a list of contexts
+              -- in which the error occurred.  The 'String' is the
+              -- message describing the error, if any.
+              | Done Text r
+              -- ^ The parse succeeded.  The 'Text' is the
+              -- input that had not yet been consumed (if any) when
+              -- the parse succeeded.
+    deriving (Show)
+
+instance NFData r => NFData (Result r) where
+    rnf (Fail bs ctxs msg) = rnf bs `seq` rnf ctxs `seq` rnf msg
+    rnf (Done bs r)        = rnf bs `seq` rnf r
+    {-# INLINE rnf #-}
+
+fmapR :: (a -> b) -> Result a -> Result b
+fmapR _ (Fail st stk msg) = Fail st stk msg
+fmapR f (Done bs r)       = Done bs (f r)
+
+instance Functor Result where
+    fmap = fmapR
+
+-- | Run a parser and return its result.
+parse :: A.Parser a -> Text -> Result a
+parse p s = case s of
+              Chunk x xs -> go (A.parse p x) xs
+              empty      -> go (A.parse p T.empty) empty
+  where
+    go (T.Fail x stk msg) ys      = Fail (chunk x ys) stk msg
+    go (T.Done x r) ys            = Done (chunk x ys) r
+    go (T.Partial k) (Chunk y ys) = go (k y) ys
+    go (T.Partial k) empty        = go (k T.empty) empty
+
+-- | Run a parser and print its result to standard output.
+parseTest :: (Show a) => A.Parser a -> Text -> IO ()
+parseTest p s = print (parse p s)
+
+-- | Convert a 'Result' value to a 'Maybe' value.
+maybeResult :: Result r -> Maybe r
+maybeResult (Done _ r) = Just r
+maybeResult _          = Nothing
+
+-- | Convert a 'Result' value to an 'Either' value.
+eitherResult :: Result r -> Either String r
+eitherResult (Done _ r)        = Right r
+eitherResult (Fail _ [] msg)   = Left msg
+eitherResult (Fail _ ctxs msg) = Left (intercalate " > " ctxs ++ ": " ++ msg)
+
+-- | Run a parser that cannot be resupplied via a 'T.Partial' result.
+--
+-- This function does not force a parser to consume all of its input.
+-- Instead, any residual input will be discarded.  To force a parser
+-- to consume all of its input, use something like this:
+--
+-- @
+--'parseOnly' (myParser 'Control.Applicative.<*' 'endOfInput')
+-- @
+parseOnly :: A.Parser a -> Text -> Either String a
+parseOnly p = eitherResult . parse p
+{-# INLINE parseOnly #-}
diff --git a/Data/Attoparsec/Types.hs b/Data/Attoparsec/Types.hs
new file mode 100644
--- /dev/null
+++ b/Data/Attoparsec/Types.hs
@@ -0,0 +1,20 @@
+-- |
+-- Module      :  Data.Attoparsec.Types
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Simple, efficient parser combinators for strings, loosely based on
+-- the Parsec library.
+
+module Data.Attoparsec.Types
+    (
+      Parser
+    , IResult(..)
+    , Chunk(chunkElemToChar)
+    ) where
+
+import Data.Attoparsec.Internal.Types (Parser(..), IResult(..), Chunk(..))
diff --git a/Data/Attoparsec/Zepto.hs b/Data/Attoparsec/Zepto.hs
--- a/Data/Attoparsec/Zepto.hs
+++ b/Data/Attoparsec/Zepto.hs
@@ -1,10 +1,14 @@
-{-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples #-}
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-} -- Data.ByteString.Unsafe
+#endif
+{-# LANGUAGE BangPatterns #-}
 
 -- |
 -- Module      :  Data.Attoparsec.Zepto
--- Copyright   :  Bryan O'Sullivan 2011
+-- Copyright   :  Bryan O'Sullivan 2007-2015
 -- License     :  BSD3
--- 
+--
 -- Maintainer  :  bos@serpentine.com
 -- Stability   :  experimental
 -- Portability :  unknown
@@ -12,112 +16,150 @@
 -- A tiny, highly specialized combinator parser for 'B.ByteString'
 -- strings.
 --
--- While the main Attoparsec module generally performs well, this
+-- While the main attoparsec module generally performs well, this
 -- module is particularly fast for simple non-recursive loops that
 -- should not normally result in failed parses.
 --
 -- /Warning/: on more complex inputs involving recursion or failure,
 -- parsers based on this module may be as much as /ten times slower/
--- than regular Attoparsec! You should /only/ use this module when you
+-- than regular attoparsec! You should /only/ use this module when you
 -- have benchmarks that prove that its use speeds your code up.
 module Data.Attoparsec.Zepto
     (
       Parser
+    , ZeptoT
     , parse
+    , parseT
     , atEnd
     , string
     , take
     , takeWhile
     ) where
 
-import Data.Word (Word8)
 import Control.Applicative
-import Control.Monad
-import Data.Monoid
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Unsafe as B
+import Control.Monad (MonadPlus(..), ap)
+import qualified Control.Monad.Fail as Fail
+import Control.Monad.IO.Class (MonadIO(..))
 import Data.ByteString (ByteString)
+import Data.Functor.Identity (Identity(runIdentity))
+import Data.Monoid as Mon (Monoid(..))
+import Data.Semigroup (Semigroup(..))
+import Data.Word (Word8)
 import Prelude hiding (take, takeWhile)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Unsafe as B
 
 newtype S = S {
       input :: ByteString
     }
 
 data Result a = Fail String
-              | OK !a
+              | OK !a S
 
 -- | A simple parser.
 --
 -- This monad is strict in its state, and the monadic bind operator
 -- ('>>=') evaluates each result to weak head normal form before
 -- passing it along.
-newtype Parser a = Parser {
-      runParser :: S -> (# Result a, S #)
+newtype ZeptoT m a = Parser {
+      runParser :: S -> m (Result a)
     }
 
-instance Functor Parser where
-    fmap f m = Parser $ \s -> case runParser m s of
-                                (# OK a, s' #)     -> (# OK (f a), s' #)
-                                (# Fail err, s' #) -> (# Fail err, s' #)
+type Parser a = ZeptoT Identity a
+
+instance Monad m => Functor (ZeptoT m) where
+    fmap f m = Parser $ \s -> do
+      result <- runParser m s
+      case result of
+        OK a s'  -> return (OK (f a) s')
+        Fail err -> return (Fail err)
     {-# INLINE fmap #-}
 
-instance Monad Parser where
-    return a = Parser $ \s -> (# OK a, s #)
+instance MonadIO m => MonadIO (ZeptoT m) where
+  liftIO act = Parser $ \s -> do
+    result <- liftIO act
+    return (OK result s)
+  {-# INLINE liftIO #-}
+
+instance Monad m => Monad (ZeptoT m) where
+    return = pure
     {-# INLINE return #-}
 
-    m >>= k   = Parser $ \s -> case runParser m s of
-                                 (# OK a, s' #) -> runParser (k a) s'
-                                 (# Fail err, s' #) -> (# Fail err, s' #)
+    m >>= k   = Parser $ \s -> do
+      result <- runParser m s
+      case result of
+        OK a s'  -> runParser (k a) s'
+        Fail err -> return (Fail err)
     {-# INLINE (>>=) #-}
 
-    fail msg = Parser $ \s -> (# Fail msg, s #)
+#if !(MIN_VERSION_base(4,13,0))
+    fail = Fail.fail
+    {-# INLINE fail #-}
+#endif
 
-instance MonadPlus Parser where
+instance Monad m => Fail.MonadFail (ZeptoT m) where
+    fail msg = Parser $ \_ -> return (Fail msg)
+    {-# INLINE fail #-}
+
+instance Monad m => MonadPlus (ZeptoT m) where
     mzero = fail "mzero"
     {-# INLINE mzero #-}
 
-    mplus a b = Parser $ \s ->
-                case runParser a s of
-                  (# ok@(OK _), s' #) -> (# ok, s' #)
-                  (# _, _ #) -> case runParser b s of
-                                   (# ok@(OK _), s'' #) -> (# ok, s'' #)
-                                   (# err, s'' #) -> (# err, s'' #)
+    mplus a b = Parser $ \s -> do
+      result <- runParser a s
+      case result of
+        ok@(OK _ _) -> return ok
+        _           -> runParser b s
     {-# INLINE mplus #-}
 
-instance Applicative Parser where
-    pure   = return
+instance (Monad m) => Applicative (ZeptoT m) where
+    pure a = Parser $ \s -> return (OK a s)
     {-# INLINE pure #-}
     (<*>)  = ap
     {-# INLINE (<*>) #-}
 
-gets :: (S -> a) -> Parser a
-gets f = Parser $ \s -> (# OK (f s), s #)
+gets :: Monad m => (S -> a) -> ZeptoT m a
+gets f = Parser $ \s -> return (OK (f s) s)
 {-# INLINE gets #-}
 
-put :: S -> Parser ()
-put s = Parser $ \_ -> (# OK (), s #)
+put :: Monad m => S -> ZeptoT m ()
+put s = Parser $ \_ -> return (OK () s)
 {-# INLINE put #-}
 
 -- | Run a parser.
 parse :: Parser a -> ByteString -> Either String a
-parse p bs = case runParser p (S bs) of
-               (# OK a, _ #) -> Right a
-               (# Fail err, _ #) -> Left err
+parse p bs = case runIdentity (runParser p (S bs)) of
+               (OK a _)   -> Right a
+               (Fail err) -> Left err
+{-# INLINE parse #-}
 
-instance Monoid (Parser a) where
+-- | Run a parser on top of the given base monad.
+parseT :: Monad m => ZeptoT m a -> ByteString -> m (Either String a)
+parseT p bs = do
+  result <- runParser p (S bs)
+  case result of
+    OK a _   -> return (Right a)
+    Fail err -> return (Left err)
+{-# INLINE parseT #-}
+
+instance Monad m => Semigroup (ZeptoT m a) where
+    (<>) = mplus
+    {-# INLINE (<>) #-}
+
+instance Monad m => Mon.Monoid (ZeptoT m a) where
     mempty  = fail "mempty"
     {-# INLINE mempty #-}
-    mappend = mplus
+    mappend = (<>)
     {-# INLINE mappend #-}
 
-instance Alternative Parser where
+instance Monad m => Alternative (ZeptoT m) where
     empty = fail "empty"
     {-# INLINE empty #-}
     (<|>) = mplus
     {-# INLINE (<|>) #-}
 
 -- | Consume input while the predicate returns 'True'.
-takeWhile :: (Word8 -> Bool) -> Parser ByteString
+takeWhile :: Monad m => (Word8 -> Bool) -> ZeptoT m ByteString
 takeWhile p = do
   (h,t) <- gets (B.span p . input)
   put (S t)
@@ -125,7 +167,7 @@
 {-# INLINE takeWhile #-}
 
 -- | Consume @n@ bytes of input.
-take :: Int -> Parser ByteString
+take :: Monad m => Int -> ZeptoT m ByteString
 take !n = do
   s <- gets input
   if B.length s >= n
@@ -134,7 +176,7 @@
 {-# INLINE take #-}
 
 -- | Match a string exactly.
-string :: ByteString -> Parser ()
+string :: Monad m => ByteString -> ZeptoT m ()
 string s = do
   i <- gets input
   if s `B.isPrefixOf` i
@@ -143,7 +185,7 @@
 {-# INLINE string #-}
 
 -- | Indicate whether the end of the input has been reached.
-atEnd :: Parser Bool
+atEnd :: Monad m => ZeptoT m Bool
 atEnd = do
   i <- gets input
   return $! B.null i
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -10,17 +10,11 @@
 and other improvements.
 
 Please report bugs via the
-[bitbucket issue tracker](http://bitbucket.org/bos/attoparsec/issues).
-
-Master [Mercurial repository](http://bitbucket.org/bos/attoparsec):
-
-* `hg clone http://bitbucket.org/bos/attoparsec`
+[github issue tracker](https://github.com/bos/attoparsec/issues).
 
-There's also a [git mirror](http://github.com/bos/attoparsec):
+Master [git repository](https://github.com/bos/attoparsec):
 
 * `git clone git://github.com/bos/attoparsec.git`
-
-(You can create and contribute changes using either Mercurial or git.)
 
 Authors
 -------
diff --git a/attoparsec.cabal b/attoparsec.cabal
--- a/attoparsec.cabal
+++ b/attoparsec.cabal
@@ -1,16 +1,16 @@
 name:            attoparsec
-version:         0.8.6.1
+version:         0.14.4
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
 author:          Bryan O'Sullivan <bos@serpentine.com>
-maintainer:      Bryan O'Sullivan <bos@serpentine.com>
+maintainer:      Bryan O'Sullivan <bos@serpentine.com>, Ben Gamari <ben@smart-cactus.org>
 stability:       experimental
-tested-with:     GHC == 6.10.4, GHC == 6.12.3, GHC == 7.0.3
-synopsis:        Fast combinator parsing for bytestrings
-cabal-version:   >= 1.6
-homepage:        https://bitbucket.org/bos/attoparsec
-bug-reports:     https://bitbucket.org/bos/attoparsec/issues
+tested-with:     GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.7, GHC ==9.0.2, GHC ==9.2.1
+synopsis:        Fast combinator parsing for bytestrings and text
+cabal-version:   2.0
+homepage:        https://github.com/bgamari/attoparsec
+bug-reports:     https://github.com/bgamari/attoparsec/issues
 build-type:      Simple
 description:
     A fast parser combinator library, aimed particularly at dealing
@@ -18,61 +18,180 @@
     file formats.
 extra-source-files:
     README.markdown
+    benchmarks/*.txt
+    benchmarks/json-data/*.json
     benchmarks/Makefile
-    benchmarks/Tiny.hs
     benchmarks/med.txt.bz2
-    tests/Makefile
-    tests/QC.hs
-    tests/QCSupport.hs
-    tests/TestFastSet.hs
+    changelog.md
+    examples/*.c
+    examples/*.hs
     examples/Makefile
-    examples/Parsec_RFC2616.hs
-    examples/RFC2616.hs
-    examples/TestRFC2616.hs
-    examples/rfc2616.c
 
 Flag developer
   Description: Whether to build the library in development mode
   Default: False
+  Manual: True
 
-flag split-base
-flag applicative-in-base
+-- We need to test and benchmark these modules,
+-- but do not want to expose them to end users
+library attoparsec-internal
+  hs-source-dirs: internal
+  build-depends: array,
+                 base >= 4.3 && < 5,
+                 bytestring <0.12,
+                 text >= 1.1.1.3
+  if !impl(ghc >= 8.0)
+    build-depends: semigroups >=0.16.1 && <0.21
+  exposed-modules: Data.Attoparsec.ByteString.Buffer
+                   Data.Attoparsec.ByteString.FastSet
+                   Data.Attoparsec.Internal.Compat
+                   Data.Attoparsec.Internal.Fhthagn
+                   Data.Attoparsec.Text.Buffer
+                   Data.Attoparsec.Text.FastSet
+  ghc-options: -O2 -Wall
+  default-language: Haskell2010
 
 library
-  if flag(split-base)
-    -- bytestring was in base-2.0 and 2.1.1
-    build-depends: base >= 2.0 && < 2.2
-  else
-    -- in base 1.0 and >= 3.0 bytestring is a separate package
-    build-depends: base < 2.0 || >= 3, bytestring >= 0.9, containers >= 0.1.0.1
-
-  if flag(applicative-in-base)
-    build-depends: base >= 2.0 && < 5.0
-    cpp-options: -DAPPLICATIVE_IN_BASE
-  else
-    build-depends: base < 2.0
+  build-depends: array,
+                 base >= 4.3 && < 5,
+                 bytestring <0.12,
+                 containers,
+                 deepseq,
+                 scientific >= 0.3.1 && < 0.4,
+                 transformers >= 0.2 && (< 0.4 || >= 0.4.1.0) && < 0.7,
+                 text >= 1.1.1.3,
+                 ghc-prim <0.9,
+                 attoparsec-internal
+  if impl(ghc < 7.4)
+    build-depends:
+      bytestring < 0.10.4.0
 
-  build-depends: deepseq
+  if !impl(ghc >= 8.0)
+    -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
+    build-depends: fail == 4.9.*,
+                   semigroups >=0.16.1 && <0.21
 
-  extensions:      CPP
   exposed-modules: Data.Attoparsec
+                   Data.Attoparsec.ByteString
+                   Data.Attoparsec.ByteString.Char8
+                   Data.Attoparsec.ByteString.Lazy
                    Data.Attoparsec.Char8
                    Data.Attoparsec.Combinator
-                   Data.Attoparsec.FastSet
+                   Data.Attoparsec.Internal
+                   Data.Attoparsec.Internal.Types
                    Data.Attoparsec.Lazy
                    Data.Attoparsec.Number
+                   Data.Attoparsec.Text
+                   Data.Attoparsec.Text.Lazy
+                   Data.Attoparsec.Types
                    Data.Attoparsec.Zepto
-  other-modules:   Data.Attoparsec.Internal
-                   Data.Attoparsec.Internal.Types
-  ghc-options:     -Wall
+  other-modules:   Data.Attoparsec.ByteString.Internal
+                   Data.Attoparsec.Text.Internal
+  ghc-options: -O2 -Wall
 
+  default-language: Haskell2010
+
   if flag(developer)
     ghc-prof-options: -auto-all
+    ghc-options: -Werror
 
-source-repository head
-  type:     mercurial
-  location: https://bitbucket.org/bos/attoparsec
+test-suite attoparsec-tests
+  type:           exitcode-stdio-1.0
+  hs-source-dirs: tests
+  main-is:        QC.hs
+  other-modules:  QC.Buffer
+                  QC.ByteString
+                  QC.Combinator
+                  QC.Common
+                  QC.IPv6.Internal
+                  QC.IPv6.Types
+                  QC.Rechunked
+                  QC.Simple
+                  QC.Text
+                  QC.Text.FastSet
+                  QC.Text.Regressions
 
+  ghc-options:
+    -Wall -threaded -rtsopts
+
+  if flag(developer)
+    ghc-options: -Werror
+
+  build-depends:
+    array,
+    attoparsec,
+    attoparsec-internal,
+    base,
+    bytestring,
+    deepseq >= 1.1,
+    QuickCheck >= 2.13.2 && < 2.15,
+    quickcheck-unicode,
+    scientific,
+    tasty >= 0.11,
+    tasty-quickcheck >= 0.8,
+    text,
+    transformers,
+    vector
+
+  default-language: Haskell2010
+
+  if !impl(ghc >= 8.0)
+    -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
+    build-depends: fail == 4.9.*,
+                   semigroups >=0.16.1 && <0.19
+
+benchmark attoparsec-benchmarks
+  type: exitcode-stdio-1.0
+  hs-source-dirs: benchmarks benchmarks/warp-3.0.1.1
+  ghc-options: -O2 -Wall -rtsopts
+  main-is: Benchmarks.hs
+  other-modules:
+    Aeson
+    Common
+    Genome
+    HeadersByteString
+    HeadersByteString.Atto
+    HeadersText
+    Links
+    Network.Wai.Handler.Warp.ReadInt
+    Network.Wai.Handler.Warp.RequestHeader
+    Numbers
+    Sets
+    TextFastSet
+    Warp
+  ghc-options: -O2 -Wall
+
+  if flag(developer)
+    ghc-options: -Werror
+
+  build-depends:
+    array,
+    attoparsec,
+    attoparsec-internal,
+    base == 4.*,
+    bytestring >= 0.10.4.0,
+    case-insensitive,
+    containers,
+    deepseq >= 1.1,
+    directory,
+    filepath,
+    ghc-prim,
+    http-types,
+    parsec >= 3.1.2,
+    scientific,
+    tasty-bench >= 0.3,
+    text >= 1.1.1.0,
+    transformers,
+    unordered-containers,
+    vector
+
+  default-language: Haskell2010
+
+  if !impl(ghc >= 8.0)
+    -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
+    build-depends: fail == 4.9.*,
+                   semigroups >=0.16.1 && <0.19
+
 source-repository head
   type:     git
-  location: https://github.com/bos/attoparsec
+  location: https://github.com/bgamari/attoparsec
diff --git a/benchmarks/Aeson.hs b/benchmarks/Aeson.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Aeson.hs
@@ -0,0 +1,353 @@
+{-# LANGUAGE BangPatterns, CPP, OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-unused-binds #-}
+
+module Aeson
+    (
+      aeson
+    , value'
+    ) where
+
+import Data.ByteString.Builder
+  (Builder, byteString, toLazyByteString, charUtf8, word8)
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((*>), (<$>), (<*), pure)
+import Data.Monoid (mappend, mempty)
+#endif
+
+import Common (pathTo)
+import Control.Applicative (liftA2)
+import Control.DeepSeq (NFData(..))
+import Control.Monad (forM)
+import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific,
+                                         skipSpace, string)
+import Data.Bits ((.|.), shiftL)
+import Data.ByteString (ByteString)
+import Data.Char (chr)
+import Data.List (sort)
+import Data.Scientific (Scientific)
+import Data.Text (Text)
+import Data.Text.Encoding (decodeUtf8')
+import Data.Vector as Vector (Vector, foldl', fromList)
+import Data.Word (Word8)
+import System.Directory (getDirectoryContents)
+import System.FilePath ((</>), dropExtension)
+import qualified Data.Attoparsec.ByteString as A
+import qualified Data.Attoparsec.Lazy as L
+import qualified Data.Attoparsec.Zepto as Z
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString.Unsafe as B
+import qualified Data.HashMap.Strict as H
+import Test.Tasty.Bench
+
+#define BACKSLASH 92
+#define CLOSE_CURLY 125
+#define CLOSE_SQUARE 93
+#define COMMA 44
+#define DOUBLE_QUOTE 34
+#define OPEN_CURLY 123
+#define OPEN_SQUARE 91
+#define C_0 48
+#define C_9 57
+#define C_A 65
+#define C_F 70
+#define C_a 97
+#define C_f 102
+#define C_n 110
+#define C_t 116
+
+data Result a = Error String
+              | Success a
+                deriving (Eq, Show)
+
+
+-- | A JSON \"object\" (key\/value map).
+type Object = H.HashMap Text Value
+
+-- | A JSON \"array\" (sequence).
+type Array = Vector Value
+
+-- | A JSON value represented as a Haskell value.
+data Value = Object !Object
+           | Array !Array
+           | String !Text
+           | Number !Scientific
+           | Bool !Bool
+           | Null
+             deriving (Eq, Show)
+
+instance NFData Value where
+    rnf (Object o) = rnf o
+    rnf (Array a)  = Vector.foldl' (\x y -> rnf y `seq` x) () a
+    rnf (String s) = rnf s
+    rnf (Number n) = rnf n
+    rnf (Bool b)   = rnf b
+    rnf Null       = ()
+
+-- | Parse a top-level JSON value.  This must be either an object or
+-- an array, per RFC 4627.
+--
+-- The conversion of a parsed value to a Haskell value is deferred
+-- until the Haskell value is needed.  This may improve performance if
+-- only a subset of the results of conversions are needed, but at a
+-- cost in thunk allocation.
+json :: Parser Value
+json = json_ object_ array_
+
+-- | Parse a top-level JSON value.  This must be either an object or
+-- an array, per RFC 4627.
+--
+-- This is a strict version of 'json' which avoids building up thunks
+-- during parsing; it performs all conversions immediately.  Prefer
+-- this version if most of the JSON data needs to be accessed.
+json' :: Parser Value
+json' = json_ object_' array_'
+
+json_ :: Parser Value -> Parser Value -> Parser Value
+json_ obj ary = do
+  w <- skipSpace *> A.satisfy (\w -> w == OPEN_CURLY || w == OPEN_SQUARE)
+  if w == OPEN_CURLY
+    then obj
+    else ary
+{-# INLINE json_ #-}
+
+object_ :: Parser Value
+object_ = {-# SCC "object_" #-} Object <$> objectValues jstring value
+
+object_' :: Parser Value
+object_' = {-# SCC "object_'" #-} do
+  !vals <- objectValues jstring' value'
+  return (Object vals)
+ where
+  jstring' = do
+    !s <- jstring
+    return s
+
+objectValues :: Parser Text -> Parser Value -> Parser (H.HashMap Text Value)
+objectValues str val = do
+  skipSpace
+  let pair = liftA2 (,) (str <* skipSpace) (char ':' *> skipSpace *> val)
+  H.fromList <$> commaSeparated pair CLOSE_CURLY
+{-# INLINE objectValues #-}
+
+array_ :: Parser Value
+array_ = {-# SCC "array_" #-} Array <$> arrayValues value
+
+array_' :: Parser Value
+array_' = {-# SCC "array_'" #-} do
+  !vals <- arrayValues value'
+  return (Array vals)
+
+commaSeparated :: Parser a -> Word8 -> Parser [a]
+commaSeparated item endByte = do
+  w <- A.peekWord8'
+  if w == endByte
+    then A.anyWord8 >> return []
+    else loop
+  where
+    loop = do
+      v <- item <* skipSpace
+      ch <- A.satisfy $ \w -> w == COMMA || w == endByte
+      if ch == COMMA
+        then skipSpace >> (v:) <$> loop
+        else return [v]
+{-# INLINE commaSeparated #-}
+
+arrayValues :: Parser Value -> Parser (Vector Value)
+arrayValues val = do
+  skipSpace
+  Vector.fromList <$> commaSeparated val CLOSE_SQUARE
+{-# INLINE arrayValues #-}
+
+-- | Parse any JSON value.  You should usually 'json' in preference to
+-- this function, as this function relaxes the object-or-array
+-- requirement of RFC 4627.
+--
+-- In particular, be careful in using this function if you think your
+-- code might interoperate with Javascript.  A na&#xef;ve Javascript
+-- library that parses JSON data using @eval@ is vulnerable to attack
+-- unless the encoded data represents an object or an array.  JSON
+-- implementations in other languages conform to that same restriction
+-- to preserve interoperability and security.
+value :: Parser Value
+value = do
+  w <- A.peekWord8'
+  case w of
+    DOUBLE_QUOTE  -> A.anyWord8 *> (String <$> jstring_)
+    OPEN_CURLY    -> A.anyWord8 *> object_
+    OPEN_SQUARE   -> A.anyWord8 *> array_
+    C_f           -> string "false" *> pure (Bool False)
+    C_t           -> string "true" *> pure (Bool True)
+    C_n           -> string "null" *> pure Null
+    _              | w >= 48 && w <= 57 || w == 45
+                  -> Number <$> scientific
+      | otherwise -> fail "not a valid json value"
+
+-- | Strict version of 'value'. See also 'json''.
+value' :: Parser Value
+value' = do
+  w <- A.peekWord8'
+  case w of
+    DOUBLE_QUOTE  -> do
+                     !s <- A.anyWord8 *> jstring_
+                     return (String s)
+    OPEN_CURLY    -> A.anyWord8 *> object_'
+    OPEN_SQUARE   -> A.anyWord8 *> array_'
+    C_f           -> string "false" *> pure (Bool False)
+    C_t           -> string "true" *> pure (Bool True)
+    C_n           -> string "null" *> pure Null
+    _              | w >= 48 && w <= 57 || w == 45
+                  -> do
+                     !n <- scientific
+                     return (Number n)
+      | otherwise -> fail "not a valid json value"
+
+-- | Parse a quoted JSON string.
+jstring :: Parser Text
+jstring = A.word8 DOUBLE_QUOTE *> jstring_
+
+-- | Parse a string without a leading quote.
+jstring_ :: Parser Text
+jstring_ = {-# SCC "jstring_" #-} do
+  s <- A.scan False $ \s c -> if s then Just False
+                                   else if c == DOUBLE_QUOTE
+                                        then Nothing
+                                        else Just (c == BACKSLASH)
+  _ <- A.word8 DOUBLE_QUOTE
+  s1 <- if BACKSLASH `B.elem` s
+        then case Z.parse unescape s of
+            Right r  -> return r
+            Left err -> fail err
+         else return s
+
+  case decodeUtf8' s1 of
+      Right r  -> return r
+      Left err -> fail $ show err
+
+{-# INLINE jstring_ #-}
+
+unescape :: Z.Parser ByteString
+unescape = toByteString <$> go mempty where
+  go acc = do
+    h <- Z.takeWhile (/=BACKSLASH)
+    let rest = do
+          start <- Z.take 2
+          let !slash = B.unsafeHead start
+              !t = B.unsafeIndex start 1
+              escape = case B.findIndex (==t) "\"\\/ntbrfu" of
+                         Just i -> i
+                         _      -> 255
+          if slash /= BACKSLASH || escape == 255
+            then fail "invalid JSON escape sequence"
+            else do
+            let cont m = go (acc `mappend` byteString h `mappend` m)
+                {-# INLINE cont #-}
+            if t /= 117 -- 'u'
+              then cont (word8 (B.unsafeIndex mapping escape))
+              else do
+                   a <- hexQuad
+                   if a < 0xd800 || a > 0xdfff
+                     then cont (charUtf8 (chr a))
+                     else do
+                       b <- Z.string "\\u" *> hexQuad
+                       if a <= 0xdbff && b >= 0xdc00 && b <= 0xdfff
+                         then let !c = ((a - 0xd800) `shiftL` 10) +
+                                       (b - 0xdc00) + 0x10000
+                              in cont (charUtf8 (chr c))
+                         else fail "invalid UTF-16 surrogates"
+    done <- Z.atEnd
+    if done
+      then return (acc `mappend` byteString h)
+      else rest
+  mapping = "\"\\/\n\t\b\r\f"
+
+hexQuad :: Z.Parser Int
+hexQuad = do
+  s <- Z.take 4
+  let hex n | w >= C_0 && w <= C_9 = w - C_0
+            | w >= C_a && w <= C_f = w - 87
+            | w >= C_A && w <= C_F = w - 55
+            | otherwise          = 255
+        where w = fromIntegral $ B.unsafeIndex s n
+      a = hex 0; b = hex 1; c = hex 2; d = hex 3
+  if (a .|. b .|. c .|. d) /= 255
+    then return $! d .|. (c `shiftL` 4) .|. (b `shiftL` 8) .|. (a `shiftL` 12)
+    else fail "invalid hex escape"
+
+decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
+decodeWith p to s =
+    case L.parse p s of
+      L.Done _ v -> case to v of
+                      Success a -> Just a
+                      _         -> Nothing
+      _          -> Nothing
+{-# INLINE decodeWith #-}
+
+decodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString
+                 -> Maybe a
+decodeStrictWith p to s =
+    case either Error to (A.parseOnly p s) of
+      Success a -> Just a
+      Error _ -> Nothing
+{-# INLINE decodeStrictWith #-}
+
+eitherDecodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString
+                 -> Either String a
+eitherDecodeWith p to s =
+    case L.parse p s of
+      L.Done _ v -> case to v of
+                      Success a -> Right a
+                      Error msg -> Left msg
+      L.Fail _ _ msg -> Left msg
+{-# INLINE eitherDecodeWith #-}
+
+eitherDecodeStrictWith :: Parser Value -> (Value -> Result a) -> B.ByteString
+                       -> Either String a
+eitherDecodeStrictWith p to s =
+    case either Error to (A.parseOnly p s) of
+      Success a -> Right a
+      Error msg -> Left msg
+{-# INLINE eitherDecodeStrictWith #-}
+
+-- $lazy
+--
+-- The 'json' and 'value' parsers decouple identification from
+-- conversion.  Identification occurs immediately (so that an invalid
+-- JSON document can be rejected as early as possible), but conversion
+-- to a Haskell value is deferred until that value is needed.
+--
+-- This decoupling can be time-efficient if only a smallish subset of
+-- elements in a JSON value need to be inspected, since the cost of
+-- conversion is zero for uninspected elements.  The trade off is an
+-- increase in memory usage, due to allocation of thunks for values
+-- that have not yet been converted.
+
+-- $strict
+--
+-- The 'json'' and 'value'' parsers combine identification with
+-- conversion.  They consume more CPU cycles up front, but have a
+-- smaller memory footprint.
+
+-- | Parse a top-level JSON value followed by optional whitespace and
+-- end-of-input.  See also: 'json'.
+jsonEOF :: Parser Value
+jsonEOF = json <* skipSpace <* endOfInput
+
+-- | Parse a top-level JSON value followed by optional whitespace and
+-- end-of-input.  See also: 'json''.
+jsonEOF' :: Parser Value
+jsonEOF' = json' <* skipSpace <* endOfInput
+
+toByteString :: Builder -> ByteString
+toByteString = L.toStrict . toLazyByteString
+{-# INLINE toByteString #-}
+
+aeson :: IO Benchmark
+aeson = do
+  path <- pathTo "json-data"
+  names <- sort . filter (`notElem` [".", ".."]) <$> getDirectoryContents path
+  benches <- forM names $ \name -> do
+    bs <- B.readFile (path </> name)
+    return . bench (dropExtension name) $ nf (A.parseOnly jsonEOF') bs
+  return $ bgroup "aeson" benches
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Benchmarks.hs
@@ -0,0 +1,126 @@
+{-# LANGUAGE BangPatterns, CPP #-}
+
+import Common ()
+import Control.Applicative (many)
+import Test.Tasty.Bench (bench, bgroup, defaultMain, nf)
+import Data.Bits
+import Data.Char (isAlpha)
+import Data.Word (Word32)
+import Data.Word (Word8)
+import Numbers (numbers)
+import Common (chunksOf)
+import Text.Parsec.Text ()
+import Text.Parsec.Text.Lazy ()
+import qualified Warp
+import qualified Aeson
+import qualified Genome
+import qualified Data.Attoparsec.ByteString as AB
+import qualified Data.Attoparsec.ByteString.Char8 as AC
+import qualified Data.Attoparsec.ByteString.Lazy as ABL
+import qualified Data.Attoparsec.Text as AT
+import qualified Data.Attoparsec.Text.Lazy as ATL
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified HeadersByteString
+import qualified HeadersText
+import qualified Links
+import qualified Text.Parsec as P
+import qualified Sets
+
+main :: IO ()
+main = do
+  let s  = take 1024 . cycle $ ['a'..'z'] ++ ['A'..'Z']
+      !b = BC.pack s
+      !bl = BL.fromChunks . map BC.pack . chunksOf 4 $ s
+      !t = T.pack s
+      !tl = TL.fromChunks . map T.pack . chunksOf 4 $ s
+  aeson <- Aeson.aeson
+  headersBS <- HeadersByteString.headers
+  headersT <- HeadersText.headers
+  defaultMain [
+     bgroup "many" [
+       bgroup "attoparsec" [
+         bench "B" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b
+       , bench "BL" $ nf (ABL.parse (many (AC.satisfy AC.isAlpha_ascii))) bl
+       , bench "T" $ nf (AT.parse (many (AT.satisfy AC.isAlpha_ascii))) t
+       , bench "TL" $ nf (ATL.parse (many (AT.satisfy AC.isAlpha_ascii))) tl
+       ]
+     , bgroup "parsec" [
+         bench "S" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") s
+       , bench "B" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") b
+       , bench "BL" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") bl
+       , bench "T" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") t
+       , bench "TL" $ nf (P.parse (many (P.satisfy AC.isAlpha_ascii)) "") tl
+       ]
+     ]
+   , bgroup "comparison" [
+       bgroup "many-vs-takeWhile" [
+         bench "many" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b
+       , bench "takeWhile" $ nf (AB.parse (AC.takeWhile AC.isAlpha_ascii)) b
+       ]
+     , bgroup "letter-vs-isAlpha" [
+         bench "letter" $ nf (AB.parse (many AC.letter_ascii)) b
+       , bench "isAlpha" $ nf (AB.parse (many (AC.satisfy AC.isAlpha_ascii))) b
+       ]
+     ]
+   , bgroup "takeWhile" [
+       bench "isAlpha" $ nf (ABL.parse (AC.takeWhile isAlpha)) bl
+     , bench "isAlpha_ascii" $ nf (ABL.parse (AC.takeWhile AC.isAlpha_ascii)) bl
+     , bench "isAlpha_iso8859_15" $
+       nf (ABL.parse (AC.takeWhile AC.isAlpha_iso8859_15)) bl
+     , bench "T isAlpha" $ nf (AT.parse (AT.takeWhile isAlpha)) t
+     , bench "TL isAlpha" $ nf (ATL.parse (AT.takeWhile isAlpha)) tl
+     ]
+   , bgroup "takeWhile1" [
+       bench "isAlpha" $ nf (ABL.parse (AC.takeWhile1 isAlpha)) bl
+     , bench "isAlpha_ascii" $ nf (ABL.parse (AC.takeWhile1 AC.isAlpha_ascii)) bl
+     , bench "T isAlpha" $ nf (AT.parse (AT.takeWhile1 isAlpha)) t
+     , bench "TL isAlpha" $ nf (ATL.parse (AT.takeWhile1 isAlpha)) tl
+     ]
+   , bench "word32LE" $ nf (AB.parse word32LE) b
+   , bgroup "scan" [
+       bench "short" $ nf (AB.parse quotedString) (BC.pack "abcdefghijk\"")
+     , bench "long" $ nf (AB.parse quotedString) b
+     ]
+   , aeson
+   , Genome.genome
+   , headersBS
+   , headersT
+   , Links.links
+   , numbers
+   , Sets.benchmarks
+   , Warp.benchmarks
+   ]
+
+-- Benchmarks bind and (potential) bounds-check merging.
+word32LE :: AB.Parser Word32
+word32LE = do
+    w1 <- AB.anyWord8
+    w2 <- AB.anyWord8
+    w3 <- AB.anyWord8
+    w4 <- AB.anyWord8
+    return $! (fromIntegral w1 :: Word32) +
+        fromIntegral w2 `unsafeShiftL` 8 +
+        fromIntegral w3 `unsafeShiftL` 16 +
+        fromIntegral w4 `unsafeShiftL` 32
+
+doubleQuote, backslash :: Word8
+doubleQuote = 34
+backslash = 92
+{-# INLINE backslash #-}
+{-# INLINE doubleQuote #-}
+
+-- | Parse a string without a leading quote.
+quotedString :: AB.Parser B.ByteString
+quotedString = AB.scan False $ \s c -> if s then Just False
+                                       else if c == doubleQuote
+                                            then Nothing
+                                            else Just (c == backslash)
+
+#if !MIN_VERSION_base(4,5,0)
+unsafeShiftL :: Bits a => a -> Int -> a
+unsafeShiftL = shiftL
+#endif
diff --git a/benchmarks/Common.hs b/benchmarks/Common.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Common.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE CPP #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Common (
+      chunksOf
+    , pathTo
+    , rechunkBS
+    , rechunkT
+    ) where
+
+import Control.DeepSeq (NFData(rnf))
+import System.Directory (doesDirectoryExist)
+import System.FilePath ((</>))
+import Text.Parsec (ParseError)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+
+#if !MIN_VERSION_bytestring(0,10,0)
+import Data.ByteString.Internal (ByteString(..))
+
+instance NFData ByteString where
+    rnf (PS _ _ _) = ()
+#endif
+
+instance NFData ParseError where
+    rnf = rnf . show
+
+chunksOf :: Int -> [a] -> [[a]]
+chunksOf k = go
+  where go xs = case splitAt k xs of
+                  ([],_)  -> []
+                  (y, ys) -> y : go ys
+
+rechunkBS :: Int -> B.ByteString -> BL.ByteString
+rechunkBS n = BL.fromChunks . map B.pack . chunksOf n . B.unpack
+
+rechunkT :: Int -> T.Text -> TL.Text
+rechunkT n = TL.fromChunks . map T.pack . chunksOf n . T.unpack
+
+pathTo :: String -> IO FilePath
+pathTo wat = do
+  exists <- doesDirectoryExist "benchmarks"
+  return $ if exists
+           then "benchmarks" </> wat
+           else wat
diff --git a/benchmarks/Genome.hs b/benchmarks/Genome.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Genome.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Genome
+    (
+      genome
+    ) where
+
+import Control.Applicative
+import Test.Tasty.Bench
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as B8
+import qualified Data.ByteString.Lazy.Char8 as L8
+import Data.Attoparsec.ByteString.Char8 as B
+import qualified Data.Attoparsec.ByteString.Lazy as BL
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import Data.Attoparsec.Text as T
+import qualified Data.Attoparsec.Text.Lazy as TL
+import Common (rechunkBS, rechunkT)
+
+genome :: Benchmark
+genome = bgroup "genome" [
+    bgroup "bytestring" [
+        bench "s" $ nf (map (B.parse searchBS)) (B8.tails geneB)
+      , bench "l" $ nf (map (BL.parse searchBS)) (L8.tails geneBL)
+      , bgroup "CI" [
+          bench "s" $ nf (map (B.parse searchBSCI)) (B8.tails geneB)
+        , bench "l" $ nf (map (BL.parse searchBSCI)) (L8.tails geneBL)
+      ]
+    ]
+  , bgroup "text" [
+        bench "s" $ nf (map (T.parse searchT)) (T.tails geneT)
+      , bench "l" $ nf (map (TL.parse searchT)) (TL.tails geneTL)
+      , bgroup "CI" [
+          bench "s" $ nf (map (T.parse searchTCI)) (T.tails geneT)
+        , bench "l" $ nf (map (TL.parse searchTCI)) (TL.tails geneTL)
+      ]
+    ]
+  ]
+  where geneB  = B8.pack gene
+        geneBL = rechunkBS 4 geneB
+        geneT  = T.pack gene
+        geneTL = rechunkT 4 geneT
+
+searchBS :: B.Parser ByteString
+searchBS = "caac" *> ("aaca" <|> "aact")
+
+searchBSCI :: B.Parser ByteString
+searchBSCI = B.stringCI "CAAC" *> (B.stringCI "AACA" <|> B.stringCI "AACT")
+
+searchT :: T.Parser Text
+searchT = "caac" *> ("aaca" <|> "aact")
+
+searchTCI :: T.Parser Text
+searchTCI = T.asciiCI "CAAC" *> (T.asciiCI "AACA" <|> T.asciiCI "AACT")
+
+-- Dictyostelium discoideum developmental protein DG1094 (gacT) gene,
+-- partial cds. http://www.ncbi.nlm.nih.gov/nuccore/AF081586.1
+
+gene :: String
+gene = "atcgatttagaaagatacaaagatagaaccatcaataataaacaagagaagagagcaagt\
+       \agagatattaataaagagattgaaagagagattgaaaagaagagattatcaccaagagaa\
+       \agattaaatttatttggtctttcttcctcatcttcatcagtgaattcaacattaacaaga\
+       \tctacagcaaatattatctctacaatagacggtagtggaggtagtaatcgtaatagtaaa\
+       \aattatggtaatggctcatcctcctcctcaaatagaagatatagtaatactattaatcaa\
+       \caattacaaatgcaattacaacaacttcaaatccaacaacaacaatatcaacaaactcaa\
+       \caatctcaaataccattacaatatcaacaacaacaacagcaacaacaacaacaaaccact\
+       \acaactacaactacatcaagtggtagtaatagattctcttcaaatagatataaaccagtt\
+       \gatcttacacaatcatcttcaaactttcgttattcacgtgaaatttatgatgatgattat\
+       \tattcaaataataatttaatgatgtttggtaatgagcaaccaaatcaaacaccaatttct\
+       \gtatcatcttcatctgcattcacacgtcaaagatctcaaagttgctttgaaccagagaat\
+       \cttgtattgctacaacaacaatatcaacaatatcaacaacaacaacaacaacaacaacaa\
+       \attccattccaagcaaatccacaatatagtaatgctgttattgaacaaaaattggatcaa\
+       \attagagataccattaataatttacatagagataaccgagtctctaga"
diff --git a/benchmarks/HeadersByteString.hs b/benchmarks/HeadersByteString.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/HeadersByteString.hs
@@ -0,0 +1,36 @@
+module HeadersByteString (headers) where
+
+import Common (pathTo, rechunkBS)
+import Test.Tasty.Bench (Benchmark, bench, bgroup, nf, nfIO)
+import HeadersByteString.Atto (request, response)
+import Network.Wai.Handler.Warp.RequestHeader (parseHeaderLines)
+import qualified Data.Attoparsec.ByteString.Char8 as B
+import qualified Data.Attoparsec.ByteString.Lazy as BL
+import qualified Data.ByteString.Char8 as B
+
+-- Note: In the benchmarks for parsing an http request
+-- from a strict bytestring, we consider warp's implementation,
+-- which has highly optimized code for handling the first
+-- line in particular. It's treatment of the headers
+-- is more relaxed from the treatment they are given by the
+-- attoparsec parser benchmarked here. Consequently, it
+-- is should not be possible to match its performance since
+-- it accepts header names with disallowed characters.
+
+headers :: IO Benchmark
+headers = do
+  req <- B.readFile =<< pathTo "http-request.txt"
+  resp <- B.readFile =<< pathTo "http-response.txt"
+  let reql    = rechunkBS 4 req
+      respl   = rechunkBS 4 resp
+  return $ bgroup "headers" [
+      bgroup "B" [
+        bench "request" $ nf (B.parseOnly request) req
+      , bench "warp" $ nfIO (parseHeaderLines (B.split '\n' req))
+      , bench "response" $ nf (B.parseOnly response) resp
+      ]
+    , bgroup "BL" [
+        bench "request" $ nf (BL.parse request) reql
+      , bench "response" $ nf (BL.parse response) respl
+      ]
+    ]
diff --git a/benchmarks/HeadersByteString/Atto.hs b/benchmarks/HeadersByteString/Atto.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/HeadersByteString/Atto.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-orphans #-}
+module HeadersByteString.Atto
+    (
+      request
+    , response
+    ) where
+
+import Control.Applicative
+import Control.DeepSeq (NFData(..))
+import Network.HTTP.Types.Version (HttpVersion, http11)
+import qualified Data.Attoparsec.ByteString.Char8 as B
+import qualified Data.ByteString.Char8 as B
+
+instance NFData HttpVersion where
+    rnf !_ = ()
+
+isHeaderChar :: Char -> Bool
+isHeaderChar c =
+  (c >= 'a' && c <= 'z') ||
+  (c >= 'A' && c <= 'Z') ||
+  (c >= '0' && c <= '9') ||
+  (c == '_') ||
+  (c == '-')
+
+header = do
+  name <- B.takeWhile1 isHeaderChar <* B.char ':' <* B.skipSpace
+  body <- bodyLine
+  return (name, body)
+
+bodyLine = B.takeTill (\c -> c == '\r' || c == '\n') <* B.endOfLine
+
+requestLine = do
+  m <- (B.takeTill B.isSpace <* B.char ' ')
+  (p,q) <- B.break (=='?') <$> (B.takeTill B.isSpace <* B.char ' ')
+  v <- httpVersion
+  return (m,p,q,v)
+
+httpVersion = http11 <$ "HTTP/1.1"
+
+responseLine = (,,) <$>
+               (httpVersion <* B.skipSpace) <*>
+               (int <* B.skipSpace) <*>
+               bodyLine
+
+int :: B.Parser Int
+int = B.decimal
+
+request = (,) <$> (requestLine <* B.endOfLine) <*> manyheader
+
+response = (,) <$> responseLine <*> many header
+
+manyheader = do
+  c <- B.peekChar'
+  if c == '\r' || c == '\n'
+    then return []
+    else (:) <$> header <*> manyheader
diff --git a/benchmarks/HeadersText.hs b/benchmarks/HeadersText.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/HeadersText.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+module HeadersText (headers) where
+
+import Common (pathTo, rechunkT)
+import Control.Applicative
+import Test.Tasty.Bench (Benchmark, bench, bgroup, nf)
+import Data.Char (isSpace)
+import qualified Data.Attoparsec.Text as T
+import qualified Data.Attoparsec.Text.Lazy as TL
+import qualified Data.Text.IO as T
+
+header = do
+  name <- T.takeWhile1 (T.inClass "a-zA-Z0-9_-") <* T.char ':' <* T.skipSpace
+  body <- (:) <$> bodyLine <*> many (T.takeWhile1 isSpace *> bodyLine)
+  return (name, body)
+
+bodyLine = T.takeTill (\c -> c == '\r' || c == '\n') <* T.endOfLine
+
+requestLine =
+    (,,) <$>
+    (method <* T.skipSpace) <*>
+    (T.takeTill isSpace <* T.skipSpace) <*>
+    httpVersion
+  where method = "GET" <|> "POST"
+
+httpVersion = "HTTP/" *> ((,) <$> (int <* T.char '.') <*> int)
+
+responseLine = (,,) <$>
+               (httpVersion <* T.skipSpace) <*>
+               (int <* T.skipSpace) <*>
+               bodyLine
+
+int :: T.Parser Int
+int = T.decimal
+
+request = (,) <$> (requestLine <* T.endOfLine) <*> many header
+
+response = (,) <$> responseLine <*> many header
+
+headers :: IO Benchmark
+headers = do
+  req <- T.readFile =<< pathTo "http-request.txt"
+  resp <- T.readFile =<< pathTo "http-response.txt"
+  let reql    = rechunkT 4 req
+      respl   = rechunkT 4 resp
+  return $ bgroup "headers" [
+      bgroup "T" [
+        bench "request" $ nf (T.parseOnly request) req
+      , bench "response" $ nf (T.parseOnly response) resp
+      ]
+    , bgroup "TL" [
+        bench "request" $ nf (TL.parse request) reql
+      , bench "response" $ nf (TL.parse response) respl
+      ]
+    ]
diff --git a/benchmarks/Links.hs b/benchmarks/Links.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Links.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Links (links) where
+
+import Control.Applicative
+import Control.DeepSeq (NFData(..))
+import Test.Tasty.Bench (Benchmark, bench, nf)
+import Data.Attoparsec.ByteString as A
+import Data.Attoparsec.ByteString.Char8 as A8
+import Data.ByteString.Char8 as B8
+
+data Link = Link {
+      linkURL :: ByteString
+    , linkParams :: [(ByteString, ByteString)]
+    } deriving (Eq, Show)
+
+instance NFData Link where
+    rnf l = rnf (linkURL l) `seq` rnf (linkParams l)
+
+link :: Parser Link
+link = Link <$> url <*> many (char8 ';' *> skipSpace *> param)
+  where url = char8 '<' *> A8.takeTill (=='>') <* char8 '>' <* skipSpace
+
+param :: Parser (ByteString, ByteString)
+param = do
+  name <- paramName
+  skipSpace *> "=" *> skipSpace
+  c <- peekChar'
+  let isTokenChar = A.inClass "!#$%&'()*+./0-9:<=>?@a-zA-Z[]^_`{|}~-"
+  val <- case c of
+           '"' -> quotedString
+           _   -> A.takeWhile isTokenChar
+  skipSpace
+  return (name, val)
+
+data Quot = Literal | Backslash
+
+quotedString :: Parser ByteString
+quotedString = char '"' *> (fixup <$> body) <* char '"'
+  where body = A8.scan Literal $ \s c ->
+          case (s,c) of
+            (Literal,  '\\') -> backslash
+            (Literal,  '"')  -> Nothing
+            _                -> literal
+        literal   = Just Literal
+        backslash = Just Backslash
+        fixup = B8.pack . go . B8.unpack
+          where go ('\\' : x@'\\' : xs) = x : go xs
+                go ('\\' : x@'"' : xs)  = x : go xs
+                go (x : xs)             = x : go xs
+                go xs                   = xs
+
+paramName :: Parser ByteString
+paramName = do
+  name <- A.takeWhile1 $ A.inClass "a-zA-Z0-9!#$&+-.^_`|~"
+  c <- peekChar
+  return $ case c of
+             Just '*' -> B8.snoc name '*'
+             _        -> name
+
+links :: Benchmark
+links = bench "links" $ nf (A.parseOnly link) lnk
+  where lnk = "<https://api.github.com/search/code?q=addClass+user%3Amozilla&page=2>; rel=\"next\", <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel=\"last\""
diff --git a/benchmarks/Numbers.hs b/benchmarks/Numbers.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Numbers.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
+
+module Numbers (numbers) where
+
+import Test.Tasty.Bench (Benchmark, bench, bgroup, nf)
+import Data.Scientific (Scientific(..))
+import Text.Parsec.Text ()
+import Text.Parsec.Text.Lazy ()
+import qualified Data.Attoparsec.ByteString.Char8 as AC
+import qualified Data.Attoparsec.Text as AT
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.Text as T
+
+strN, strNePos, strNeNeg :: String
+strN     = "1234.56789"
+strNePos = "1234.56789e3"
+strNeNeg = "1234.56789e-3"
+
+numbers :: Benchmark
+numbers = bgroup "numbers" [
+  let !tN     = T.pack strN
+      !tNePos = T.pack strNePos
+      !tNeNeg = T.pack strNeNeg
+  in bgroup "Text"
+  [
+    bgroup "no power"
+    [ bench "double" $ nf (AT.parseOnly AT.double) tN
+    , bench "number" $ nf (AT.parseOnly AT.number) tN
+    , bench "rational" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Rational)) tN
+    , bench "scientific" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tN
+    ]
+  , bgroup "positive power"
+    [ bench "double" $ nf (AT.parseOnly AT.double) tNePos
+    , bench "number" $ nf (AT.parseOnly AT.number) tNePos
+    , bench "rational" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Rational)) tNePos
+    , bench "scientific" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tNePos
+    ]
+  , bgroup "negative power"
+    [ bench "double" $ nf (AT.parseOnly AT.double) tNeNeg
+    , bench "number" $ nf (AT.parseOnly AT.number) tNeNeg
+    , bench "rational" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Rational))  tNeNeg
+    , bench "scientific" $
+      nf (AT.parseOnly (AT.rational :: AT.Parser Scientific)) tNeNeg
+    ]
+  ]
+  , let !bN     = BC.pack strN
+        !bNePos = BC.pack strNePos
+        !bNeNeg = BC.pack strNeNeg
+  in bgroup "ByteString"
+  [ bgroup "no power"
+    [ bench "double" $ nf (AC.parseOnly AC.double) bN
+    , bench "number" $ nf (AC.parseOnly AC.number) bN
+    , bench "rational" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Rational))   bN
+    , bench "scientific" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bN
+    ]
+  , bgroup "positive power"
+    [ bench "double" $ nf (AC.parseOnly AC.double) bNePos
+    , bench "number" $ nf (AC.parseOnly AC.number) bNePos
+    , bench "rational" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Rational)) bNePos
+    , bench "scientific" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bNePos
+    ]
+  , bgroup "negative power"
+    [ bench "double" $ nf (AC.parseOnly AC.double) bNeNeg
+    , bench "number" $ nf (AC.parseOnly AC.number) bNeNeg
+    , bench "rational" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Rational)) bNeNeg
+    , bench "scientific" $
+      nf (AC.parseOnly (AC.rational :: AC.Parser Scientific)) bNeNeg
+    ]
+  ]
+ ]
diff --git a/benchmarks/Sets.hs b/benchmarks/Sets.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Sets.hs
@@ -0,0 +1,21 @@
+module Sets (benchmarks) where
+
+import Test.Tasty.Bench
+import Data.Char (ord)
+import qualified Data.Attoparsec.Text.FastSet as FastSet
+import qualified TextFastSet
+import qualified Data.HashSet as HashSet
+import qualified Data.IntSet as IntSet
+
+smallSet :: String
+smallSet = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']
+
+benchmarks :: Benchmark
+benchmarks = bgroup "sets" [
+    bench "Fast" $ whnf (FastSet.member '*') (FastSet.fromList smallSet)
+  , bench "Hash" $ whnf (HashSet.member '*') (HashSet.fromList smallSet)
+  , bench "Int" $ whnf (IntSet.member (ord '*'))
+                  (IntSet.fromList (map ord smallSet))
+  , bench "TextFast" $ whnf (TextFastSet.member '*')
+                       (TextFastSet.fromList smallSet)
+  ]
diff --git a/benchmarks/TextFastSet.hs b/benchmarks/TextFastSet.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/TextFastSet.hs
@@ -0,0 +1,121 @@
+{-# LANGUAGE BangPatterns #-}
+
+------------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Attoparsec.FastSet
+-- Copyright   :  Felipe Lessa 2010, Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  felipe.lessa@gmail.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Fast set membership tests for 'Char' values. We test for
+-- membership using a hashtable implemented with Robin Hood
+-- collision resolution. The set representation is unboxed,
+-- and the characters and hashes interleaved, for efficiency.
+--
+--
+-----------------------------------------------------------------------------
+module TextFastSet
+    (
+    -- * Data type
+      FastSet
+    -- * Construction
+    , fromList
+    , set
+    -- * Lookup
+    , member
+    -- * Handy interface
+    , charClass
+    ) where
+
+import Data.Bits ((.|.), (.&.), shiftR)
+import Data.Function (on)
+import Data.List (sort, sortBy)
+import qualified Data.Array.Base as AB
+import qualified Data.Array.Unboxed as A
+import qualified Data.Text as T
+
+data FastSet = FastSet {
+    table :: {-# UNPACK #-} !(A.UArray Int Int)
+  , mask  :: {-# UNPACK #-} !Int
+  }
+
+data Entry = Entry {
+    key          :: {-# UNPACK #-} !Char
+  , initialIndex :: {-# UNPACK #-} !Int
+  , index        :: {-# UNPACK #-} !Int
+  }
+
+offset :: Entry -> Int
+offset e = index e - initialIndex e
+
+resolveCollisions :: [Entry] -> [Entry]
+resolveCollisions [] = []
+resolveCollisions [e] = [e]
+resolveCollisions (a:b:entries) = a' : resolveCollisions (b' : entries)
+  where (a', b')
+          | index a < index b   = (a, b)
+          | offset a < offset b = (b { index=index a }, a { index=index a + 1 })
+          | otherwise           = (a, b { index=index a + 1 })
+
+pad :: Int -> [Entry] -> [Entry]
+pad = go 0
+  where -- ensure that we pad enough so that lookups beyond the
+        -- last hash in the table fall within the array
+        go !_ !m []          = replicate (max 1 m + 1) empty
+        go  k  m (e:entries) = map (const empty) [k..i - 1] ++ e :
+                               go (i + 1) (m + i - k - 1) entries
+          where i            = index e
+        empty                = Entry '\0' maxBound 0
+
+nextPowerOf2 :: Int -> Int
+nextPowerOf2 0  = 1
+nextPowerOf2 x  = go (x - 1) 1
+  where go y 32 = y + 1
+        go y k  = go (y .|. (y `shiftR` k)) $ k * 2
+
+fastHash :: Char -> Int
+fastHash = fromEnum
+
+fromList :: String -> FastSet
+fromList s = FastSet (AB.listArray (0, length interleaved - 1) interleaved)
+             mask'
+  where s'      = ordNub (sort s)
+        l       = length s'
+        mask'   = nextPowerOf2 ((5 * l) `div` 4) - 1
+        entries = pad mask' .
+                  resolveCollisions .
+                  sortBy (compare `on` initialIndex) .
+                  zipWith (\c i -> Entry c i i) s' .
+                  map ((.&. mask') . fastHash) $ s'
+        interleaved = concatMap (\e -> [fromEnum $ key e, initialIndex e])
+                      entries
+
+ordNub :: Eq a => [a] -> [a]
+ordNub []     = []
+ordNub (y:ys) = go y ys
+  where go x (z:zs)
+          | x == z    = go x zs
+          | otherwise = x : go z zs
+        go x []       = [x]
+
+set :: T.Text -> FastSet
+set = fromList . T.unpack
+
+-- | Check the set for membership.
+member :: Char -> FastSet -> Bool
+member c a           = go (2 * i)
+  where i            = fastHash c .&. mask a
+        lookupAt j b = (i' <= i) && (c == c' || b)
+            where c' = toEnum $ AB.unsafeAt (table a) j
+                  i' = AB.unsafeAt (table a) $ j + 1
+        go j         = lookupAt j . lookupAt (j + 2) . lookupAt (j + 4) .
+                       lookupAt (j + 6) . go $ j + 8
+
+charClass :: String -> FastSet
+charClass = fromList . go
+  where go (a:'-':b:xs) = [a..b] ++ go xs
+        go (x:xs)       = x : go xs
+        go _            = ""
diff --git a/benchmarks/Tiny.hs b/benchmarks/Tiny.hs
deleted file mode 100644
--- a/benchmarks/Tiny.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-import Control.Applicative ((<|>))
-import Control.Monad (forM_)
-import System.Environment (getArgs)
-import qualified Data.Attoparsec.Char8 as A
-import qualified Data.ByteString.Char8 as B
-import qualified Text.Parsec as P
-import qualified Text.Parsec.ByteString as P
-
-attoparsec = do
-  args <- getArgs
-  forM_ args $ \arg -> do
-    input <- B.readFile arg
-    case A.parse p input `A.feed` B.empty of
-      A.Done _ xs -> print (length xs)
-      what        -> print what
- where
-  slow = A.many (A.many1 A.letter_ascii <|> A.many1 A.digit)
-  fast = A.many (A.takeWhile1 isLetter <|> A.takeWhile1 isDigit)
-  isDigit c  = c >= '0' && c <= '9'
-  isLetter c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-  p = fast
-
-parsec = do
-  args <- getArgs
-  forM_ args $ \arg -> do
-    input <- readFile arg
-    case P.parse (P.many (P.many1 P.letter P.<|> P.many1 P.digit)) "" input of
-      Left err -> print err
-      Right xs -> print (length xs)
-
-main = attoparsec
diff --git a/benchmarks/Warp.hs b/benchmarks/Warp.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Warp.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Warp (benchmarks) where
+
+import Test.Tasty.Bench (Benchmark, bench, bgroup, nf)
+import Data.ByteString (ByteString)
+import Network.Wai.Handler.Warp.ReadInt (readInt)
+import qualified Data.Attoparsec.ByteString.Char8 as B
+
+benchmarks :: Benchmark
+benchmarks = bgroup "warp" [
+    bgroup "decimal" [
+      bench "warp" $ nf (readInt :: ByteString -> Int) "31337"
+    , bench "atto" $ nf (B.parse (B.decimal :: B.Parser Int)) "31337"
+    ]
+  ]
diff --git a/benchmarks/http-request.txt b/benchmarks/http-request.txt
new file mode 100644
--- /dev/null
+++ b/benchmarks/http-request.txt
@@ -0,0 +1,9 @@
+GET / HTTP/1.1
+Host: twitter.com
+Accept: text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, */*; q=0.8
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
+Cache-Control: max-age=0
+Cookie: guest_id=v1%3A139; _twitter_sess=BAh7CSIKZmxhc2hJQz-e1e1; __utma=43838368.452555194.1399611824.1; __utmb=43838368; __utmc=43838368; __utmz=1399611824.1.1.utmcsr=(direct)|utmcmd=(none)
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86 Safari/537.36
+
diff --git a/benchmarks/http-response.txt b/benchmarks/http-response.txt
new file mode 100644
--- /dev/null
+++ b/benchmarks/http-response.txt
@@ -0,0 +1,14 @@
+HTTP/1.1 200 OK
+Date: Fri, 09 May 2014 04:24:57 GMT
+Expires: -1
+Cache-Control: private, max-age=0
+Content-Type: text/html; charset=ISO-8859-1
+Set-Cookie: PREF=ID=1a871afc4240db5e:FF:LM=1399609497:S=e5MZ0itEekjVwNcU; expires=Sun, 08-May-2016 04:24:57 GMT; path=/; domain=.google.com
+Set-Cookie: NID=67=-WlfaDG6VSEPk7abAjrK98HBSoCD2ID6JKkUR95tEumzDmg7Fc8pSQ8; expires=Sat, 08-Nov-2014 04:24:57 GMT; path=/; domain=.google.com; HttpOnly
+P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
+Server: gws
+X-XSS-Protection: 1; mode=block
+X-Frame-Options: SAMEORIGIN
+Alternate-Protocol: 80:quic
+Transfer-Encoding: chunked
+
diff --git a/benchmarks/json-data/example.json b/benchmarks/json-data/example.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/example.json
@@ -0,0 +1,88 @@
+{"web-app": {
+  "servlet": [   
+    {
+      "servlet-name": "cofaxCDS",
+      "servlet-class": "org.cofax.cds.CDSServlet",
+      "init-param": {
+        "configGlossary:installationAt": "Philadelphia, PA",
+        "configGlossary:adminEmail": "ksm@pobox.com",
+        "configGlossary:poweredBy": "Cofax",
+        "configGlossary:poweredByIcon": "/images/cofax.gif",
+        "configGlossary:staticPath": "/content/static",
+        "templateProcessorClass": "org.cofax.WysiwygTemplate",
+        "templateLoaderClass": "org.cofax.FilesTemplateLoader",
+        "templatePath": "templates",
+        "templateOverridePath": "",
+        "defaultListTemplate": "listTemplate.htm",
+        "defaultFileTemplate": "articleTemplate.htm",
+        "useJSP": false,
+        "jspListTemplate": "listTemplate.jsp",
+        "jspFileTemplate": "articleTemplate.jsp",
+        "cachePackageTagsTrack": 200,
+        "cachePackageTagsStore": 200,
+        "cachePackageTagsRefresh": 60,
+        "cacheTemplatesTrack": 100,
+        "cacheTemplatesStore": 50,
+        "cacheTemplatesRefresh": 15,
+        "cachePagesTrack": 200,
+        "cachePagesStore": 100,
+        "cachePagesRefresh": 10,
+        "cachePagesDirtyRead": 10,
+        "searchEngineListTemplate": "forSearchEnginesList.htm",
+        "searchEngineFileTemplate": "forSearchEngines.htm",
+        "searchEngineRobotsDb": "WEB-INF/robots.db",
+        "useDataStore": true,
+        "dataStoreClass": "org.cofax.SqlDataStore",
+        "redirectionClass": "org.cofax.SqlRedirection",
+        "dataStoreName": "cofax",
+        "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+        "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
+        "dataStoreUser": "sa",
+        "dataStorePassword": "dataStoreTestQuery",
+        "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
+        "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
+        "dataStoreInitConns": 10,
+        "dataStoreMaxConns": 100,
+        "dataStoreConnUsageLimit": 100,
+        "dataStoreLogLevel": "debug",
+        "maxUrlLength": 500}},
+    {
+      "servlet-name": "cofaxEmail",
+      "servlet-class": "org.cofax.cds.EmailServlet",
+      "init-param": {
+      "mailHost": "mail1",
+      "mailHostOverride": "mail2"}},
+    {
+      "servlet-name": "cofaxAdmin",
+      "servlet-class": "org.cofax.cds.AdminServlet"},
+ 
+    {
+      "servlet-name": "fileServlet",
+      "servlet-class": "org.cofax.cds.FileServlet"},
+    {
+      "servlet-name": "cofaxTools",
+      "servlet-class": "org.cofax.cms.CofaxToolsServlet",
+      "init-param": {
+        "templatePath": "toolstemplates/",
+        "log": 1,
+        "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
+        "logMaxSize": "",
+        "dataLog": 1,
+        "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
+        "dataLogMaxSize": "",
+        "removePageCache": "/content/admin/remove?cache=pages&id=",
+        "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
+        "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
+        "lookInContext": 1,
+        "adminGroupID": 4,
+        "betaServer": true}}],
+  "servlet-mapping": {
+    "cofaxCDS": "/",
+    "cofaxEmail": "/cofaxutil/aemail/*",
+    "cofaxAdmin": "/admin/*",
+    "fileServlet": "/static/*",
+    "cofaxTools": "/tools/*"},
+ 
+  "taglib": {
+    "taglib-uri": "cofax.tld",
+    "taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
diff --git a/benchmarks/json-data/geometry.json b/benchmarks/json-data/geometry.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/geometry.json
@@ -0,0 +1,1 @@
+{"geometry": {"type": "Polygon", "coordinates": [[[-0.939359853061118, 51.57401065198471], [-0.939440892477492, 51.57431080772057], [-0.939543636564569, 51.57460846194951], [-0.939564627628489, 51.574822653966265], [-0.939763179055758, 51.575406210178826], [-0.939787182642249, 51.575552991614], [-0.939819571231525, 51.57564949527348], [-0.939851290904264, 51.57571272360808], [-0.939975682132949, 51.57588648747347], [-0.940036822193859, 51.57598774653439], [-0.940072640734852, 51.57606090267849], [-0.940109693338918, 51.576205104339515], [-0.940125502187331, 51.57645611534466], [-0.940118623499009, 51.57662779459441], [-0.94008851367835, 51.57680555827417], [-0.939998015208524, 51.57709787034017], [-0.939928028667517, 51.577252794653916], [-0.939830628174189, 51.57740747134858], [-0.939796941313687, 51.57749078985784], [-0.939785586773343, 51.57754463746666], [-0.939770656147318, 51.57769016804059], [-0.939658154074368, 51.57824573765943], [-0.939485738834128, 51.57883313597966], [-0.93945717030888, 51.579192545519916], [-0.939524336079755, 51.57928306919007], [-0.939540939284811, 51.57931379092206], [-0.939553921057406, 51.579748206813974], [-0.939549110634237, 51.57983088690364], [-0.939520940649101, 51.58004913048237], [-0.93951863934971, 51.58014801827346], [-0.939525037302583, 51.580245186310094], [-0.939540364690294, 51.58033074581249], [-0.939561798495469, 51.58040197377017], [-0.939594984852117, 51.58046431619436], [-0.939708262827559, 51.580619996404984], [-0.939729069878358, 51.58065615108302], [-0.939759224390201, 51.58072476025555], [-0.939813615319267, 51.58093026195459], [-0.939900523550716, 51.58172321441459], [-0.939894144544868, 51.581997403240464], [-0.939910832471369, 51.58208657162566], [-0.940114353648015, 51.582457967531546], [-0.94022333049887, 51.58267475179605], [-0.940267247821581, 51.58277225843995], [-0.94038427828014, 51.583077233742756], [-0.940493362377966, 51.583289522851196], [-0.940571515796737, 51.58340442254201], [-0.940725857371931, 51.58359464061899], [-0.941198340240742, 51.584069167875626], [-0.941335307610427, 51.584261925920295], [-0.941372786463165, 51.5843261048293], [-0.941416540699353, 51.58443080287741], [-0.941461326187118, 51.584739621364996], [-0.941517445876004, 51.5849954910945], [-0.941575869597484, 51.58533860085252], [-0.941574762730556, 51.58538624677686], [-0.941565185406358, 51.58542572382202], [-0.941550002863301, 51.58545795698674], [-0.941515976834126, 51.58549361692739], [-0.941470510606583, 51.585524677868065], [-0.941423872780384, 51.585544039043356], [-0.94131509921043, 51.585566436558274], [-0.941075026707647, 51.58558675057684], [-0.940953181611661, 51.58561262652464], [-0.940734943851404, 51.58568708689612], [-0.940229533088359, 51.585883040066975], [-0.940067635923264, 51.58595531027499], [-0.939917220191166, 51.58603038143916], [-0.939797255285709, 51.586099433232604], [-0.939675637701456, 51.586177461657186], [-0.939611074554604, 51.58622273608784], [-0.939340396866166, 51.586441486256], [-0.93912244296424, 51.58662744303347], [-0.938817233975319, 51.58671729893312], [-0.938661522913105, 51.586771639765516], [-0.938087678078033, 51.586992141762096], [-0.937332636663603, 51.5873072119485], [-0.93492634290483, 51.58836081134952], [-0.934774110277819, 51.58845114531925], [-0.934663126573178, 51.588505886685766], [-0.934565467487243, 51.588546362183585], [-0.934462140700832, 51.588582290320545], [-0.934337145222589, 51.58861892084846], [-0.934213782000904, 51.588647473549656], [-0.934055887760941, 51.588671216763295], [-0.933259701136762, 51.58864510257983], [-0.933213278816969, 51.588716614209304], [-0.932681740160827, 51.588792708227174], [-0.931992471253759, 51.58900853446031], [-0.930629113767652, 51.58946908647644], [-0.928525036745892, 51.59005953842682], [-0.928533690860491, 51.59024394687689], [-0.928456010745829, 51.59047792078815], [-0.928256501298223, 51.5906748158337], [-0.927916132025856, 51.59066181734799], [-0.927671608556404, 51.590624516635486], [-0.927319567022116, 51.59061680481465], [-0.926850285435352, 51.59062240702726], [-0.926313746570405, 51.59066425819173], [-0.925516790702947, 51.59079184232522], [-0.925387133168341, 51.59078076476673], [-0.925293323156809, 51.59077990606886], [-0.925202187496562, 51.59078806346173], [-0.925112304116411, 51.59080432476366], [-0.925036768134577, 51.59082431403807], [-0.924968299737815, 51.59085066215826], [-0.924899640304234, 51.59088510100373], [-0.924851228495836, 51.590917926896914], [-0.924734051019008, 51.59105082982951], [-0.924694255912291, 51.59108553291224], [-0.924446018071168, 51.59126668934789], [-0.924204972773907, 51.59150995377465], [-0.923492520665307, 51.59215352189589], [-0.922775141969353, 51.59288246146081], [-0.922298613651092, 51.59343737077436], [-0.922101568270595, 51.59365046303728], [-0.92149319027045, 51.59422483935332], [-0.921029930136652, 51.59464499018023], [-0.919455791303858, 51.595519790418045], [-0.919908472816787, 51.59560757835559], [-0.919902358174605, 51.595621908790214], [-0.919721503870405, 51.59588190272939], [-0.919513222918683, 51.59614164398608], [-0.919057326435374, 51.59661490568889], [-0.918991959815932, 51.59669253146064], [-0.918853979663433, 51.59690975873926], [-0.91882720841051, 51.59694278142396], [-0.918711889332325, 51.597056812913756], [-0.918614808732714, 51.59713234806153], [-0.918297245740306, 51.59749448485627], [-0.918073703114389, 51.59778825130676], [-0.917853804369843, 51.59811082427763], [-0.917772408698363, 51.59831598343439], [-0.917709563771812, 51.59853030520902], [-0.917692745480418, 51.59856971355161], [-0.917634249201942, 51.59866178857289], [-0.917443039919903, 51.59887043094418], [-0.917335250471836, 51.598971042984616], [-0.916888284039272, 51.599309503426845], [-0.916921110547038, 51.59938623548714], [-0.916942485633783, 51.5995195094582], [-0.916937652924948, 51.599601289122916], [-0.916945811778801, 51.599683188627004], [-0.916964246289877, 51.599757989575366], [-0.917049297107238, 51.59994580090974], [-0.917089705367533, 51.60000731699611], [-0.917171120773417, 51.60010517795964], [-0.91752823274465, 51.60044925531009], [-0.917834023417531, 51.600765883511485], [-0.917913079603466, 51.600902386385464], [-0.918033251654948, 51.60107073894696], [-0.91851090277833, 51.601507638962644], [-0.918694916056997, 51.601663091331545], [-0.919167224655989, 51.60214309940451], [-0.919302231291783, 51.6024167896932], [-0.919552009673002, 51.60266096432073], [-0.919812571846437, 51.60293760761218], [-0.920091738726093, 51.60358667644501], [-0.920208566517809, 51.603592246724574], [-0.920644522919282, 51.60359715428394], [-0.921093152621479, 51.6036156641763], [-0.921168285587618, 51.603613657034074], [-0.921469264587163, 51.6035867495928], [-0.921584776688781, 51.603586911416876], [-0.921718864440287, 51.603595336217005], [-0.921999521996191, 51.60363387995426], [-0.922136050325758, 51.603661209181794], [-0.922248015684399, 51.60368921195661], [-0.922346882036963, 51.60372159023333], [-0.922478548042792, 51.60377135359644], [-0.922605777045377, 51.603825571929555], [-0.92269948345521, 51.60389297005248], [-0.922855181916126, 51.60396453348124], [-0.922908065211369, 51.60398749776935], [-0.923525984356841, 51.604174796116844], [-0.923689774691443, 51.6042095667925], [-0.923842334751645, 51.60423074681459], [-0.924020987014581, 51.604247669912816], [-0.924152253615336, 51.604253368572344], [-0.924379056519158, 51.60424915231234], [-0.924491916632975, 51.60423939614583], [-0.925129396784027, 51.604149022807746], [-0.925308707040747, 51.60413807581467], [-0.925396812395019, 51.604137083863186], [-0.925816640142735, 51.60415261457396], [-0.926339243350925, 51.604157394450915], [-0.926627592983669, 51.60417621577326], [-0.928219342008724, 51.60433911850777], [-0.928540897883304, 51.60435823822504], [-0.928666454251138, 51.6043611822271], [-0.928925123731038, 51.60435275210506], [-0.929272427371303, 51.60432085222454], [-0.929350681081097, 51.604308977474346], [-0.929525019586135, 51.60426381040009], [-0.929730308556221, 51.60419195021111], [-0.929806393059037, 51.60414948374236], [-0.929854111423592, 51.60408517871234], [-0.929877477717563, 51.604012559228565], [-0.929880189120251, 51.60395863398061], [-0.930157001898001, 51.603362311928585], [-0.930233415197893, 51.60324431822904], [-0.930397156019029, 51.60303540508514], [-0.93058677482955, 51.602831223239896], [-0.930747612253953, 51.60268432562219], [-0.931065151604954, 51.602443542878724], [-0.931358556224333, 51.60224659876122], [-0.931494751600125, 51.602165114969594], [-0.931807666849096, 51.601998019766675], [-0.932115553298882, 51.60186055047904], [-0.932344261944379, 51.601774512081256], [-0.932581062209752, 51.601712824287226], [-0.932837650566022, 51.60166929919289], [-0.93304760157037, 51.60164423223924], [-0.933247236692325, 51.60162806284857], [-0.933524572231589, 51.601623388892406], [-0.93367307135076, 51.60163283011416], [-0.933854562367985, 51.601651562386515], [-0.934222940436163, 51.60170526005669], [-0.934582321335698, 51.60177326158339], [-0.935176916778695, 51.60190903449902], [-0.935323237909383, 51.60194992468383], [-0.935449328012611, 51.60199153042619], [-0.935555166022244, 51.60203475076641], [-0.935754957696255, 51.60213547009268], [-0.935920944220561, 51.60219991608389], [-0.936105992086264, 51.60225194623237], [-0.936251123590137, 51.60228203448254], [-0.9362553703842, 51.602285669620606], [-0.935954861941404, 51.603034649313756], [-0.936025513047831, 51.60328615677915], [-0.937604653681525, 51.60374194595848], [-0.937842729718605, 51.6037494948452], [-0.937998245297976, 51.60376798569096], [-0.938149157504488, 51.60379812385097], [-0.938282536474463, 51.60383709493093], [-0.938398403200176, 51.60388400001471], [-0.938549544157173, 51.60396629131982], [-0.938542113846477, 51.60403725821696], [-0.938540670189083, 51.60403724516617], [-0.938690470772444, 51.60417707075241], [-0.93885671831091, 51.60429276731543], [-0.938949655717409, 51.60433227129961], [-0.939171393952754, 51.60435945147724], [-0.939491406642938, 51.60438302306183], [-0.939580914110842, 51.60438383145672], [-0.939698081584302, 51.604374998744255], [-0.939860253923854, 51.60435578228165], [-0.940131370864495, 51.60430877574863], [-0.940224037565311, 51.60429792302206], [-0.941065905352937, 51.604358569226044], [-0.941456261791824, 51.60439985396626], [-0.94172260946072, 51.604433725629356], [-0.942065117075164, 51.604483568721975], [-0.942405972956444, 51.60454238758566], [-0.942542307804962, 51.60457868292929], [-0.942668453620936, 51.60461848302318], [-0.942754322773386, 51.60465162617505], [-0.942930037674105, 51.6047332338937], [-0.94300827141212, 51.60478429141865], [-0.943050642772121, 51.60482513526179], [-0.943095505071305, 51.604883085645305], [-0.943175837511794, 51.60503037259752], [-0.943199044776033, 51.60508812802956], [-0.943264927978451, 51.605360268787045], [-0.94328295289835, 51.6055168856955], [-0.943285556153251, 51.605653582182974], [-0.94327790338372, 51.60573443814757], [-0.943262026480571, 51.60579633763445], [-0.943228365851772, 51.605877858692274], [-0.943092212068021, 51.60614458434088], [-0.943074097962666, 51.60624063192375], [-0.943061365824471, 51.606415854446915], [-0.943044862244347, 51.60650472320056], [-0.943017897594943, 51.606608783583646], [-0.942979591589439, 51.606703750216774], [-0.942905884027612, 51.60683076806164], [-0.942741267849139, 51.60707925374213], [-0.942655006715899, 51.607249318295594], [-0.942630361430127, 51.60731563455148], [-0.942616263944651, 51.607425205688976], [-0.942621958529523, 51.60749089598715], [-0.942636336634899, 51.60755576531453], [-0.942660904708633, 51.607617129739225], [-0.942696981288364, 51.607680396114986], [-0.942747433102709, 51.60774648940761], [-0.942856244975984, 51.6078490746924], [-0.94299552290573, 51.60794563997599], [-0.943040847342192, 51.60798381288104], [-0.943186973159248, 51.608158666884215], [-0.943285889122319, 51.60825217104693], [-0.943509689787491, 51.60844031193307], [-0.94379690141149, 51.609007570967925], [-0.943824004868445, 51.60908424372538], [-0.943831400135399, 51.609201201602104], [-0.943839541642426, 51.60922375393887], [-0.943852077204152, 51.6092436483043], [-0.943874740412961, 51.60926273459518], [-0.943900416430683, 51.60927645299323], [-0.944008015202393, 51.60930709311221], [-0.944074894993692, 51.60934995527111], [-0.944126815315737, 51.60941516198104], [-0.944143328071964, 51.60945037786937], [-0.944150844233183, 51.609499899486615], [-0.944148608042361, 51.60953404761941], [-0.944074023202655, 51.60969882315075], [-0.94403415265091, 51.60986121332522], [-0.944017357658548, 51.60996266784037], [-0.943992023164905, 51.61030771903426], [-0.943965568458423, 51.61051428886229], [-0.943938629028152, 51.61067949277199], [-0.943919488028492, 51.61075754789674], [-0.943885949921455, 51.61083367520212], [-0.943827406881077, 51.61092935920088], [-0.943739589608875, 51.61104186395993], [-0.943638735204063, 51.61115604969767], [-0.943533757272514, 51.611261206608894], [-0.942952360107171, 51.61179457356613], [-0.942768364001955, 51.61194397664764], [-0.942436714102017, 51.61217027698273], [-0.942010518369458, 51.61248743929258], [-0.941742162181165, 51.61266215641604], [-0.941369087685306, 51.61286829880399], [-0.941218061678922, 51.612965845186196], [-0.941055044244821, 51.613082165678385], [-0.940962318642569, 51.61315685920963], [-0.940802313735133, 51.613329853845215], [-0.940532273923746, 51.613638528438315], [-0.940201080800705, 51.61403027273604], [-0.940058816377521, 51.614185443187054], [-0.939985695447699, 51.614286388653916], [-0.939953592073967, 51.614362527773245], [-0.939906859457064, 51.614508669589505], [-0.939802341993177, 51.61490335803689], [-0.939554942446072, 51.615603370947234], [-0.939452722231603, 51.61596121406953], [-0.939421935085161, 51.61604275989804], [-0.939387192811998, 51.616108085051245], [-0.939207265482904, 51.61639149465681], [-0.939036585027605, 51.61671185322904], [-0.938852844916865, 51.61697274874371], [-0.938765881571911, 51.61710953487875], [-0.938636321443754, 51.617400592062225], [-0.93858227703968, 51.617550263869646], [-0.938563060896774, 51.61763101488344], [-0.938557821588965, 51.617793716095726], [-0.938568952285691, 51.6178738422429], [-0.938586194898738, 51.61793963701825], [-0.93864824402059, 51.61806608070808], [-0.938712639101221, 51.61815388154161], [-0.938801458484915, 51.61824729803767], [-0.938902019778203, 51.61833272809444], [-0.939001577491258, 51.61839926656718], [-0.939080060597956, 51.6184404379885], [-0.939144458958051, 51.618466196342986], [-0.93924483456823, 51.61849767462955], [-0.939389936057716, 51.61853135511866], [-0.939533886937889, 51.618552436752374], [-0.939605967169062, 51.618558482633226], [-0.939704125343146, 51.618561167280205], [-0.940011869234288, 51.61855765138392], [-0.940970156479417, 51.61846828865034], [-0.942814559287174, 51.61834913395653], [-0.9433943585448, 51.61832378069166], [-0.943791844341078, 51.61831207069643], [-0.944095316626396, 51.61830580819228], [-0.944345189840605, 51.61830625638639], [-0.944633949874169, 51.618311549349706], [-0.944866264500346, 51.618321729423634], [-0.945069571918896, 51.61833704343469], [-0.945259736594118, 51.618358533188456], [-0.945405071369022, 51.6183823175338], [-0.945538707551366, 51.61841229079249], [-0.945670733169093, 51.618449442740584], [-0.945789657802543, 51.61849097274293], [-0.945898390514756, 51.618536007789324], [-0.946002624502939, 51.61858819565799], [-0.946144975691139, 51.61867849034559], [-0.946290660655923, 51.61881197458077], [-0.946424293873759, 51.618966930407886], [-0.94648587943588, 51.619052004215185], [-0.946597289998464, 51.61923103785771], [-0.946748500992991, 51.619500344620654], [-0.946865282768134, 51.619759451627154], [-0.94692090631825, 51.619852564183816], [-0.946986743272162, 51.619941272483025], [-0.947121992710119, 51.62008904866086], [-0.947221067183078, 51.620177155655796], [-0.947357337089385, 51.62028088174252], [-0.947636341593443, 51.62045871900467], [-0.947732020809812, 51.62050633282523], [-0.947832261440868, 51.62054409665008], [-0.948024909405708, 51.6205835873772], [-0.948272727755043, 51.62061098363029], [-0.94903310890345, 51.62064836261257], [-0.949342820854191, 51.62068530212313], [-0.949548509996597, 51.62072310869445], [-0.949603327033706, 51.620726296510135], [-0.94966121922192, 51.62072141934501], [-0.949725095662238, 51.62070760405018], [-0.949813979767225, 51.620674230793945], [-0.949850856696741, 51.620766275113425], [-0.949938127431095, 51.62092800552347], [-0.95012170684362, 51.62142328688538], [-0.950137689181391, 51.621481875301626], [-0.950144591409982, 51.621558365780544], [-0.950143525838059, 51.62166715485939], [-0.950086848280287, 51.62218276713024], [-0.950081566444785, 51.62234906486587], [-0.950091380322934, 51.6227375905417], [-0.950012857804674, 51.623198158520914], [-0.949963053357781, 51.62366617649237], [-0.94993621019599, 51.62382778558582], [-0.949887611273865, 51.62405573809743], [-0.94981748429385, 51.62434014525264], [-0.949698012983878, 51.6246969431444], [-0.949601071539472, 51.62520410239216], [-0.949519655994856, 51.62547671925938], [-0.949509640700394, 51.62553507516918], [-0.949509569744091, 51.62560071332227], [-0.949517625184728, 51.6256898023632], [-0.949539397678852, 51.62581048474923], [-0.949602831958219, 51.626066413978656], [-0.949622600072634, 51.6262113557699], [-0.949625807500304, 51.62644786389373], [-0.949588359660548, 51.62688092470566], [-0.949587162842075, 51.62718303218221], [-0.949593421398238, 51.627287390862], [-0.949641886384285, 51.62762860642186], [-0.949677564559904, 51.627772791296934], [-0.949732061930258, 51.62791534613564], [-0.949847071945823, 51.62812767746571], [-0.95005020451512, 51.62890367131774], [-0.949860358893705, 51.62924185674224], [-0.949849459019953, 51.62927592739189], [-0.949848649628705, 51.62931098742953], [-0.949857806222275, 51.62935243070728], [-0.949882540677514, 51.62940750068883], [-0.949782851646605, 51.62940750843079], [-0.949684104107472, 51.6296170289926], [-0.949619670293909, 51.62984214210067], [-0.949589348281571, 51.62990391300069], [-0.949478823262764, 51.63006027755304], [-0.949419643728549, 51.63018293320961], [-0.949378577882241, 51.63033452402259], [-0.949364251310331, 51.63051692549393], [-0.949339228920643, 51.63059942443184], [-0.949248633732607, 51.63076855530058], [-0.949181283974238, 51.630869557872636], [-0.949044504574139, 51.63103647701982], [-0.948893935504611, 51.63136242402941], [-0.948761069414249, 51.631297394415576], [-0.948669492362367, 51.63125880992652], [-0.948537801268757, 51.63120547966423], [-0.948447461288637, 51.63117589768262], [-0.948353982967507, 51.63115707745748], [-0.948302104865814, 51.63115121794117], [-0.948079606840815, 51.63115102360314], [-0.947964190602531, 51.63114369566099], [-0.94782149485015, 51.63112892992514], [-0.947725107052886, 51.63111098229264], [-0.947684910040859, 51.63109983219839], [-0.947483021604023, 51.63102069524269], [-0.947447137482345, 51.63101048287877], [-0.947306094892948, 51.630986739722026], [-0.947000710620611, 51.63094713644845], [-0.946674033898238, 51.6308911565172], [-0.946364247153943, 51.63079216747898], [-0.946230490849763, 51.63076579091048], [-0.946172752135344, 51.63076347450912], [-0.94612066649297, 51.630766603772976], [-0.945914796224295, 51.63079712600587], [-0.94583241748209, 51.63079818492752], [-0.945382953779145, 51.63067905708907], [-0.945085984219956, 51.63058827220451], [-0.944883205963743, 51.630547786680644], [-0.944304065189339, 51.630538086402446], [-0.94394898927073, 51.630523204990325], [-0.943611477254356, 51.63049858971805], [-0.943603681926519, 51.6307098224617], [-0.943277115569317, 51.63102249010073], [-0.943359247728321, 51.63109426279834], [-0.942862682241593, 51.631385618132356], [-0.942777562378065, 51.63144239822567], [-0.942532313252267, 51.63161282917167], [-0.942337892928893, 51.63177202827151], [-0.94226606523137, 51.631816339444626], [-0.942197377359527, 51.63184988892168], [-0.942115813951467, 51.631877927416205], [-0.941937005967162, 51.631924871353945], [-0.941512981586086, 51.63201636159427], [-0.94144898217334, 51.6320346671529], [-0.94125937051438, 51.632111184999914], [-0.940790185204025, 51.6323425346351], [-0.940501042462563, 51.632535943664614], [-0.940243238615803, 51.63268647504363], [-0.940131608045529, 51.632764593869275], [-0.939328651391563, 51.63361514453957], [-0.939011405652477, 51.634145481445906], [-0.93882930544315, 51.63451878632893], [-0.93850479164515, 51.63486472819315], [-0.93841585373771, 51.63483694950617], [-0.938308667759282, 51.63503379600045], [-0.938237520065274, 51.63511048065125], [-0.938174497877949, 51.635148574806536], [-0.938097155068085, 51.63518114448376], [-0.938014243480848, 51.63520467214815], [-0.937885103100742, 51.635227781700706], [-0.937899482630853, 51.63529265131639], [-0.937852791962712, 51.635312010611116], [-0.937756752174709, 51.63534081433219], [-0.93768849662133, 51.635355482713884], [-0.937445207164159, 51.63537845841074], [-0.937282775985471, 51.6354039635962], [-0.936848828519967, 51.635485456519916], [-0.935951432459366, 51.63561220386278], [-0.935719677036262, 51.635636179646525], [-0.935420148631615, 51.63565414571281], [-0.935249454884316, 51.63560044703531], [-0.935077590540852, 51.635535048401415], [-0.934717727795324, 51.63535285185533], [-0.934413155884105, 51.635216113905294], [-0.934240481559584, 51.635123731852076], [-0.934130824273522, 51.63505529964683], [-0.934018404467151, 51.63498144729724], [-0.93379675026591, 51.63482118293064], [-0.933679892303923, 51.6347517857655], [-0.933595523374065, 51.63471415412531], [-0.933350473747258, 51.63462740768713], [-0.933261876876166, 51.63458524160035], [-0.933052343088727, 51.63446285066096], [-0.932887751506176, 51.63439571653097], [-0.932638117941304, 51.63431971687678], [-0.932307197466639, 51.63419801967628], [-0.931343887912331, 51.63380981222079], [-0.931071830619705, 51.63376597498289], [-0.930956833347264, 51.63374065092008], [-0.930823331188951, 51.63370346918478], [-0.930701576222194, 51.633658301797674], [-0.930601553796263, 51.63361063468632], [-0.930506119022842, 51.63355221932683], [-0.930386739592999, 51.633467510133144], [-0.930286034494439, 51.633387466714524], [-0.930225334024314, 51.63332666999925], [-0.930188937852857, 51.633276884582266], [-0.930114567680391, 51.63312155131756], [-0.92999324620862, 51.63293521875163], [-0.929900400330813, 51.63282827174111], [-0.929602366751531, 51.6325378240622], [-0.929499431873266, 51.632429885607195], [-0.929341000864788, 51.63222433167361], [-0.929059923028374, 51.631889079042224], [-0.928963213558906, 51.63176231446386], [-0.928896162303318, 51.6316645934755], [-0.928844852932023, 51.631573310156845], [-0.928688841592085, 51.63126527289447], [-0.928672375509884, 51.6312282570475], [-0.928615004479859, 51.631026321392014], [-0.928599834825331, 51.63099561149414], [-0.928552267379979, 51.63092953870757], [-0.928477466267079, 51.630854225808044], [-0.928389580173335, 51.630782390113474], [-0.928294323595921, 51.6307167812279], [-0.928190294396403, 51.63065558801307], [-0.928078937075949, 51.630598823630024], [-0.927494137115659, 51.630339021667446], [-0.927177150281751, 51.63017967221046], [-0.927053070740772, 51.63011110151437], [-0.926922044883713, 51.63003077810591], [-0.926774152423019, 51.6299305188448], [-0.926569924361936, 51.62976860145066], [-0.926465515994788, 51.62966244509719], [-0.926222881099496, 51.62935271335746], [-0.925807083215573, 51.62885077488713], [-0.925685153671251, 51.62869140695483], [-0.925627779063265, 51.628612654944924], [-0.925107975398826, 51.62780494620014], [-0.925039238852947, 51.627717997425265], [-0.924853081975605, 51.627525670804864], [-0.924566287633664, 51.62725149768458], [-0.924018135317732, 51.62666651663998], [-0.9236755124427, 51.62631000590676], [-0.923506463123086, 51.62618886774415], [-0.92325024557972, 51.62602736696645], [-0.923179326155173, 51.62597186775246], [-0.923151247824846, 51.62593744208942], [-0.923025917353845, 51.62573937605691], [-0.922746731858051, 51.625388839233764], [-0.922647729925315, 51.625421200084226], [-0.922438316532782, 51.62517470633975], [-0.922266691774008, 51.62491866820555], [-0.922176577184834, 51.624819832363215], [-0.921722712186069, 51.62440384906751], [-0.921324388846087, 51.624082786314446], [-0.921078577970903, 51.623909687134365], [-0.920860652296657, 51.62377910436709], [-0.920574889783577, 51.623646099345635], [-0.920239048968319, 51.623492851580735], [-0.920014292502202, 51.62371107994427], [-0.919774493442185, 51.623954346092496], [-0.9196346398006, 51.62406455586703], [-0.919395541436808, 51.62427815528515], [-0.919291601043514, 51.624396787581134], [-0.919216417933559, 51.6245210794288], [-0.919153464283899, 51.62467785367513], [-0.919134125069682, 51.624762197061855], [-0.919115026043568, 51.62495803894169], [-0.919049238753011, 51.62517323267518], [-0.919009465019033, 51.625266379578875], [-0.918926652164549, 51.625407685106715], [-0.91889138185638, 51.62549368011671], [-0.918887531877765, 51.62553410703284], [-0.918896749679156, 51.62569334383204], [-0.918892707420934, 51.62574186144837], [-0.918872585162246, 51.62579832350382], [-0.918836276012485, 51.62586722482348], [-0.918763089019947, 51.62596815648993], [-0.918486277330256, 51.626309088016214], [-0.918317614737411, 51.62653682130949], [-0.917905561785174, 51.626975413689514], [-0.917718470441796, 51.62724883363936], [-0.917588198962995, 51.627380709193844], [-0.917518986462533, 51.627435819379606], [-0.917391270738013, 51.627520961779815], [-0.916852199941663, 51.62783249660931], [-0.916708494011591, 51.62822500463541], [-0.916564194300437, 51.62882431452802], [-0.91642514281193, 51.62950639562586], [-0.916399138398425, 51.62974892972319], [-0.916394191477189, 51.62995659074321], [-0.917260413231125, 51.62992321851857], [-0.917422640699178, 51.63166639247214], [-0.91745600722272, 51.63232848375385], [-0.917204699151121, 51.632324368705305], [-0.916787813832452, 51.632356490901394], [-0.916473041038736, 51.63240843616508], [-0.91615824611563, 51.63246127954521], [-0.916096846672852, 51.632491284427324], [-0.916000979824314, 51.632573122584574], [-0.916035541448316, 51.63300234215989], [-0.916058746179642, 51.633180590521675], [-0.916070697537387, 51.63322475979131], [-0.916098260729099, 51.63328076225654], [-0.916287121367376, 51.6334803208717], [-0.916556537933578, 51.63369500893812], [-0.916833436931067, 51.63389897542989], [-0.916980624704717, 51.63396776999687], [-0.917236275570907, 51.634093312450645], [-0.91746761535009, 51.63414759643489], [-0.917599467742121, 51.63382870989293], [-0.917652284973834, 51.63367364156546], [-0.917677934007693, 51.63362802065708], [-0.917745133700401, 51.63359716923921], [-0.917749446066394, 51.633598108140106], [-0.917778102484095, 51.633608262991594], [-0.918084580428658, 51.633662338963], [-0.918258883815884, 51.633684625273325], [-0.918506861448772, 51.63370758977881], [-0.918953829589691, 51.63374767133924], [-0.919245145699076, 51.633771033193085], [-0.919300707852053, 51.63386505735126], [-0.919518444759651, 51.63449197843591], [-0.919277685382965, 51.63446908250848], [-0.919031520477806, 51.63467362436313], [-0.918786199566619, 51.63490335001199], [-0.918632752044247, 51.63503681158531], [-0.918623327237537, 51.63512933850577], [-0.918590569006466, 51.635413172104], [-0.918679820058316, 51.63554886817429], [-0.918329488250497, 51.63557621368664], [-0.918276435808259, 51.635741170885815], [-0.918247752304029, 51.6360358318421], [-0.918226764712395, 51.6364321689642], [-0.918316733144818, 51.63702374696847], [-0.918287332378286, 51.63783452012518], [-0.918306713699577, 51.63835621240955], [-0.918316674296085, 51.639213205140855], [-0.918347519668651, 51.639799742499974], [-0.918322169732004, 51.63995416480466], [-0.918318885834364, 51.64003146244247], [-0.91832686087795, 51.64012145202931], [-0.91837911416845, 51.640354816042915], [-0.918418495846573, 51.64070405330022], [-0.918530296534871, 51.64128953760163], [-0.918512952473936, 51.64147190762244], [-0.918367217757134, 51.64200916315153], [-0.917905817511154, 51.6420255938785], [-0.917874522823857, 51.64200462484983], [-0.9178264462409, 51.64196012300076], [-0.917792775459127, 51.641917552189355], [-0.917773553228143, 51.64187511449974], [-0.917765526057023, 51.64184806570082], [-0.917757894232724, 51.6417436926823], [-0.917749532884981, 51.64142711089125], [-0.917739557627689, 51.64136048104305], [-0.917720785029217, 51.641299165096676], [-0.917688816437575, 51.64124581999865], [-0.917649452591449, 51.641199600032465], [-0.917568381483579, 51.64114490323613], [-0.917433423830488, 51.64098630616572], [-0.917315173490429, 51.64079369481265], [-0.916601390868836, 51.640243120219885], [-0.916329281834837, 51.640018517003504], [-0.916001068304932, 51.63966211774633], [-0.915790319174844, 51.63947044935813], [-0.915502073944432, 51.63913509831614], [-0.915393357554307, 51.63902799332443], [-0.915169439572157, 51.63884339546647], [-0.914312592230519, 51.638234837864296], [-0.913969150495335, 51.63797270396478], [-0.913808719070197, 51.63773204326735], [-0.913709021859032, 51.63761063348384], [-0.913238840648949, 51.637814889395024], [-0.912211197236081, 51.63818662075986], [-0.912057780107923, 51.6382571327065], [-0.911911629192503, 51.63832591344631], [-0.911683066608314, 51.6384568717294], [-0.911571655864317, 51.638583520328496], [-0.910821072629623, 51.63897039510019], [-0.910799442348496, 51.63890815232427], [-0.910457034748542, 51.63884473254883], [-0.90959863753988, 51.63872527019996], [-0.909397970101408, 51.639078576087414], [-0.909048252097236, 51.63925965643008], [-0.909362542404515, 51.63959166868019], [-0.90780907162756, 51.64013291512084], [-0.906217399025103, 51.640939038154336], [-0.905898125060113, 51.64111499768922], [-0.905490384709512, 51.641363863281036], [-0.905329841704473, 51.64154939281248], [-0.905189541321435, 51.641794455508446], [-0.90489098319803, 51.64194992468491], [-0.904781623731163, 51.641990266433346], [-0.904676706895303, 51.64202615370086], [-0.904609919053975, 51.64203901826923], [-0.904237228330216, 51.64209218907456], [-0.90337364044862, 51.64224597828853], [-0.902975191138407, 51.642348358507896], [-0.90292303291413, 51.6422939216028], [-0.902563354675933, 51.64240655335107], [-0.902346768622897, 51.642458479170756], [-0.900824166346957, 51.64291090498388], [-0.900831401206159, 51.64297031739377], [-0.900456613238591, 51.64299018760407], [-0.900019098619797, 51.64297440185565], [-0.899740380937974, 51.64290615240652], [-0.899740489711103, 51.64290165761423], [-0.899316872364163, 51.642849133775655], [-0.899203336991784, 51.642822893203494], [-0.898949902655656, 51.64272520647125], [-0.898783095909619, 51.642631028913314], [-0.898613530793898, 51.64253143027416], [-0.898274969154989, 51.64230885935864], [-0.898003026265053, 51.642080618381755], [-0.897815191816853, 51.641840577798526], [-0.897681652652772, 51.6416262230417], [-0.897327401428262, 51.64091885338664], [-0.896908641882592, 51.6401308512027], [-0.896689777704333, 51.63985994571793], [-0.896199107519928, 51.639356299928586], [-0.896147069948886, 51.63929736526477], [-0.896071667668875, 51.63912941223961], [-0.896034388155249, 51.63881974973283], [-0.89604243255033, 51.63866696761571], [-0.896079873457203, 51.63849378104931], [-0.896158355572289, 51.63829670279626], [-0.896345617779906, 51.63796397393339], [-0.896436991088377, 51.637771512438086], [-0.896627579786388, 51.63748017587825], [-0.896853716275347, 51.63721255114492], [-0.896930541034958, 51.63714313797598], [-0.897052325259386, 51.63706695367484], [-0.897622203318074, 51.636806151704704], [-0.897875248140837, 51.636679946210485], [-0.898045509693898, 51.63657094674504], [-0.898161794997489, 51.63648302058021], [-0.898300490282884, 51.636364732965696], [-0.898761753797595, 51.63587451909389], [-0.898944791614438, 51.635595696246455], [-0.899167964890093, 51.63497197055003], [-0.899296205851425, 51.63450920414348], [-0.899574174378538, 51.633591065468096], [-0.89965934952667, 51.63323579470252], [-0.899745200652967, 51.632733067337156], [-0.89977291429982, 51.632065248259224], [-0.899749317297925, 51.63190587518938], [-0.899730833669311, 51.631833768913715], [-0.899698165870897, 51.631750739777836], [-0.89965967663145, 51.63166945441679], [-0.899415121605884, 51.63126703489972], [-0.899342021743563, 51.6311233827535], [-0.899274678557411, 51.630980683675816], [-0.899221406706553, 51.63067446858268], [-0.899099405183406, 51.63046202142283], [-0.899036514315775, 51.63037421293725], [-0.898969246754073, 51.63028816171176], [-0.898790586842518, 51.63008867047265], [-0.898592010806669, 51.62987640386868], [-0.898497321924236, 51.62978919602221], [-0.898330098469121, 51.62965455114822], [-0.898092642525963, 51.62949676796704], [-0.897090362270362, 51.62894426419184], [-0.896737033461809, 51.62879887742956], [-0.896347312922056, 51.6286648367393], [-0.895633444660858, 51.62837398981453], [-0.895432402381131, 51.628264199314984], [-0.895328663542796, 51.62819308870188], [-0.895257753282041, 51.62813847178444], [-0.895144755729953, 51.62803220648194], [-0.894948239644532, 51.627795675481295], [-0.894944118635818, 51.62766795529761], [-0.894659948504904, 51.62723368184], [-0.894597856997988, 51.62711350846984], [-0.894557343909314, 51.62699713484451], [-0.894469809950127, 51.62655661915932], [-0.894297931114171, 51.625960652861906], [-0.894027819576293, 51.62530531541029], [-0.893931965007508, 51.62514795788166], [-0.893770350871199, 51.62496210671055], [-0.893637995566781, 51.62476124514902], [-0.893507481839104, 51.62466290563429], [-0.892108104715385, 51.62369479825078], [-0.891788795844237, 51.623459800649094], [-0.891922368328922, 51.62337294285213], [-0.891402229815371, 51.62296161084893], [-0.891224922435199, 51.622768414566416], [-0.890089770742591, 51.621276764770215], [-0.890188416566163, 51.62120036880181], [-0.889947380146256, 51.62101466068101], [-0.889727152716072, 51.62086421627997], [-0.889328903798693, 51.62066892786315], [-0.889153387824523, 51.620758083474584], [-0.888409981594066, 51.6201459098237], [-0.888016456293258, 51.619876030785385], [-0.887588982852847, 51.619754191291285], [-0.887143566599165, 51.61965735685454], [-0.88701981132148, 51.61963820065132], [-0.886790744842007, 51.619613550199404], [-0.886603228328527, 51.619602780759124], [-0.886388075513318, 51.619599841439666], [-0.886090409498186, 51.61960421155123], [-0.8851368584814, 51.61967159165818], [-0.883828125903616, 51.61979133688442], [-0.883515973065361, 51.619797361107345], [-0.883424375160774, 51.6198216668555], [-0.883259776293847, 51.619877648328995], [-0.883163867754863, 51.61990101371408], [-0.883044634749604, 51.619815357981636], [-0.881854770311083, 51.61956485587701], [-0.881704286246311, 51.61951666620604], [-0.881635675440863, 51.619487239450166], [-0.881560131370525, 51.619446057447796], [-0.881477720403852, 51.619390423316226], [-0.881374708667671, 51.619291432867335], [-0.880834298239682, 51.61853547912722], [-0.880617549323506, 51.618127888748454], [-0.880388345702594, 51.61816796449318], [-0.879226788544387, 51.6185884841998], [-0.878534686661489, 51.61883184500677], [-0.878385021629543, 51.61898507235025], [-0.878148819949825, 51.61913297697072], [-0.878102165244257, 51.61915051459153], [-0.87804120240859, 51.61916252048532], [-0.877967464227806, 51.619165412606506], [-0.877896924603018, 51.61915574690363], [-0.877839648002824, 51.61913541789456], [-0.877812586845032, 51.61911987344738], [-0.877382402665225, 51.61869944717381], [-0.877261875140598, 51.61866682400238], [-0.877087293116294, 51.618600414623565], [-0.876592344555959, 51.61846350297477], [-0.876408990128558, 51.61845995037962], [-0.876374465270622, 51.61845422502283], [-0.876347205240439, 51.61844677083749], [-0.87630299358364, 51.61842386858449], [-0.876241963569583, 51.618380124514495], [-0.876216636094276, 51.618352907107045], [-0.876152781748704, 51.618131100785114], [-0.876106882196741, 51.61811807314475], [-0.876305643178539, 51.617614643124426], [-0.875030363348109, 51.6174927341714], [-0.874705473526163, 51.61748872204597], [-0.874564111923802, 51.6174810731233], [-0.874279482039409, 51.61730930128958], [-0.874259717266618, 51.61699889890464], [-0.874416434195306, 51.61673604585861], [-0.874423036602998, 51.61652750219062], [-0.870144618410033, 51.61769939147719], [-0.870074692270606, 51.617607003497994], [-0.869665459226217, 51.61768399010514], [-0.869137937974611, 51.617812887107476], [-0.868711126950696, 51.61789959196275], [-0.868460959800069, 51.617969115035805], [-0.866874516019656, 51.61827841686334], [-0.866642434191741, 51.6183175388698], [-0.866517885416195, 51.61833072340073], [-0.866392071649004, 51.61833670224208], [-0.865776872894858, 51.61833166083683], [-0.865633662902087, 51.618340168339564], [-0.865493072065054, 51.618359490991885], [-0.864874419821269, 51.618492883413026], [-0.864829070270363, 51.61851582340227], [-0.8648101986804, 51.61846169086974], [-0.864778464993556, 51.618402038980314], [-0.864733824417545, 51.61833866562683], [-0.864681918741689, 51.61827702035103], [-0.864649512487616, 51.61824433697217], [-0.864492159027339, 51.61812502442397], [-0.864510219622979, 51.618037979732996], [-0.864490008258273, 51.61792179156664], [-0.863791866117017, 51.616668790850674], [-0.863578496430752, 51.61619016667409], [-0.863939572338851, 51.6160749702936], [-0.864141702322916, 51.61602027805823], [-0.864343742093738, 51.615969181278444], [-0.864684853799959, 51.61590144547291], [-0.864287415633653, 51.61573755014447], [-0.864114344880943, 51.615611790807684], [-0.86394143216696, 51.615479738556914], [-0.863424226660599, 51.6150224515856], [-0.863108525016747, 51.61470918210108], [-0.862999136822108, 51.61463618943345], [-0.862947760773663, 51.614611414387845], [-0.862827479233939, 51.614569786988696], [-0.862764327092327, 51.6145538895073], [-0.862690954996651, 51.614542388851355], [-0.862422671693898, 51.614528100870835], [-0.862278208948609, 51.61452939875511], [-0.862025067586916, 51.614544929155834], [-0.861633333855888, 51.61461576315295], [-0.861195617216796, 51.61467715820802], [-0.860991546767721, 51.61469406144679], [-0.860819513274215, 51.61470048511226], [-0.860591345418716, 51.61469917048917], [-0.860366335624517, 51.61468709604235], [-0.860199196800327, 51.61467108707321], [-0.860140174693704, 51.6146633207896], [-0.859842784619867, 51.61460018922178], [-0.85969929013584, 51.61456282905675], [-0.859501466379857, 51.61450336097874], [-0.859306643699259, 51.614439425872085], [-0.859175017225196, 51.614389591981386], [-0.858977780895874, 51.61430675031806], [-0.858172868778381, 51.61392127488393], [-0.856305510909038, 51.61299763777437], [-0.855879431428414, 51.61282624136621], [-0.855413827571698, 51.612676038205095], [-0.855073660630441, 51.61259179657028], [-0.854915624510577, 51.612558784566126], [-0.854688372582268, 51.61252150056368], [-0.854459541396129, 51.6124895957323], [-0.854208848612115, 51.61246556965946], [-0.853413812340721, 51.612436228916096], [-0.851724243907319, 51.61242871018406], [-0.851450292115, 51.612410744947404], [-0.850998615679464, 51.61233888823236], [-0.850653274334699, 51.61223120468302], [-0.850372939737194, 51.61235164666859], [-0.850315593337778, 51.61233490012849], [-0.850193999216673, 51.612288751000705], [-0.850146601119627, 51.612278395984944], [-0.849926028861458, 51.61226274823948], [-0.849854084982468, 51.61225215268858], [-0.849714847013531, 51.612218418620564], [-0.849473435162227, 51.61217019573735], [-0.849372523204365, 51.61216291272777], [-0.849235958321253, 51.61219484371945], [-0.849170915863905, 51.6121969037703], [-0.849112126238191, 51.61218014249445], [-0.8487984760956, 51.61201881385575], [-0.848813983178796, 51.61186251023449], [-0.848805967905994, 51.611779707971536], [-0.848777693193183, 51.61169850541887], [-0.848751669639592, 51.61164250170296], [-0.848740414389996, 51.61163070213332], [-0.848685616135578, 51.61162746733029], [-0.848598109857592, 51.61148993537107], [-0.848561752293423, 51.61144282198033], [-0.848420551583887, 51.61131555337684], [-0.848346143135118, 51.61123120073643], [-0.848017978126262, 51.61073074025961], [-0.84803240586268, 51.61067423405594], [-0.848009203184881, 51.61062095534751], [-0.848010806265629, 51.61061467688053], [-0.848360723390725, 51.61054078070849], [-0.848731046077576, 51.61040234328455], [-0.848814480324059, 51.61035820278237], [-0.848820437461021, 51.610351067821576], [-0.848690278305866, 51.610072847084595], [-0.847947554822518, 51.60900543974003], [-0.847435103308081, 51.6083125448088], [-0.847167998407497, 51.60796823756615], [-0.846186886755928, 51.60662333116728], [-0.845549998419521, 51.605828497430636], [-0.845383680959569, 51.60566770865375], [-0.844840468159951, 51.60522267062485], [-0.84443530295085, 51.60497141150611], [-0.844232696249957, 51.60481835643492], [-0.843486943931864, 51.60416181103064], [-0.84332558359401, 51.60420428093958], [-0.842908147301968, 51.603868373383044], [-0.842663709069561, 51.603714004109015], [-0.842310199280505, 51.603533382087996], [-0.841471682375652, 51.60311958453644], [-0.841215384127901, 51.602977683579475], [-0.840873068217364, 51.60281155440105], [-0.840467421086961, 51.602637605395635], [-0.840268344470896, 51.602516948405764], [-0.840203154295604, 51.60246864832527], [-0.838474883614574, 51.601841924417336], [-0.838334815858368, 51.60178568911777], [-0.838125139250388, 51.60168470536249], [-0.837520083534699, 51.60134782062488], [-0.837365310402971, 51.60124558073874], [-0.837143016970701, 51.6010734356079], [-0.83702163004049, 51.600964332538595], [-0.836879440722268, 51.60082175386177], [-0.836733036616179, 51.60067463738169], [-0.836105420124444, 51.59992210370809], [-0.836001567218505, 51.59980508080317], [-0.835894758960057, 51.59969072601903], [-0.835646409012494, 51.5994652683849], [-0.835572705263831, 51.59941148620318], [-0.835355212679077, 51.599278049641256], [-0.835001490423373, 51.59910819321327], [-0.834666328550124, 51.59894661249016], [-0.834023851532118, 51.59860753956394], [-0.833813699592692, 51.59846967713012], [-0.832219972267628, 51.59727861587006], [-0.831975375091702, 51.59713321406168], [-0.83180286996819, 51.597047874561696], [-0.83156138306724, 51.59695015903964], [-0.831279067386554, 51.596868221715724], [-0.831119729288761, 51.59683246683902], [-0.830996129682144, 51.596810555210986], [-0.830798964246538, 51.59678611250204], [-0.829935838169309, 51.596720865686486], [-0.82967342169104, 51.596707460026586], [-0.829378950815281, 51.59670542343618], [-0.828672101908656, 51.596738836236966], [-0.828529092462618, 51.59674190522934], [-0.828241907711544, 51.596737240965595], [-0.828066024571149, 51.59672739285258], [-0.827854311754233, 51.596707295846045], [-0.827399248313258, 51.59666228882735], [-0.827164974703315, 51.59662128423301], [-0.827063074447412, 51.59659778687348], [-0.826830893268571, 51.59653162563389], [-0.826403126611598, 51.596379885757386], [-0.826320361645679, 51.596342192238744], [-0.826196596762853, 51.596270819297594], [-0.825930135887572, 51.596078429107884], [-0.825702044863314, 51.59590980062742], [-0.825239717878873, 51.595531118786504], [-0.824901250965003, 51.59522021379687], [-0.824412039116432, 51.59470908081712], [-0.8242790371805, 51.59460434384618], [-0.824162427084317, 51.59453573788591], [-0.823734544991122, 51.59433363318264], [-0.822923577534385, 51.59387232098135], [-0.82274220720895, 51.593740122024236], [-0.822758790294358, 51.59343366962803], [-0.822450529949737, 51.592123177421634], [-0.822408018987733, 51.591980681321466], [-0.82236394886053, 51.59184266543808], [-0.822242174035691, 51.59158338051977], [-0.821801765862476, 51.5908065697487], [-0.821372709449585, 51.59009371260957], [-0.821171850754746, 51.58982284235581], [-0.820679968304875, 51.58936291919855], [-0.820417155492676, 51.58914357740762], [-0.82015811620844, 51.5888901042506], [-0.820045903377484, 51.58876399099103], [-0.81975498206002, 51.5884040936899], [-0.819793038416411, 51.58838379523831], [-0.819648800144719, 51.588268149727725], [-0.819147039514258, 51.58763368041164], [-0.818936357700162, 51.58740856531028], [-0.818746726401906, 51.58698404449756], [-0.818744261992127, 51.58691208559554], [-0.818786542624285, 51.586561832259704], [-0.818798419467402, 51.58638211648965], [-0.818772601288344, 51.58593047014409], [-0.818622316220491, 51.585380460186784], [-0.818493730937228, 51.58471737211902], [-0.818460174123387, 51.58461992329734], [-0.818316632401033, 51.58436670899539], [-0.818092592164715, 51.58404524580265], [-0.817774082795079, 51.58341531231479], [-0.817553796530972, 51.58311636524129], [-0.817445537064436, 51.58300557512581], [-0.81689125274485, 51.582562990062094], [-0.816348587477007, 51.58217357091916], [-0.816214612729635, 51.58210837837547], [-0.816144330954904, 51.58209148442308], [-0.816059129697027, 51.58209332267878], [-0.815742672724781, 51.5820523651453], [-0.815217212787465, 51.58194545592985], [-0.815002344756643, 51.58188304223224], [-0.814826435408141, 51.5818210214772], [-0.814485295861823, 51.581730356582035], [-0.81444044205173, 51.581790148477246], [-0.813566956536122, 51.581635656767844], [-0.813282023122958, 51.58154825394594], [-0.813052037332166, 51.581456910143594], [-0.812870182657061, 51.581346270732034], [-0.812790810356639, 51.58129061819263], [-0.812604263086127, 51.581138568732094], [-0.812386509085548, 51.58085492331321], [-0.812249092317067, 51.58070067277682], [-0.812167619564544, 51.58055957666617], [-0.812051961231651, 51.58029045130041], [-0.812042798783181, 51.580254391465495], [-0.812034433182585, 51.580187767648724], [-0.812033188044369, 51.58012481260171], [-0.812058064730261, 51.580000977815104], [-0.81229781440549, 51.579440518478464], [-0.812247901650195, 51.57941753400863], [-0.812446355706805, 51.57916777205078], [-0.81277233113049, 51.578787120404634], [-0.813191367818544, 51.57821318632392], [-0.813476583358647, 51.57767926033569], [-0.81372993476285, 51.57714950751218], [-0.813894821439398, 51.57669169369027], [-0.813998634879093, 51.57614064720803], [-0.814138744624452, 51.57508193151095], [-0.814120940539715, 51.57493428638376], [-0.81419874804071, 51.57321943977239], [-0.814492542549023, 51.572575897898666], [-0.814547744449169, 51.57211787423915], [-0.814549364628156, 51.57200009817749], [-0.81449843948966, 51.57157247390041], [-0.81447275908744, 51.57022974030085], [-0.814470739157426, 51.56964165674743], [-0.814429823166273, 51.56938407823071], [-0.814416473674158, 51.5693425811485], [-0.814362577800679, 51.569251219648685], [-0.81406844007837, 51.5689659058573], [-0.813908308238922, 51.56874308971205], [-0.813853532979604, 51.56863013877188], [-0.81375715260415, 51.56839717647337], [-0.81371284208748, 51.56815934527622], [-0.813667666933597, 51.567788426746645], [-0.813915408556528, 51.567527470860746], [-0.814280993234198, 51.56684059466537], [-0.814704823511867, 51.56613272518902], [-0.814994772052415, 51.56569055892733], [-0.815202529336662, 51.56519091397622], [-0.815219131565213, 51.56505170869626], [-0.815351636137841, 51.564671793906264], [-0.815511116853932, 51.56436408558186], [-0.815565592175225, 51.5642108755608], [-0.815662011458114, 51.564053592855515], [-0.815731002538058, 51.56389693250399], [-0.815762954470268, 51.56377766396064], [-0.815882314039101, 51.56307031436626], [-0.815899206541573, 51.563030920866616], [-0.815918960262566, 51.5629924554096], [-0.816100387305838, 51.56272812828101], [-0.816239061970809, 51.562387838558415], [-0.816351227865814, 51.56217946080997], [-0.816402225233145, 51.562104443964415], [-0.816445731089239, 51.56204014171416], [-0.816755073070336, 51.56173843863565], [-0.81682883069147, 51.5615089920632], [-0.81709149295673, 51.56100450196165], [-0.817126546068515, 51.5610435199925], [-0.817036868291134, 51.56144185218239], [-0.817602599672938, 51.56148891511105], [-0.817650902097453, 51.56129517879352], [-0.81772376875861, 51.56109989153342], [-0.818544773098936, 51.56114952106405], [-0.818940645385275, 51.56112652991029], [-0.819286252234888, 51.56087194248433], [-0.820505192935939, 51.560762809232635], [-0.821152924392013, 51.56109751750433], [-0.821401734784996, 51.56112699167495], [-0.821468077854438, 51.561127657861135], [-0.821837057068471, 51.56108460493917], [-0.822551882107614, 51.56083281445182], [-0.822991148836609, 51.56069335159132], [-0.823298868990794, 51.56056425765945], [-0.823427756279142, 51.560489119484224], [-0.823816316952276, 51.56018999039105], [-0.823841530161624, 51.56016326766115], [-0.823879440321637, 51.5600917131651], [-0.823939663402364, 51.55926686943448], [-0.824000930577316, 51.55924050793579], [-0.823876052668265, 51.55798579953388], [-0.823797968341331, 51.557154174451156], [-0.823813910366727, 51.55698348995032], [-0.824268965579194, 51.556733581409404], [-0.824612742777356, 51.55649154853787], [-0.826344281900068, 51.55484359477631], [-0.826657025878971, 51.55457337099326], [-0.827233265990788, 51.554040521447654], [-0.827929376968602, 51.55344502444081], [-0.828029419518581, 51.553368693973354], [-0.828246668974642, 51.55322159923911], [-0.828485269800709, 51.5530855074047], [-0.828605105979095, 51.55302466009866], [-0.829372820563392, 51.55267264797847], [-0.830416538296143, 51.552300003050114], [-0.830341853307235, 51.55217517181714], [-0.830015969895102, 51.55217192349864], [-0.82991663595149, 51.55216463892005], [-0.829524156953837, 51.55211486704629], [-0.829282415323888, 51.552092673855796], [-0.828838545910614, 51.55207835426137], [-0.828599504055965, 51.55206338004898], [-0.828680519991051, 51.55199764928292], [-0.828534433277995, 51.55195752639793], [-0.828384829125967, 51.55188589688778], [-0.827987906418731, 51.55167242458396], [-0.827957477145366, 51.551621766572], [-0.827834232346298, 51.55159086272802], [-0.827633977763617, 51.551525919798664], [-0.827259642164726, 51.55144395104261], [-0.826879262755715, 51.5513727108443], [-0.826619197529414, 51.551334143723224], [-0.825020961294276, 51.55117248609027], [-0.825087548806697, 51.55099511486544], [-0.825080332863119, 51.55093929339289], [-0.825041927300218, 51.55086247849746], [-0.82502361605882, 51.55078946149474], [-0.825044884876699, 51.55069166368164], [-0.825058487270179, 51.550667521970404], [-0.82509857658956, 51.550622964257876], [-0.825145597538488, 51.55058926609727], [-0.825325151596322, 51.5505056412203], [-0.824909915146001, 51.550164291306395], [-0.82525013660448, 51.550002248032946], [-0.825332063085088, 51.549957209837], [-0.825638185418255, 51.54977504214384], [-0.82578350044032, 51.54967668704559], [-0.825923116734683, 51.54957557721289], [-0.826170603160388, 51.54937393870707], [-0.826371785812396, 51.54917813090106], [-0.826492161334072, 51.549039961540565], [-0.826611394860751, 51.548890091280356], [-0.82670116630089, 51.54876420424681], [-0.826782355507479, 51.54863553380353], [-0.826823019292071, 51.54856850170786], [-0.827062757600335, 51.548106920435835], [-0.827101368877001, 51.54800749719491], [-0.827194201898492, 51.54770629998806], [-0.827307057244965, 51.54741159704493], [-0.827582602426052, 51.54684696658141], [-0.827901482950928, 51.54639156924703], [-0.828226190833503, 51.54604592938406], [-0.828636291311094, 51.545744301711125], [-0.82879259021163, 51.54566673370386], [-0.828904643767125, 51.545627388779295], [-0.829074413403866, 51.54558682127211], [-0.829642313890905, 51.54554213206049], [-0.831137752395514, 51.5457125947128], [-0.831296230672639, 51.545718668970665], [-0.831381409559054, 51.545715021306385], [-0.831520416985355, 51.54569302674314], [-0.831658465956176, 51.54565213966273], [-0.832162223002951, 51.54540897973132], [-0.832259763552867, 51.545373083913695], [-0.832342495362879, 51.54535232675641], [-0.832449690786029, 51.545333611293344], [-0.832560958333776, 51.54532482723805], [-0.832748224427793, 51.54533298427906], [-0.833594396864807, 51.5455158387706], [-0.833803468208608, 51.5455736658201], [-0.834066591719905, 51.54566080332341], [-0.834319302360527, 51.54576042533909], [-0.834632701147966, 51.545911902800114], [-0.834743597643834, 51.54597414830218], [-0.834972095381443, 51.546118487532766], [-0.835101437527799, 51.546192605160904], [-0.835308853525451, 51.54642845092972], [-0.835597379030446, 51.546650714213946], [-0.835675530378703, 51.54669644865621], [-0.835765285050956, 51.54673960061442], [-0.835946924814448, 51.54679895002405], [-0.836738145066418, 51.54693268079673], [-0.837616543696299, 51.54698454508781], [-0.837668585980954, 51.546979665457], [-0.837867989708348, 51.546964555807335], [-0.83797367625272, 51.54694851789646], [-0.838105566972017, 51.54692284834119], [-0.838233315283634, 51.54688994418392], [-0.838329229403341, 51.54686122067977], [-0.838482151664417, 51.546802489195365], [-0.839036827411148, 51.54642762424692], [-0.83955396219585, 51.54605418383688], [-0.840116011657223, 51.54567219327131], [-0.840736658187885, 51.54525391246058], [-0.840941426195899, 51.54514083988849], [-0.841049279937165, 51.54509604683764], [-0.841194847094701, 51.5450426342828], [-0.841299520083949, 51.545009498946165], [-0.841898633062652, 51.544870644649805], [-0.842282244574123, 51.54481328536381], [-0.842762474116396, 51.54475597844143], [-0.843565178344648, 51.54477737891959], [-0.844086979548171, 51.54484366398717], [-0.845732620874625, 51.545006428046236], [-0.847066038668597, 51.54519847249473], [-0.847735465249349, 51.545415455459946], [-0.84773690700669, 51.54541546961599], [-0.848634731053663, 51.54572550693968], [-0.849946581441456, 51.54620234699594], [-0.850255922443757, 51.54628810259981], [-0.850450510421732, 51.5463493547082], [-0.850677807173489, 51.54642891042725], [-0.850994850981171, 51.546552505063595], [-0.852786328510159, 51.547342426670774], [-0.85300310746802, 51.547496506935786], [-0.853571212311598, 51.54778799706584], [-0.854020445083318, 51.54798930492918], [-0.854581807452525, 51.548205193183556], [-0.85478620907829, 51.54827822314386], [-0.854963577157503, 51.54833660211785], [-0.855161244465997, 51.54839068294659], [-0.855663052553423, 51.5485088736389], [-0.856166529832507, 51.54867563412252], [-0.856279761006, 51.54870371304979], [-0.856530960852844, 51.54875111981111], [-0.856804082121709, 51.54878705024175], [-0.857112033920981, 51.54881432744164], [-0.857381573472553, 51.548820548731904], [-0.857549123049589, 51.54881049056259], [-0.857844479857821, 51.548764809719025], [-0.858057604662229, 51.54872012637499], [-0.858337617310588, 51.54865361386837], [-0.858552497890933, 51.54859635820055], [-0.859049392399301, 51.548450127924276], [-0.859439117962245, 51.5483792842905], [-0.859697682244768, 51.54836291412634], [-0.859779823131423, 51.54836551056866], [-0.860170027263243, 51.548390881318824], [-0.860456238387038, 51.54842243448379], [-0.861009536104037, 51.548500639150554], [-0.861158816462501, 51.54852906321894], [-0.861352413335375, 51.54857320311727], [-0.861544411683264, 51.54862362144007], [-0.861731905414109, 51.5486811891874], [-0.862073439754406, 51.548807688741114], [-0.86254414698236, 51.54901726458452], [-0.86282747298222, 51.54916477803516], [-0.863015068128655, 51.549276295417606], [-0.863120154717426, 51.549342054318615], [-0.863285809311142, 51.54946594721784], [-0.863418211576468, 51.54959311456195], [-0.863530092020445, 51.54973357070672], [-0.863653360363745, 51.549937978681236], [-0.863733641061499, 51.550131180181424], [-0.863790336700716, 51.5503448343906], [-0.863824973966162, 51.550691353426465], [-0.863841717303786, 51.55100353042492], [-0.863889686614544, 51.55116225019172], [-0.863971345177536, 51.55135816235228], [-0.864192531443895, 51.5518009005184], [-0.864636908176204, 51.552606367995786], [-0.864885616784935, 51.55304487507487], [-0.864984710926909, 51.55317801261536], [-0.865042267578469, 51.5532415116859], [-0.86524661818949, 51.553434113390985], [-0.866448255146234, 51.55464702695421], [-0.866553639357719, 51.55475954277147], [-0.86713929523259, 51.555454866418074], [-0.86728119491555, 51.55560729781788], [-0.867357192432134, 51.55568356216347], [-0.867846797612144, 51.55612348793147], [-0.867948777192819, 51.5561991033314], [-0.868039688780355, 51.55625572917072], [-0.868162193200772, 51.55631805467487], [-0.868334859667638, 51.55639345221028], [-0.868507816648064, 51.556457162985154], [-0.868686743286876, 51.556512838449954], [-0.868885971532242, 51.55656421341042], [-0.869870431325262, 51.55700170522159], [-0.870538382015661, 51.557289577406756], [-0.87065953954758, 51.55734829060127], [-0.870968323528286, 51.55751940747054], [-0.871084688448939, 51.55759695683154], [-0.871173919806704, 51.55766345498963], [-0.871421843971099, 51.55790412108149], [-0.871517352960249, 51.558008444760674], [-0.871560414081151, 51.55807539786269], [-0.871689483441928, 51.558339198343305], [-0.871715457861831, 51.558455441841], [-0.871819115572425, 51.558871857901316], [-0.872116688986198, 51.559438501590606], [-0.87224925001588, 51.559678057158926], [-0.872395481580982, 51.5598898694294], [-0.872503199025109, 51.56002578071336], [-0.872616797176149, 51.56015725249727], [-0.872767427555836, 51.560307962534345], [-0.873712440787397, 51.560887112412736], [-0.874019840047307, 51.56105730856152], [-0.874413245272104, 51.56124990894107], [-0.875159636577155, 51.56157807024888], [-0.875469862748955, 51.561692540724444], [-0.875618818634067, 51.561736229028845], [-0.87605776549836, 51.56183754414599], [-0.876366373823489, 51.56190074371407], [-0.87668521195865, 51.561958645316366], [-0.876968369886447, 51.56200091867397], [-0.877197163756339, 51.56202468778881], [-0.877516822654725, 51.5620493254706], [-0.878098847659676, 51.56208186543848], [-0.879220205739232, 51.56212315048378], [-0.879742407250114, 51.562124539056946], [-0.8803196812009, 51.56211566057546], [-0.88047709073344, 51.562109069498774], [-0.880781923890852, 51.5620912956137], [-0.881058065229737, 51.56206695318683], [-0.881262135404653, 51.56204012483733], [-0.881418631531618, 51.562011943580096], [-0.881649213834679, 51.56196288783239], [-0.882003250428868, 51.56187993977645], [-0.882376388095226, 51.56178278572967], [-0.882764299497775, 51.56167138432022], [-0.883194585739291, 51.561537905452155], [-0.883498576630078, 51.5614364931922], [-0.883756281221724, 51.56134003501421], [-0.884086956514705, 51.56120920221847], [-0.884407665982054, 51.56107287871968], [-0.885457870533961, 51.5606602434964], [-0.885606584631741, 51.56059601575753], [-0.88578613479336, 51.56050960117672], [-0.88595858283258, 51.56041862303493], [-0.886091760097573, 51.560340759581955], [-0.886521253482028, 51.56006159461465], [-0.886883345687433, 51.559824949307504], [-0.887389733197074, 51.559468282123994], [-0.887580604245187, 51.55927227271282], [-0.887708691217493, 51.559107139161064], [-0.888191015763102, 51.55861266662589], [-0.888192457957821, 51.55861268028735], [-0.888287760756616, 51.55849039596854], [-0.888562664893145, 51.558278995716826], [-0.888677108662246, 51.55814070717499], [-0.888887527216288, 51.55791161122132], [-0.889030158653071, 51.55774121885465], [-0.889203011709727, 51.557514464273005], [-0.88945350380216, 51.55717964382524], [-0.889600043815338, 51.556967026485395], [-0.889736358446423, 51.55670036168757], [-0.889858423154084, 51.55648571413559], [-0.889957478394766, 51.55626815130874], [-0.88999480235023, 51.556157006507235], [-0.890171676314085, 51.5555274577222], [-0.89040150985715, 51.554855248874496], [-0.891496918227321, 51.55316795557777], [-0.892148150167392, 51.55212836271704], [-0.892302414411729, 51.5517746441604], [-0.892679622502675, 51.55097074336506], [-0.892968782461996, 51.55046633574481], [-0.893655961353766, 51.54930928124159], [-0.894173495307085, 51.548604708475054], [-0.894625223197592, 51.54805597035748], [-0.895275002004698, 51.547308578527485], [-0.895581553072133, 51.54691762432374], [-0.89567259455686, 51.54679079793778], [-0.895853734572665, 51.54651645501248], [-0.896746527292651, 51.54508077321264], [-0.896901839906062, 51.544860136456265], [-0.897255891587921, 51.54494888564188], [-0.898115394177492, 51.545187148067974], [-0.89822539056202, 51.54523044209882], [-0.898280925208036, 51.54525973711452], [-0.898317695099433, 51.54528975512979], [-0.898473190139101, 51.54530020648797], [-0.899619101095523, 51.54544313546729], [-0.901006352145532, 51.54562517973134], [-0.901825064903737, 51.54570208025918], [-0.903152296119515, 51.54586195719927], [-0.903215411109321, 51.54587603470979], [-0.903297183099556, 51.545893883241035], [-0.903017403675823, 51.54655396139701], [-0.902616538461231, 51.54745118838641], [-0.902395351374664, 51.54801290343283], [-0.902224993241029, 51.54837997226972], [-0.902166365216381, 51.54859882282856], [-0.902146545476892, 51.54876318664974], [-0.902208891983797, 51.54892921824649], [-0.902230894835185, 51.549033728477525], [-0.902380735585514, 51.54999904656443], [-0.902673692529055, 51.551610411429984], [-0.902806620567669, 51.55250003963136], [-0.902816651036337, 51.55268266601908], [-0.902804979597758, 51.55292803179951], [-0.902756997764027, 51.55318384821566], [-0.902654701329301, 51.55353896524768], [-0.902427419928527, 51.55423280167036], [-0.901847751389036, 51.555843197130926], [-0.901770133963284, 51.556011515784924], [-0.90172081219273, 51.556082988265544], [-0.902203201151337, 51.55617741874876], [-0.906010818638152, 51.55679743475821], [-0.906204734572883, 51.556771367660915], [-0.906311884484255, 51.55675438267928], [-0.906358975073264, 51.55689599188705], [-0.90638590166065, 51.55691602462513], [-0.906615524939952, 51.55696492104195], [-0.907278267614382, 51.55705831304524], [-0.907858939004531, 51.55720578727805], [-0.908174621569804, 51.5572752632291], [-0.908339760107985, 51.55730647205926], [-0.908420198492941, 51.557320707807335], [-0.908923514869315, 51.557385632424236], [-0.909322889103033, 51.5574540848968], [-0.909506497855653, 51.557497152980005], [-0.909658336207082, 51.557541723987356], [-0.909754316957776, 51.55756959081508], [-0.909871264277585, 51.557625526703404], [-0.91002439519459, 51.55767640345812], [-0.91014009429463, 51.557724234915874], [-0.910363938659539, 51.55783421414451], [-0.910769828656022, 51.55805288423369], [-0.910899633150579, 51.55817457810929], [-0.911134211672749, 51.55843931338367], [-0.911191431662737, 51.558519870694006], [-0.911262279817118, 51.55863382382822], [-0.911345597527786, 51.558829717406], [-0.911347039740573, 51.55882973078292], [-0.911354152248679, 51.55895478193117], [-0.911501156990394, 51.55932300828838], [-0.911744284152759, 51.55977395051585], [-0.911784714781588, 51.55983277167005], [-0.911848028397377, 51.559899897522016], [-0.911951124589094, 51.55999256899618], [-0.912043240814804, 51.56006176008463], [-0.912343203354435, 51.560247072388215], [-0.91252735254784, 51.560389049785144], [-0.912663001694362, 51.56050809825428], [-0.913644040185922, 51.561715780647766], [-0.914729932802775, 51.56149024267299], [-0.915936249212879, 51.561720788632314], [-0.917099342153636, 51.56255696600573], [-0.917716153850379, 51.56209778262442], [-0.918510926061236, 51.561494569835055], [-0.919190082061234, 51.56187308324347], [-0.919265061021478, 51.56187467281339], [-0.919319677161742, 51.561883268238525], [-0.919395565855925, 51.56190734542486], [-0.919450182060758, 51.561915940789575], [-0.919451624375034, 51.56191595406745], [-0.919612764956992, 51.561873377936905], [-0.919684473323871, 51.562134798108005], [-0.919731696029427, 51.56227280618616], [-0.919795125391412, 51.562396576626476], [-0.919877773921036, 51.56250074208832], [-0.920024454979703, 51.56264236275641], [-0.920273793481437, 51.562835281288635], [-0.920455811890565, 51.56300779833283], [-0.92054707457537, 51.56311384087594], [-0.920622684574115, 51.56321074767881], [-0.920768557091237, 51.56344767224896], [-0.920815933327546, 51.56357938704838], [-0.92087756775181, 51.56365728255545], [-0.920897207761338, 51.56368084160506], [-0.920950783915168, 51.5637334861553], [-0.921113636188415, 51.563862665653886], [-0.921195103215065, 51.56395602921301], [-0.921351882125165, 51.56422002842434], [-0.921395592904906, 51.56432383493418], [-0.921420893006769, 51.56441308549212], [-0.921438619701684, 51.56451755238376], [-0.921413985191466, 51.56464410933019], [-0.92167481147157, 51.56453500840272], [-0.923479752756133, 51.56373602685831], [-0.924155377789785, 51.5634113259626], [-0.924873111301507, 51.56399247344971], [-0.924951149378637, 51.56404803772923], [-0.925274524870032, 51.56428388466152], [-0.92664770764064, 51.56515336065692], [-0.927393574791524, 51.56558368874587], [-0.927927453464337, 51.5659491340051], [-0.92835633038721, 51.56599441223158], [-0.928244524844939, 51.56725223174753], [-0.928125342518282, 51.56741209518939], [-0.9281054698832, 51.56745956981058], [-0.927839528670842, 51.568092855254655], [-0.93052584537502, 51.568532778436946], [-0.930434864440691, 51.56872077542371], [-0.930290537945866, 51.568968530677175], [-0.93032458943141, 51.568993118606556], [-0.930407160146686, 51.56904062792432], [-0.930494248489543, 51.56908008580425], [-0.93056005729139, 51.5691040638391], [-0.930644619283805, 51.56912821268005], [-0.930755210497826, 51.569149901051155], [-0.931002865082897, 51.56917193845677], [-0.931506345671459, 51.5692367670135], [-0.9319179887186, 51.56928007686346], [-0.93222706378822, 51.569328746497334], [-0.932389335623021, 51.56936169347699], [-0.932508352034028, 51.56939334769875], [-0.932608510110525, 51.56942932617174], [-0.932871163025979, 51.56955040480943], [-0.933086053531851, 51.569616199317096], [-0.933414865356232, 51.569684826955594], [-0.93386895042082, 51.56976448240679], [-0.934635570791928, 51.5700537823344], [-0.934785550106084, 51.57011898456062], [-0.934985327167408, 51.57021431104797], [-0.935122135234023, 51.5702874858722], [-0.935333952219633, 51.570423383659445], [-0.935683954424458, 51.570697207984594], [-0.935948857561102, 51.57084617434456], [-0.936321009353978, 51.57109861741231], [-0.936776166293208, 51.57138058458356], [-0.936874033955222, 51.57139136186155], [-0.937185388877335, 51.57140497135624], [-0.937358713203379, 51.57139754881963], [-0.937474500211682, 51.571382411871916], [-0.937604964789291, 51.57135661760672], [-0.938082770631526, 51.571224267138255], [-0.938303744516349, 51.57115343316592], [-0.938622419406116, 51.57103852370375], [-0.938583754985448, 51.57127375671787], [-0.938615426417796, 51.5714008261012], [-0.938651384040882, 51.57152973256723], [-0.938810396393867, 51.572013125409214], [-0.938917102284257, 51.5723881447753], [-0.938977920287056, 51.572564931845086], [-0.939147081147104, 51.57298457478389], [-0.93921529881351, 51.57340150695511], [-0.939295227462625, 51.57374930879435], [-0.939359853061118, 51.57401065198471]]]}}
diff --git a/benchmarks/json-data/integers.json b/benchmarks/json-data/integers.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/integers.json
@@ -0,0 +1,1 @@
+[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 39, 42, 44, 47, 50, 53, 56, 60, 63, 67, 72, 76, 81, 86, 91, 96, 102, 109, 115, 122, 130, 138, 146, 155, 165, 175, 186, 197, 209, 222, 236, 250, 266, 282, 299, 318, 337, 358, 380, 403, 428, 454, 482, 511, 543, 576, 611, 649, 688, 730, 775, 823, 873, 926, 983, 1043, 1107, 1175, 1247, 1323, 1404, 1490, 1582, 1679, 1781, 1890, 2006, 2129, 2259, 2398, 2544, 2700, 2865, 3041, 3227, 3425, 3634, 3857, 4093, 4343, 4609, 4891, 5191, 5509, 5846, 6204, 6583, 6986, 7414, 7868, 8349, 8860, 9403, 9978, 10589, 11237, 11925, 12655, 13430, 14252, 15124, 16050, 17032, 18075, 19181, 20355, 21601, 22923, 24326, 25815, 27396, 29072, 30852, 32740, 34744, 36871, 39128, 41523, 44064, 46762, 49624, 52661, 55884, 59305, 62935, 66787, 70875, 75213, 79817, 84702, 89887, 95389, 101227, 107423, 113998, 120976, 128381, 136239, 144578, 153427, 162818, 172784, 183360, 194583, 206493, 219132, 232545, 246778, 261883, 277912, 294923, 312975, 332131, 352460, 374034, 396928, 421223, 447005, 474365, 503400, 534212, 566911, 601610, 638433, 677511, 718980, 762987, 809688, 859247, 911840, 967652, 1026880, 1089734, 1156434, 1227217, 1302333, 1382046, 1466638, 1556408, 1651673, 1752769, 1860052, 1973902, 2094721, 2222934, 2358996, 2503385, 2656613, 2819219, 2991777, 3174898, 3369227, 3575451, 3794297, 4026539, 4272995, 4534536, 4812086, 5106625, 5419191, 5750889, 6102889, 6476435, 6872845, 7293518, 7739939, 8213686, 8716429, 9249944, 9816115, 10416939, 11054539, 11731166, 12449207, 13211198, 14019829, 14877955, 15788605, 16754994, 17780533, 18868844, 20023768, 21249383, 22550016, 23930257, 25394980, 26949356, 28598872, 30349352, 32206975, 34178300, 36270285, 38490317, 40846232, 43346349, 45999492, 48815029, 51802899, 54973651, 58338478, 61909260, 65698602, 69719882, 73987297, 78515911, 83321713, 88421668, 93833782, 99577160, 105672079, 112140056, 119003924, 126287916, 134017747, 142220706, 150925751, 160163614, 169966908, 180370243, 191410345, 203126189, 215559137, 228753081, 242754599, 257613123, 273381107, 290114218, 307871529, 326715729, 346713346, 367934976, 390455540, 414354543, 439716356, 466630515, 495192035, 525501749, 557666661, 591800322, 628023236, 666463282, 707256166, 750545902, 796485316, 845236589, 896971830, 951873682, 1010135966, 1071964368, 1137577163, 1207205986, 1281096650, 1359510014, 1442722903, 1531029087, 1624740315, 1724187420, 1829721484, 1941715077, 2060563573, 2186686548, 2320529259, 2462564214, 2613292844, 2773247272, 2942992191, 3123126858, 3314287206, 3517148098, 3732425698, 3960880011, 4203317554, 4460594215, 4733618266, 5023353573, 5330822998, 5657112012, 6003372524, 6370826950, 6760772526, 7174585891, 7613727944, 8079749004, 8574294281, 9099109685, 9656047991, 10247075377, 10874278366, 11539871197, 12246203633, 12995769265, 13791214310, 14635346955, 15531147272, 16481777734, 17490594386, 18561158687, 19697250088, 20902879371, 22182302812, 23540037202, 24980875800, 26509905246, 28132523526, 29854459026, 31681790754, 33620969802, 35678842122, 37862672691, 40180171161, 42639519077, 45249398761, 48019023960, 50958172379, 54077220194, 57387178688, 60899733121, 64627283986, 68582990784, 72780818484, 77235586822, 81963022620, 86979815309, 92303675844, 97953399235, 103948930895, 110311437058, 117063379497, 124228594829, 131832378662, 139901574895, 148464670491, 157551896043, 167195332496, 177429024407, 188289100133, 199813899374, 212044108527, 225022904322, 238796106249, 253412338321, 268923200725, 285383451995, 302851202324, 321388118716, 341059642687, 361935221296, 384088552321, 407597844432, 432546093294, 459021374572, 487117154867, 516932621682, 548573033590, 582150091830, 617782334651, 655595555791, 695723248569, 738307077168, 783497376747, 831453684183, 882345301285, 936351892486, 993664119121, 1054484312524, 1119027188325, 1187520604468, 1260206365627, 1337341076854, 1419197049486, 1506063262491, 1598246382662, 1696071847252, 1799885012878, 1910052374747, 2026962860500, 2151029203266, 2282689398739, 2422408251457, 2570679015712, 2728025136906, 2895002099486, 3072199387991, 3260242568131, 3459795495242, 3671562657914, 3896291665080, 4134775885316, 4387857247705, 4656429214122, 4941439933460, 5243895588908, 5564863950114, 5905478142772, 6266940648935, 6650527552175, 7057593042589, 7489574197539, 7947996055022, 8434476997558, 8950734465625, 9498591020797, 10079980779998, 10696956243580, 11351695541337, 12046510122031, 12783852913581, 13566326982715, 14396694724673, 15277887615381, 16213016560543, 17205382878181, 18258489953389, 19376055606456, 20562025218016, 21820585657560, 23156180064488, 24573523533875, 26077619762337, 27673778712750, 29367635360200, 31165169585327, 33072727285306, 35097042776985, 37245262571278, 39524970602741, 41944215003394, 44511536515321, 47235998642351, 50127219647252, 53195406507421, 56451390948928, 59906667686130, 63573435001862, 67464637811456, 71594013362620, 75976139732519, 80626487293267, 85561473327514, 90798519986944, 96356115798305, 102253880934088, 108512636478302, 115154477931865, 122202853217119, 129682645456833, 137620260819954, 146043721744222, 154982765864743, 164468950997792, 174535766550465, 185218751749486, 196555621106568, 208586397563259, 221353553785311, 234902162105402, 249280053643550, 264537987166964, 280729828285480, 297912739615178, 316147382581544, 335498131574595, 356033301212013, 377825387512598, 400951323831468, 425492752460545, 451536312853150, 479173947490266, 508503226468250, 539627691953919, 572657223723034, 607708427072674, 644905044476938, 684378392439283, 726267825083707, 770721226121430, 817895530929871, 867957280587026, 921083209817197, 977460870923688, 1037289295911185, 1100779699135317, 1168156222959992, 1239656729054927, 1315533638126921, 1396054821049394, 1481504544536185, 1572184474698156, 1668414742025481, 1770535071555377, 1878905982215138, 1993910059574563, 2115953306501003, 2245466576485316, 2382907094698829, 2528760072151156, 2683540418647385, 2847794560591953]
diff --git a/benchmarks/json-data/jp10.json b/benchmarks/json-data/jp10.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/jp10.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"2458313","profile_image_url":"http://a2.twimg.com/profile_images/1203653060/fure091226_normal.png","created_at":"Thu, 27 Jan 2011 20:30:04 +0000","from_user":"19princess","id_str":"30724239224995840","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6d77\u6674\u300c\u672c\u65e5\u306e\u6771\u4eac\u306e\u304a\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3067\u3057\u3087\u3046\u3002\u6700\u9ad8\u6c17\u6e29\u306f8\u5ea6\u3001\u6700\u4f4e\u6c17\u6e29\u306f1\u5ea6\u3067\u3059\u3002\u3042\u306a\u305f\u306e\u4eca\u65e5\u306e\u4eba\u751f\u306b\u3068\u3073\u3063\u304d\u308a\u306e\u304a\u5929\u6c17\u3092\u2665\u300d","id":30724239224995840,"from_user_id":2458313,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://babyprincess.sakura.ne.jp/about/&quot; rel=&quot;nofollow&quot;&gt;\u5929\u4f7f\u5bb6\u306e\u88cf\u5c71&lt;/a&gt;"},{"from_user_id_str":"66578965","profile_image_url":"http://a0.twimg.com/profile_images/1183763267/fossetta_normal.png","created_at":"Thu, 27 Jan 2011 20:00:04 +0000","from_user":"Fossetta_Tokyo","id_str":"30716689779785729","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059!!\u6771\u4eac\u90fd\u3001\u672c\u65e5\u306e\u304a\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3002\u6700\u9ad8\u6c17\u6e298\u5ea6\u3001\u6700\u4f4e\u6c17\u6e291\u5ea6\u3002\u6771\u4eac\u5730\u65b9\u3067\u306f\u3001\u7a7a\u6c17\u306e\u4e7e\u71e5\u3057\u305f\u72b6\u614b\u304c\u7d9a\u3044\u3066\u3044\u307e\u3059\u3002\u706b\u306e\u53d6\u308a\u6271\u3044\u306b\u6ce8\u610f\u3057\u3066\u4e0b\u3055\u3044\u3002\u4f0a\u8c46\u8af8\u5cf6\u3068\u5c0f\u7b20\u539f\u8af8\u5cf6\u306b\u306f\u3001\u5f37\u98a8\u3001\u6ce2\u6d6a\u3001\u4e7e\u71e5\u3001\u971c\u306e\u6ce8\u610f\u5831\u3092\u767a\u8868\u4e2d\u3067\u3059\u3002","id":30716689779785729,"from_user_id":66578965,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bit.ly/Fossetta&quot; rel=&quot;nofollow&quot;&gt;\u30d5\u30a9\u30bb\u30c3\u30bf ver.3.1.1&lt;/a&gt;"},{"from_user_id_str":"104041146","profile_image_url":"http://a2.twimg.com/profile_images/863965118/001jwatokyo_normal.jpg","created_at":"Thu, 27 Jan 2011 19:44:33 +0000","from_user":"jwa_tokyo","id_str":"30712787537756160","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6c17\u8c61\u5e81\u304b\u3089\u6771\u4eac\u306e\u5929\u6c17\u4e88\u5831\u304c\u767a\u8868\u3055\u308c\u307e\u3057\u305f\u3000\u305d\u306e\u5929\u6c17\u4e88\u5831\u3092\u3053\u3053\u3067\u3064\u3076\u3084\u3053\u3046\u304b\u306a\u3041\uff5e\uff1f\u3000\u8003\u3048\u4e2d\u3000\u307e\u3066\u6b21\u53f7\uff08\u7b11","id":30712787537756160,"from_user_id":104041146,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.docodemo.jp/twil/&quot; rel=&quot;nofollow&quot;&gt;Twil2 (Tweet Anytime, Anywhere by Mail)&lt;/a&gt;"},{"from_user_id_str":"144500192","profile_image_url":"http://a3.twimg.com/a/1294874399/images/default_profile_3_normal.png","created_at":"Thu, 27 Jan 2011 18:59:33 +0000","from_user":"kyo4to4","id_str":"30701462774358016","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u90fd \u516b\u4e08\u5cf6 - \u4eca\u65e5\u306e\u5929\u6c17\u306f\u30fb\u30fb\u30fb\u66c7\u306e\u3061\u6674\u3067\u3059\u306e\uff01","id":30701462774358016,"from_user_id":144500192,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/kyo4to4&quot; rel=&quot;nofollow&quot;&gt;lost-sheep-bot&lt;/a&gt;"},{"from_user_id_str":"165724582","profile_image_url":"http://a0.twimg.com/profile_images/1222842347/163087_1256281064506_1753997852_484926_2761052_n_normal.jpg","created_at":"Thu, 27 Jan 2011 17:39:06 +0000","from_user":"Rifqi_19931020","id_str":"30681213748387840","metadata":{"result_type":"recent"},"to_user_id":113796067,"text":"@CHLionRagbaby \u30b1\u30f3\u3061\u3083\u3093\u3001\u671d\u4eca\u307e\u3067\u306e\u81ea\u5206\u306e\u30db\u30fc\u30e0\u30a8\u30ea\u30a2\u304b\u3089\u307e\u3060\u975e\u5e38\u306b\u5bd2\u3044\u3068\u96e8\u304c\u964d\u3063\u3066\u3044\u305f..\u3069\u306e\u3088\u3046\u306b\u73fe\u5728\u306e\u6771\u4eac\u306e\u5929\u6c17\uff1f","id":30681213748387840,"from_user_id":165724582,"to_user":"CHLionRagbaby","geo":null,"iso_language_code":"ja","to_user_id_str":"113796067","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"120911929","profile_image_url":"http://a0.twimg.com/profile_images/772435076/20100312___capture2_normal.png","created_at":"Thu, 27 Jan 2011 17:28:30 +0000","from_user":"Cirno_fan","id_str":"30678546020040705","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u65e5\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u3001\u66c7\u6642\u3005\u6674\u3067\u6700\u9ad8\u6c17\u6e29\u306f8\u2103\uff01 \u6700\u4f4e\u6c17\u6e29\u306f2\u2103\u3060\u3063\u305f\u3088\uff01 RT @mimi22999 \uff08\uff65\u2200\uff65\uff09\uff4c\u3001\u865a\u5f31\u306a\u8005\u306b\u3068\u3063\u3066\u3001\u6717\u3089\u304b\u306a\u9854\u306f\u4e0a\u5929\u6c17\u3068\u540c\u3058\u304f\u3089\u3044\u3046\u308c\u3057\u3044\u3082\u306e\u3060\u3002\u30d5\u30e9\u30f3\u30af\u30ea\u30f3 #tenki #bot","id":30678546020040705,"from_user_id":120911929,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://blog.livedoor.jp/fairycirno/archives/34686.html&quot; rel=&quot;nofollow&quot;&gt;\u5e7b\u60f3\u90f7 \u9727\u306e\u6e56&lt;/a&gt;"},{"from_user_id_str":"65976527","profile_image_url":"http://a0.twimg.com/profile_images/452810990/little_italies_____normal.jpg","created_at":"Thu, 27 Jan 2011 17:00:03 +0000","from_user":"heta_weather01","id_str":"30671388754845696","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u30d8\u30bf\u5929\u3011Tere hommikust.\u30a8\u30b9\u30c8\u30cb\u30a2\u3067\u3059\u3002\u4eca\u65e5\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3067\u660e\u65e5\u306f\u66c7\u308a\u3067\u3059\u3002\u3061\u306a\u307f\u306b\u50d5\u306e\u3068\u3053\u308d\u3067\u306f\u66c7\u308a\u3067\u6c17\u6e29-7\u2103\u3067\u3059\u3002\u3061\u306a\u307f\u306b\u30b9\u30ab\u30a4\u30d7\u306e\u958b\u767a\u672c\u90e8\u306f\u50d5\u306e\u5bb6\u306b\u3042\u308b\u3093\u3067\u3059\u3002","id":30671388754845696,"from_user_id":65976527,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www15.atpages.jp/~kageyanma/&quot; rel=&quot;nofollow&quot;&gt;\u5730\u7403\u306e\u4e2d&lt;/a&gt;"},{"from_user_id_str":"7278433","profile_image_url":"http://a3.twimg.com/profile_images/1218965303/michael-1_normal.png","created_at":"Thu, 27 Jan 2011 16:50:16 +0000","from_user":"shimohiko","id_str":"30668926035689472","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3042\u308a\u3002\n\u3010\u7f8e\u4eba\u5929\u6c17/\u6771\u4eac\u3011\u7f8e\u4eba\u5929\u6c17\u30ad\u30e3\u30b9\u30bf\u30fc\u306e&quot;\u3055\u3042\u3084\u3093\u3055\u3093&quot;\u306b\u3088\u308b\u3068\u300c1/29(\u571f)\u306f\u304f\u3082\u308a\u3067\u3001\u964d\u6c34\u78ba\u738740%\u3001\u6700\u9ad8\u6c17\u6e29\u306f6\u2103\u3067\u6700\u4f4e\u6c17\u6e29\u306f1\u2103\u3067\u3059\u300d\u7f8e\u4eba\u5929\u6c17\u21d2http://bit.ly/djB8th http://twitpic.com/3twnl0 #bt_tenki","id":30668926035689472,"from_user_id":7278433,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bijintenki.jp&quot; rel=&quot;nofollow&quot;&gt;bijintenki.jp&lt;/a&gt;"},{"from_user_id_str":"61770","profile_image_url":"http://a3.twimg.com/profile_images/1206955079/tw172a_normal.png","created_at":"Thu, 27 Jan 2011 16:40:52 +0000","from_user":"rsky","id_str":"30666561853333504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3075\u3068\u591c\u7a7a\u3092\u898b\u4e0a\u3052\u3066\u30aa\u30ea\u30aa\u30f3\u304c\u898b\u3048\u306a\u304f\u3066\u300c\u6771\u4eac\u306b\u306f\u7a7a\u304c\u306a\u3044\u300d\u3068\u667a\u6075\u5b50\u306e\u3088\u3046\u306a\u3053\u3068\u3092\u601d\u3063\u305f\u308f\u3051\u3060\u304c\u3001\u305f\u3076\u3093\u534a\u5206\u3050\u3089\u3044\u306f\u5929\u6c17\u306e\u305b\u3044\u3067\u3059","id":30666561853333504,"from_user_id":61770,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"103259265","profile_image_url":"http://a0.twimg.com/profile_images/767857973/anime_icon_normal.gif","created_at":"Thu, 27 Jan 2011 16:37:42 +0000","from_user":"liveshowonly","id_str":"30665765698928640","metadata":{"result_type":"recent"},"to_user_id":null,"text":"iPhone\u5929\u6c17\u3002\u6771\u4eac4\u2103\u3063\u3066\u7d50\u69cb\u5bd2\u304f\u306a\u3044\u3058\u3083\u3093\u3002\uff08\u78ba\u304b\u306b\u3082\u306e\u51c4\u304f\u5bd2\u3044\u8a33\u3067\u306f\u7121\u3044\uff09\u3002\u798f\u5ca1\u5e02\u306f1\u2103\u3060\u3002\u52dd\u3061\u3060\u305c\u3002Rock'n'roll","id":30665765698928640,"from_user_id":103259265,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"165242761","profile_image_url":"http://a1.twimg.com/profile_images/1147334744/SN3E00600001_normal.jpg","created_at":"Thu, 27 Jan 2011 16:37:35 +0000","from_user":"deuxavril0502","id_str":"30665736556912640","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6b8b\u5ff5\u3001\u79c1\u306f\u6c96\u7e04\u3067\u3059(&gt;_&lt;)\u3067\u3082\u304a\u5929\u6c17\u826f\u3055\u305d\u3046\u3067\u826f\u304b\u3063\u305f\u306d\u3002\u3053\u3061\u3089\u306f\u96e8\u3088\uff5eRT @rinandy2010: \u305d\u3046\u3067\u3059\u3063\u266a\u51fa\u5f35\u3067(^^)\u304a\u306d\u3048\u3055\u307e\u306f\u6771\u4eac\u3067\u3059\u304b\uff1f\u3081\u3063\u3061\u3083\u5929\u6c17\u826f\u304f\u3066\u3073\u3063\u304f\u308a\u3067\u3059\u3002\u624b\u888b\u3068\u304b\u5168\u7136\u3044\u3089\u306a\u3044\u3067\u3059\u306d\u30fc RT @deuxavril0502 \u6771\u4eac\u306a\u306e\u30fc\uff1f","id":30665736556912640,"from_user_id":165242761,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"163900288","profile_image_url":"http://a1.twimg.com/profile_images/1210224823/icon12945064955238_normal.jpg","created_at":"Thu, 27 Jan 2011 16:24:37 +0000","from_user":"nyao_yurichan","id_str":"30662472734089216","metadata":{"result_type":"recent"},"to_user_id":100985873,"text":"@ray_ko302 \u767a\u898b\u3042\u308a\u304c\u3068\u3067\u3059\u3045\u3002\u3053\u3061\u3089\u3067\u3082\u3088\u308d\u3057\u304f\u306d\u3002\u6771\u4eac\u306f\u4eca\u65e5\u3082\u4e7e\u71e5\u3067\u5927\u5909\u3088\u3002\u305d\u3063\u3061\u3068\u771f\u9006\u306e\u5929\u6c17\u3060\u306d\u3002\u30a2\u30a4\u30b9\u30d0\u30fc\u30f3\u304d\u3092\u3064\u3051\u3066\u3088\u306d\u3002","id":30662472734089216,"from_user_id":163900288,"to_user":"ray_ko302","geo":null,"iso_language_code":"ja","to_user_id_str":"100985873","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"49227098","profile_image_url":"http://a3.twimg.com/profile_images/965007882/____normal.jpg","created_at":"Thu, 27 Jan 2011 15:52:26 +0000","from_user":"dosannko6","id_str":"30654371016478720","metadata":{"result_type":"recent"},"to_user_id":108570870,"text":"@peke_hajiP \u4ffa\u304c\u6771\u4eac \u6765\u3066\u6700\u521d\u306b\u9a5a\u3044\u305f\u306e\u304c\u3001\u5929\u6c17\u4e88\u5831\u3067\u82b1\u7c89\u60c5\u5831\u304c\u6d41\u308c\u308b\u3053\u3068\u3067\u3001\u6700\u521d\u306b\u8a66\u3057\u305f\u306e\u304c \u30b4\u30ad\u69d8 \u53ec\u559a\u306e\u5100\u5f0f\u3067\u3059\u304a\uff1f","id":30654371016478720,"from_user_id":49227098,"to_user":"peke_hajip","geo":null,"iso_language_code":"ja","to_user_id_str":"108570870","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"71148934","profile_image_url":"http://a0.twimg.com/profile_images/1209223630/image_normal.jpg","created_at":"Thu, 27 Jan 2011 15:46:49 +0000","from_user":"123keiko","id_str":"30652958311981058","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u9727\u5cf6\u306e\u964d\u7070\u306e\u30cb\u30e5\u30fc\u30b9\u3092\u898b\u3066\u601d\u3044\u51fa\u3057\u307e\u3057\u305f\u3002\u4e0a\u4eac\u3057\u305f\u59cb\u3081\u306e\u9803\u3001\u6771\u4eac\u306f1\u5e74\u4e2d\u3001\u7070\u304c\u964d\u3089\u306a\u3044\u304b\u3089\u7a7a\u6c17\u304c\u6f84\u3093\u3067\u3066\u904e\u3054\u3057\u3084\u3059\u3044\u306a\u3041\u3001\u3068\u601d\u3063\u305f\u306a\u3041\u3001\u3063\u3066\u3002\n\u5b9f\u5bb6\u306f\u51ac\u306e\u5b63\u7bc0\u98a8\u3067\u685c\u5cf6\u306e\u7070\u304c\u964d\u308b\u5730\u533a\u3067\u3057\u305f\u3002\u9e7f\u5150\u5cf6\u306e\u5929\u6c17\u4e88\u5831\u3067\u306f\u3001\u6bce\u65e5\u3001\u685c\u5cf6\u4e0a\u7a7a\u306e\u98a8\u5411\u304d\u4e88\u5831\u304c\u3067\u307e\u3059\u3002\u3053\u308c\u304b\u3089\u306f\u9727\u5cf6\u3082\u304b\u306a\uff1f","id":30652958311981058,"from_user_id":71148934,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"91124773","profile_image_url":"http://a3.twimg.com/profile_images/1139308356/prof101007_3-1_normal.jpg","created_at":"Thu, 27 Jan 2011 15:43:35 +0000","from_user":"sanposuruhito","id_str":"30652146277945345","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u5bb5\u306e\u90fd\u5fc3\u306f\u3001\u8eab\u3082\u5f15\u304d\u7de0\u307e\u308b\u3068\u3044\u3046\u3088\u308a\u306f\u51cd\u3048\u308b\u7a0b\u306e\u51b7\u6c17\u3092\u611f\u3058\u308b\u5bd2\u3044\u591c\u3067\u3059\u3002\u660e\u65e5\u65e5\u4e2d\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u3001\u5915\u65b9\u306b\u591a\u5c11\u96f2\u304c\u51fa\u308b\u5834\u6240\u304c\u3042\u308a\u305d\u3046\u306a\u3082\u306e\u306e\u6982\u306d\u6674\u308c\u7a7a\u304c\u5e83\u304c\u308a\u7d9a\u3051\u305d\u3046\u3067\u3059\u3002\u6700\u9ad8\u6c17\u6e29\u306f\u30015-6\u5ea6\u4f4d\u3068\u306a\u308a\u305d\u3046\u3067\u3059\u3002#weather_tokyo","id":30652146277945345,"from_user_id":91124773,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://projects.playwell.jp/go/Saezuri&quot; rel=&quot;nofollow&quot;&gt;Saezuri&lt;/a&gt;"}],"max_id":30724239224995840,"since_id":28179956995457024,"refresh_url":"?since_id=30724239224995840&q=%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97","next_page":"?page=2&max_id=30724239224995840&lang=ja&q=%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97","results_per_page":15,"page":1,"completed_in":0.104827,"warning":"adjusted since_id to 28179956995457024 (), requested since_id was older than allowed -- since_id removed for pagination.","since_id_str":"28179956995457024","max_id_str":"30724239224995840","query":"%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97"}
diff --git a/benchmarks/json-data/jp100.json b/benchmarks/json-data/jp100.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/jp100.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"178045354","profile_image_url":"http://a0.twimg.com/profile_images/1214479381/154722_10100141954893059_808622_55276626_7445050_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:40:04 +0000","from_user":"ChuriSta_gt","id_str":"41190705623732224","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3072\u3089\u304c\u306a\u306e\u300c\u3064\u300d\u306f\u3082\u3046Twitter\u306e\u300c\u3064\u300d\u3060\uff01","id":41190705623732224,"from_user_id":178045354,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b for iPhone&lt;/a&gt;"},{"from_user_id_str":"71746558","profile_image_url":"http://a2.twimg.com/profile_images/591641547/wwd_normal.gif","created_at":"Fri, 25 Feb 2011 17:40:02 +0000","from_user":"fuckkilldiestar","id_str":"41190699571494912","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u306b\u3057\u3066\u3082Twitter\u3084pixiv\u96e2\u308c\u3092\u3069\u3046\u306b\u304b\u3057\u308d\u674f\u4ec1\u30d6\u30eb\u30de","id":41190699571494912,"from_user_id":71746558,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"131230176","profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","created_at":"Fri, 25 Feb 2011 17:39:58 +0000","from_user":"proory_bot","id_str":"41190683922546688","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30ea\u30cd\u30f3\u30dd\u30fc\u30c1 http://bit.ly/btjqlH","id":41190683922546688,"from_user_id":131230176,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://proory.com/&quot; rel=&quot;nofollow&quot;&gt;proory tems&lt;/a&gt;"},{"from_user_id_str":"120359038","profile_image_url":"http://a1.twimg.com/profile_images/946521484/200805161826000_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:58 +0000","from_user":"tukinosuke","id_str":"41190680835391488","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @fuefukioyasumi: \u3082\u3046\u3044\u3044\u3002\u300c\u671d\u751f\u300d\u306a\u3093\u304b\u3044\u3044\u3002BBC\u3082CNN\u3082\u82f1\u8a9e\u653e\u9001\u3060\u3002\u307f\u3093\u306a\u3001\u30c6\u30ec\u30d3\u3092\u3076\u3061\u3063\u3068\u5207\u3063\u3066Twitter\u3092\u898b\u3088\u3046\u3002\u3053\u3053\u306b\u300c\u751f\u304d\u305f\u60c5\u5831\u300d\u304c\u6d41\u308c\u3066\u3044\u308b\u3002\u300c\u751f\u304d\u305f\u53eb\u3073\u300d\u304c\u3042\u308b\u3002\u3053\u3053\u304b\u3089\u3067\u3082\u6b74\u53f2\u306e\u8ee2\u63db\u70b9\u3092\u611f\u3058\u308b\u4e8b\u304c\u3067\u304d\u308b\u306e\u3060\u3002 @gjmorley #libjp","id":41190680835391488,"from_user_id":120359038,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"166512109","profile_image_url":"http://a3.twimg.com/profile_images/1224583217/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:50 +0000","from_user":"yurii1129","id_str":"41190649839620096","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u6c17\u4ed8\u3044\u305f\u2026\u307f\u3043\u304f\u3093\u306eTwitter\u540d\u3001\u3084\u307e\u306d\u3084\u3093(\uffe3\u25c7\uffe3;)","id":41190649839620096,"from_user_id":166512109,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"228999619","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png","created_at":"Fri, 25 Feb 2011 17:39:49 +0000","from_user":"takami926","id_str":"41190644793745408","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u7530\u539f\u3055\u3093\u3001\u5fdc\u63f4\u3057\u3066\u307e\u3059\u3002WEB\u3082TWITTER\u3082\u62dd\u898b\u3057\u3066\u307e\u3059\u3002\u7530\u539f\u3055\u3093\u304c\u653f\u6cbb\u5bb6\u306b\u306a\u3063\u3066\u3001\u65e5\u672c\u3092\u5909\u3048\u3066\u304f\u3060\u3055\u3044\u3002\u5c16\u95a3\u3001\u5317\u65b9\u554f\u984c\u5171\u306b\u65e5\u672c\u306e\u653f\u6cbb\u306e\u5931\u6557\u3067\u3059\u3002\u8a55\u8ad6\u5bb6\u306f\u8272\u3005\u8a00\u3063\u3066\u307e\u3059\u304c\u3001\u4e2d\u6771\u307b\u3069\u56fd\u6c11\u306e\u71b1\u6c17\u304c\u7121\u304f\u3001\u683c\u5dee\u304c\u3042\u308a\u3001\u4f55\u3082\u5909\u308f\u3089\u306a\u3044\u666f\u6c17\u4f4e\u8ff7\u306e\u65e5\u672c\u306b\u56fd\u6c11\u306f\u8ae6\u3081\u3066\u308b\u3093\u3067\u3059\u3002","id":41190644793745408,"from_user_id":228999619,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"151773701","profile_image_url":"http://a0.twimg.com/profile_images/1213699753/obi_nao_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:44 +0000","from_user":"obi_nao","id_str":"41190622949941248","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3060\u3044\u3076\u5e74\u4e0b\u306e\u5f8c\u8f29\u306b\u3001\u30d3\u30b8\u30cd\u30b9\u3084\u308b\u306a\u3089\u771f\u5263\u306bTwitter\u3084\u308c\uff01\u3063\u3066\u6012\u3089\u308c\u305f\u3002\u306a\u306e\u3067\u4eca\u65e5\u304b\u3089\u771f\u5263\u306b\u3064\u3076\u3084\u304f\u3053\u3068\u306b\u3057\u307e\u3059\u3002\u3088\u308d\u3057\u304f\u3067\u3059\u3002","id":41190622949941248,"from_user_id":151773701,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.flight.co.jp/iPhone/TweetMe/&quot; rel=&quot;nofollow&quot;&gt;TweetMe for iPhone&lt;/a&gt;"},{"from_user_id_str":"20817229","profile_image_url":"http://a0.twimg.com/profile_images/1212012721/205_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:43 +0000","from_user":"allte","id_str":"41190619804082176","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u7206\u7b11\u3057\u3066\u547c\u5438\u56f0\u96e3\u3067\u75d9\u6523\u3059\u308b\u5618\u304f\u3093\u304c\u898b\u308c\u308b\u306e\u306fTwitter\u3060\u3051","id":41190619804082176,"from_user_id":20817229,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.movatwi.jp&quot; rel=&quot;nofollow&quot;&gt;www.movatwi.jp&lt;/a&gt;"},{"from_user_id_str":"166907967","profile_image_url":"http://a2.twimg.com/profile_images/1250526230/___normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:43 +0000","from_user":"NTTYAHOOOOOOOI","id_str":"41190618235412480","metadata":{"result_type":"recent"},"to_user_id":106469594,"text":"@takahirororo \u3066\u304b\u4f55\u3067twitter\u4e0a\u3067\u30a2\u30c9\u30d0\u30a4\u30b9\u3082\u3089\u3063\u3066\u3093\u306d\u3093\uff57","id":41190618235412480,"from_user_id":166907967,"to_user":"takahirororo","geo":null,"iso_language_code":"ja","to_user_id_str":"106469594","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"82581287","profile_image_url":"http://a0.twimg.com/profile_images/774721566/miyaru2_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:38 +0000","from_user":"kine_rahchaos","id_str":"41190598132244480","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30a2\u30aa\u30b7\u30de\u3055\u3093\u304cTwitter\u59cb\u3081\u305f\u3060\u3068\u2026","id":41190598132244480,"from_user_id":82581287,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"136633905","profile_image_url":"http://a2.twimg.com/profile_images/1247161991/yama_normal.png","created_at":"Fri, 25 Feb 2011 17:39:35 +0000","from_user":"yamachi39","id_str":"41190584706285568","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3084\u3063\u3071\u308amixi\u3088\u308atwitter\u306e\u304c\u597d\u304d\u304b\u3082","id":41190584706285568,"from_user_id":136633905,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://jigtwi.jp/?p=1&quot; rel=&quot;nofollow&quot;&gt;jigtwi&lt;/a&gt;"},{"from_user_id_str":"44029295","profile_image_url":"http://a2.twimg.com/profile_images/1112965522/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:32 +0000","from_user":"no2yosee","id_str":"41190572769280000","metadata":{"result_type":"recent"},"to_user_id":97721124,"text":"@hn0345 \u3042\u3001\u500b\u4eba\u7684\u306b\u306f\u4eca\u306ftwitter\u306e\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u306b\u66f8\u3044\u3066\u3042\u308b\u30d6\u30ed\u30b0\u306e\u30e6\u30cb\u30c3\u30c8\u3092\u306e\u3093\u3073\u308a\u3084\u3063\u3066\u307e\u3059w","id":41190572769280000,"from_user_id":44029295,"to_user":"hn0345","geo":null,"iso_language_code":"ja","to_user_id_str":"97721124","source":"&lt;a href=&quot;http://www.flight.co.jp/iPhone/TweetMe/&quot; rel=&quot;nofollow&quot;&gt;TweetMe for iPhone&lt;/a&gt;"},{"from_user_id_str":"149872179","profile_image_url":"http://a0.twimg.com/profile_images/1145770150/Winter11_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:31 +0000","from_user":"xmyyyxx","id_str":"41190566951653376","metadata":{"result_type":"recent"},"to_user_id":95069405,"text":"@rindofu \u653b\u7565\u672c\u3042\u308c\u3070\u3044\u3044\u306e\u306b\u3063\u3066\u601d\u3044\u307e\u3059(T\u03c9T)/~~~ \u79c1\u3082\u76f4\u3057\u305f\u3044\u3068\u3053\u3044\u3063\u3071\u3044\u3060\u3051\u3069\u3001\u3042\u306860\u5e74\u304f\u3089\u3044\u3044\u304d\u3089\u308c\u308b\u306f\u305a\u3060\u3057\u3001\u306e\u3093\u3073\u308a\u76f4\u308c\u3070\u3044\u3044\u306a\u3042 \u304a\u3084\u3059\u307f\u3067\u3059^^\uff01\u308a\u3093\u3055\u3093\u3068twitter\u3067\u4ef2\u826f\u304f\u306a\u308c\u3066\u3088\u304b\u3063\u305f\u3067\u3059\u3063","id":41190566951653376,"from_user_id":149872179,"to_user":"rindofu","geo":null,"iso_language_code":"ja","to_user_id_str":"95069405","source":"&lt;a href=&quot;http://twtr.jp&quot; rel=&quot;nofollow&quot;&gt;Keitai Web&lt;/a&gt;"},{"from_user_id_str":"105579892","profile_image_url":"http://a0.twimg.com/profile_images/1212950455/love_happy_pink_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:30 +0000","from_user":"love_happy_pink","id_str":"41190566494601216","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u305d\u308c\u898b\u305f\u3044\u306a\u266aRT @kazukt \u3046\u308b\u304a\u307c\u7d75\u3001\u4ed6\u306e\u4eba\u306e\u3082\u898b\u3066\u3044\u305f\u3089\u3084\u305f\u3089\u30de\u30f3\u30ac\u306e\u30ad\u30e3\u30e9\u30af\u30bf\u30fc\u3067\u3080\u3061\u3083\u304f\u3061\u3083\u4e0a\u624b\u3044\u4eba\u304c\uff01\u2026\u3068\u3001\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u898b\u305f\u3089\u3001\u306a\u3093\u3068\u3054\u672c\u4eba\u304c\u66f8\u3044\u3066\u3044\u3089\u3063\u3057\u3083\u3063\u305f\u3002Twitter\u3063\u3066\u30b9\u30b4\u30a4\u308f\u3002","id":41190566494601216,"from_user_id":105579892,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.nibirutech.com/&quot; rel=&quot;nofollow&quot;&gt;TwitBird iPad&lt;/a&gt;"},{"from_user_id_str":"16996368","profile_image_url":"http://a0.twimg.com/profile_images/1198892387/pochi_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:30 +0000","from_user":"HyoYoshikawa","id_str":"41190564187611136","metadata":{"result_type":"recent"},"to_user_id":1800565,"text":"@shinichiro_beck \u73fe\u5730\u304b\u3089\u306a\u3089\u826f\u304f\u3066\u4ed6\u306e\u5730\u57df\u304b\u3089\u3060\u4f59\u8a08\u306a\u3089\u3001\u4f55\u306e\u305f\u3081\u306bTwitter\u304c\u3042\u308b\u306e\u304b\u308f\u304b\u3089\u306a\u3044\u3088\u3002\u3044\u307e\u8d77\u304d\u3066\u308b\u3053\u3068\u306e\u8aac\u660e\u3082\u3064\u304b\u306a\u3044\u3002\u30a2\u30eb\u30b8\u30e3\u30b8\u30fc\u30e9\u304c\u4f1d\u3048\u3066\u308b\u3053\u3068\u304c\u5168\u3066\u3058\u3083\u306a\u3044\u3057\u3001\u65e5\u672c\u306eTV\u306f\u4f1d\u3048\u306a\u3044\u3067\u3057\u3087\u3046\u3002\u77e5\u308a\u305f\u304c\u3063\u3066\u308b\u4eba\u3082\u305f\u304f\u3055\u3093\u3044\u308b\u3002","id":41190564187611136,"from_user_id":16996368,"to_user":"shinichiro_beck","geo":null,"iso_language_code":"ja","to_user_id_str":"1800565","source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"119070802","profile_image_url":"http://a2.twimg.com/profile_images/1229773005/346d8435099798113a1326e1ba4949ee_normal.jpeg","created_at":"Fri, 25 Feb 2011 17:39:25 +0000","from_user":"takotako726","id_str":"41190545439207424","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u9b54\u6cd5\u5c11\u5973\u307e\u3069\u304b\u30de\u30ae\u30ab\u306e\u53cd\u97ff\u304ctwitter\u3067\u306f\u3093\u3071\u306d\u3048\u4ef6\u3002","id":41190545439207424,"from_user_id":119070802,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://z.twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b/twipple&lt;/a&gt;"},{"from_user_id_str":"165695316","profile_image_url":"http://a1.twimg.com/profile_images/681748782/ring_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:21 +0000","from_user":"pandora_shotbar","id_str":"41190526447390720","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u300e\u30b7\u30e7\u30c3\u30c8\u30d0\u30fc\u3000\u30d1\u30f3\u30c9\u30e9\u3000\u30c4\u30a4\u30c3\u30bf\u30fc\u306e\u3064\u3076\u3084\u304d\u300f\u30b7\u30e7\u30c3\u30c8\u30d0\u30fc\u3000\u30d1\u30f3\u30c9\u30e9\u3000\u30c4\u30a4\u30c3\u30bf\u30fc\u306e\u3064\u2026\uff5chttp://pandora-twitter.seesaa.net/article/187809936.html","id":41190526447390720,"from_user_id":165695316,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://blog.seesaa.jp/&quot; rel=&quot;nofollow&quot;&gt;SeesaaBlog&lt;/a&gt;"},{"from_user_id_str":"88862311","profile_image_url":"http://a2.twimg.com/profile_images/1182243698/161113_100001897885617_169366_q_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:16 +0000","from_user":"amebaguide","id_str":"41190504926416896","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u300e\u30a2\u30e1\u30d6\u30ed\u653b\u7565\u30ac\u30a4\u30c9\u306e\u30c4\u30a4\u30c3\u30bf\u30fc\u306e\u3064\u3076\u3084\u304d\u300f\u30d6\u30ed\u30b0\u306e\u653b\u7565\u3000\u30c4\u30a4\u30c3\u30bf\u30fc\u306e\u3064\u3076\u3084\u304d\u96c6\uff5chttp://accessup-twitter.seesaa.net/article/187809931.html","id":41190504926416896,"from_user_id":88862311,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://blog.seesaa.jp/&quot; rel=&quot;nofollow&quot;&gt;SeesaaBlog&lt;/a&gt;"},{"from_user_id_str":"186895007","profile_image_url":"http://a2.twimg.com/profile_images/1229610799/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:11 +0000","from_user":"zizikt","id_str":"41190486123356161","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3053\u308c\u306f\u500b\u4eba\u7684\u306b\u306f\u91cd\u5b9d\u3067\u3059\u3002\n\u25c6iPhone&amp;iPad\u5411\u3051Twitter\u30a2\u30d7\u30ea\u300c\u3064\u3044\u3063\u3077\u308b\u300d\u306bEvernote\u3068\u306e\u9023\u643a\u6a5f\u80fd\u3092\u8ffd\u52a0 \nhttp://bit.ly/hPf44u","id":41190486123356161,"from_user_id":186895007,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"132320738","profile_image_url":"http://a3.twimg.com/profile_images/1229760475/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:04 +0000","from_user":"faina_","id_str":"41190453592334336","metadata":{"result_type":"recent"},"to_user_id":167894537,"text":"@gjmorley \u30e2\u30fc\u30ea\u30fc\u3055\u3093\u306e\u7ffb\u8a33\u306e\u8a00\u8449\u306e\u30bb\u30f3\u30b9\u304c\u3059\u304d\u3067\u3059\u3002\u305d\u3057\u3066\u3001Twitter\u3067\u77e5\u308b\u3001\u73fe\u5730\u306e\u4eba\u306e\u76ee\u306e\u529b\u3084\u3001\u60c5\u5831\u3092\u4f1d\u3048\u3066\u304f\u308c\u308b\u7686\u3055\u3093\u306e\u60c5\u71b1\u306b\u611f\u52d5\u3057\u3066\u3044\u307e\u3059\u3002\u611f\u52d5\u3059\u308b\u3063\u3066\u3059\u3054\u3044\u30a8\u30cd\u30eb\u30ae\u30fc\u3067\u3059\uff01\uff01","id":41190453592334336,"from_user_id":132320738,"to_user":"gjmorley","geo":null,"iso_language_code":"ja","to_user_id_str":"167894537","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"24870552","profile_image_url":"http://a3.twimg.com/profile_images/907130634/4_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:03 +0000","from_user":"tana1192","id_str":"41190450480021504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u500b\u4eba\u7684\u306b\u306f\u3001\u30bf\u30b0\u5f3e\u304d\u3059\u308c\u3070\u3044\u3044\uff08\u5f3e\u3051\u308b\u30c4\u30fc\u30eb\u3092\u4f7f\u3063\u3066Twitter\u3092\u3059\u308c\u3070\u3044\u3044\uff09\u3068\u601d\u3046\u3093\u3060\u3051\u3069\u306a\u3042\u3002\u307f\u3093\u306a\u305d\u308c\u306a\u308a\u306bTwitter\u3084\u308b\u4eba\u3060\u3057\u3001\u30c4\u30fc\u30eb\u9078\u3073\u304f\u3089\u3044\u5e45\u3092\u6301\u3063\u3066\u3084\u3063\u3066\u3082\u3002 \u307e\u3042\u3001\u4ffa\u30a2\u30cb\u30e1\u306f\u89b3\u308b\u89b3\u308b\u8a50\u6b3a\u3059\u308b\u3060\u3051\u306e\u4eba\u3060\u304b\u3089\u95a2\u4fc2\u306a\u3044\u3093\u3060\u3051\u3069\u3082\uff57\uff57\u5b9f\u6cc1\u306f\u697d\u3057\u305d\u3046\u306b\u898b\u3048\u308b\u3088\u3002","id":41190450480021504,"from_user_id":24870552,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"58509646","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Fri, 25 Feb 2011 17:39:02 +0000","from_user":"kakuyas","id_str":"41190446663344128","metadata":{"result_type":"recent"},"to_user_id":107076877,"text":"@Dayspool \u6df1\u591c\uff12\uff19\u6642\u304f\u3089\u3044\u307e\u3067\u306f\u6bce\u65e5\u55b6\u696d\u3057\u3066\u308b\u306e\u3067\u3001twitter\u3001\u30e1\u30c3\u30bb\u3001PS3\u306a\u3069\u3067\u3088\u3093\u3067\u3051\u308c\u3002\u3053\u3063\u3061\u304b\u3089\u58f0\u304b\u3051\u308b\u3053\u3068\u3082\u3042\u308b\u304b\u3082\u3060\u304c\uff57","id":41190446663344128,"from_user_id":58509646,"to_user":"Dayspool","geo":null,"iso_language_code":"ja","to_user_id_str":"107076877","source":"&lt;a href=&quot;http://cheebow.info/chemt/archives/2007/04/twitterwindowst.html&quot; rel=&quot;nofollow&quot;&gt;Twit for Windows&lt;/a&gt;"},{"from_user_id_str":"149128527","profile_image_url":"http://a2.twimg.com/profile_images/1254922702/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:39:00 +0000","from_user":"uni13yoki","id_str":"41190437087748096","metadata":{"result_type":"recent"},"to_user_id":119468594,"text":"@kuro_wr84 \u304a\u308c\u3068\u304a\u524d\u3067Twitter\u3067\u4f1a\u8a71\u3057\u305f\u3089\u3001\u5927\u5909\u306a\u3053\u3068\u306b\u306a\u308b\u306a","id":41190437087748096,"from_user_id":149128527,"to_user":"kuro_wr84","geo":null,"iso_language_code":"ja","to_user_id_str":"119468594","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"18670595","profile_image_url":"http://a2.twimg.com/profile_images/1250674062/ProfilePhoto_normal.png","created_at":"Fri, 25 Feb 2011 17:38:59 +0000","from_user":"nyuuuuun","id_str":"41190436450222080","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3078\u30fc\u3053\u3093\u306a\u306b\u3088\u304f\u4f3c\u308b\u3053\u3068\u3082\u3042\u308b\u3093\u3060\u30fc\nhttp://twitter.com/Re_44/status/35943233016168448\nhttp://twitter.com/3510_misaka/status/36122114821988352","id":41190436450222080,"from_user_id":18670595,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"96267603","profile_image_url":"http://a3.twimg.com/profile_images/1245253473/DSiLL3_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:59 +0000","from_user":"arivis","id_str":"41190433119940608","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://twitter.com/#!/arivis/status/40636755380142080 \u306a\u3093\u3064\u3046\u304b\u3053\u308c\u3067\u8d64\u3063\u3066\u306e\u3082\u3061\u3087\u3063\u3068\u3042\u308c\u3063\u3059\u306d\u3002\u305d\u3057\u3066\u4e88\u671f\u3057\u3066\u3044\u305f\u304b\u306e\u3088\u3046\u3060","id":41190433119940608,"from_user_id":96267603,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"148097776","profile_image_url":"http://a3.twimg.com/profile_images/1166904064/broken-heart_normal.png","created_at":"Fri, 25 Feb 2011 17:38:56 +0000","from_user":"ReajuBreaker_A","id_str":"41190422135058432","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u672c\u57a2\u30d5\u30a9\u30ed\u30fc\u3088\u308d\u3057\u304f\u3067\u3059\u2192 http://twitter.com/ReajuBreaker \uff08\uff20\u3060\u3068\u30ea\u30d7\u30e9\u30a4\u304c\u57cb\u307e\u308b\u305f\u3081\u3001URL\u306b\u3057\u3066\u3042\u308a\u307e\u3059\uff09","id":41190422135058432,"from_user_id":148097776,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.twitter.com/ReajuBreaker&quot; rel=&quot;nofollow&quot;&gt;\u73fe\u5145\u6bba\u3057\u306e\u7121\u4eba\u9023\u545f\uff1c\u30aa\u30fc\u30c8\u30c4\u30a4\u30fc\u30c8\uff1e&lt;/a&gt;"},{"from_user_id_str":"59711654","profile_image_url":"http://a2.twimg.com/profile_images/416212928/flowers-06-1_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:56 +0000","from_user":"agamo45","id_str":"41190421522546688","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @ebizo66: \u30ea\u30d3\u30a2\u30fb\u30c8\u30ea\u30dd\u30ea\u306eTw\uff1a\u6551\u6025\u8eca\u304c\u6765\u305f\u304c\u3001\u8ca0\u50b7\u8005\u3092\u8eca\u5185\u3067\u6bba\u5bb3\u3057\u3066\u3044\u305f\u3001\u3068\u3002\uff08\u6ec5\u8336\u82e6\u8336\u3060\uff01\uff09http://ow.ly/43pQ2 #libjp","id":41190421522546688,"from_user_id":59711654,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"145311373","profile_image_url":"http://a3.twimg.com/profile_images/1187802576/a_gam_02_normal.png","created_at":"Fri, 25 Feb 2011 17:38:55 +0000","from_user":"nogic1008","id_str":"41190418141937664","metadata":{"result_type":"recent"},"to_user_id":88117317,"text":"@runasoru \u307e\u3042\u5acc\u306a\u3089\u6df1\u591c\u5e2f\u306bTwitter\u898b\u306a\u304d\u3083\u3044\u3044\u3060\u3051\u3067\u3059\u304b\u3089\u306d\u30fc \u30103/19BDM\u30aa\u30d5http://twvt.us/bdoff_kansai\u3011","id":41190418141937664,"from_user_id":145311373,"to_user":"runasoru","geo":null,"iso_language_code":"ja","to_user_id_str":"88117317","source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"195851300","profile_image_url":"http://a2.twimg.com/profile_images/1124572815/be7b4c0a06cb60e8_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:49 +0000","from_user":"LoveLAscrewDoll","id_str":"41190391147540480","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @jp_mjp: SCREW TV SHOW Vol.6\u306e\u653e\u9001\u304c\u7121\u4e8b\u306b\u7d42\u4e86\u3044\u305f\u3057\u307e\u3057\u305f\u3002\u3054\u89a7\u9802\u304d\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3057\u305f\uff01\u6b21\u56de\u653e\u9001\u306f3\u670818\u65e5(\u91d1)\u3067\u3059\u3002\u8996\u8074\u8005\u30d7\u30ec\u30bc\u30f3\u30c8\u306e\u8a73\u7d30\u306f\u5f8c\u65e5MJP\u3067\u304a\u77e5\u3089\u305b\u3044\u305f\u3057\u307e\u3059\u3002\u305d\u306e\u969b\u306b\u306f\u3001\u3053\u306eTwitter\u3067\u3082\u304a\u77e5\u3089\u305b\u3044\u305f\u3057\u307e\u3059\u306e\u3067\u3001\u304a\u697d\u3057\u307f\u306b\uff01#SCREWTV","id":41190391147540480,"from_user_id":195851300,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://z.twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b/twipple&lt;/a&gt;"},{"from_user_id_str":"178045354","profile_image_url":"http://a0.twimg.com/profile_images/1214479381/154722_10100141954893059_808622_55276626_7445050_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:48 +0000","from_user":"ChuriSta_gt","id_str":"41190389549510656","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3053\u3053\u4e00\u9031\u9593Twitter\u304c\u3084\u305f\u3089\u697d\u3057\u3044\u306e\u3067\u3059\u3051\u3069\u30fc\u30fc\u30fc\uff01\u306b\u3072\u3072\u3063\u7b11","id":41190389549510656,"from_user_id":178045354,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b for iPhone&lt;/a&gt;"},{"from_user_id_str":"50592111","profile_image_url":"http://a0.twimg.com/profile_images/1252176582/lFjpi_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:48 +0000","from_user":"crowNeko","id_str":"41190387271864320","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30a8\u30ed\u30b2\u30d7\u30ec\u30a4\u3057\u306a\u304c\u3089\u307e\u3069\u30de\u30aeTL\u3092\u898b\u306a\u3044\u3088\u3046\u306b\u534a\u76ee\u306b\u306a\u308a\u306a\u304c\u3089Twitter\u3057\u3066\u308b\u6df1\u591c2\u6642\u534a\u3002","id":41190387271864320,"from_user_id":50592111,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://stone.com/Twittelator&quot; rel=&quot;nofollow&quot;&gt;Twittelator&lt;/a&gt;"},{"from_user_id_str":"7141467","profile_image_url":"http://a3.twimg.com/profile_images/1198540741/icon12912579345276_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:40 +0000","from_user":"hina_geshi","id_str":"41190355961380864","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u7d50\u5c40\u30cd\u30bf\u30d0\u30ec\u3059\u3093\u306a\u3063\u3066\u8a00\u3046\u65b9\u304c\u30a2\u30ec\u3060\u3088\u306d\u3001\u3057\u306a\u3044\u308f\u3051\u7121\u3044\u3058\u3083\u306a\u3044\u8133\u5185\u5782\u308c\u6d41\u3057\u304cTwitter\u306a\u3093\u3060\u304b\u3089\u3055","id":41190355961380864,"from_user_id":7141467,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://projects.playwell.jp/go/Saezuri&quot; rel=&quot;nofollow&quot;&gt;Saezuri&lt;/a&gt;"},{"from_user_id_str":"149608984","profile_image_url":"http://a0.twimg.com/profile_images/1205950885/090702_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:39 +0000","from_user":"Mr_Tsubaki","id_str":"41190349447774208","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u307e\u3069\u304b\u306fTwitter\u5408\u308f\u305b\u3066\uff11\u6642\u9593\u306f\u697d\u3057\u3044","id":41190349447774208,"from_user_id":149608984,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://z.twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b/twipple&lt;/a&gt;"},{"from_user_id_str":"122271550","profile_image_url":"http://a0.twimg.com/profile_images/961936499/neoneko_bot5jpg_____normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:39 +0000","from_user":"neoneko_bot5","id_str":"41190348726345728","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u30c6\u30b9\u30c8\uff1a23\u3011\u4eca\u65e5\u304b\u3089\u5ba3\u4f1d\u958b\u59cb\u2606\u306d\u304a\u306d\u3053\u306eTwitter \u3067 EasyBottex\u3000\u3067\u304d\u308b\u307e\u3067\uff01\u2192http://neoneko.blog31.fc2.com/","id":41190348726345728,"from_user_id":122271550,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www20.atpages.jp/neoneko/&quot; rel=&quot;nofollow&quot;&gt;neoneko_bot5&lt;/a&gt;"},{"from_user_id_str":"127069188","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png","created_at":"Fri, 25 Feb 2011 17:38:37 +0000","from_user":"MYCHEBOT","id_str":"41190340908163074","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30eb\u30d5\u3055\u3093\u304c\u914d\u4fe1\u3092\u7d42\u4e86\u3057\u307e\u3057\u305f\uff01/ http://777labo.com/mychecker/view/745.php / \u30c8\u30d4\u30c3\u30af:XSplit\u30c6\u30b9\u30c8\u3000twitter\u2192http://twitter.com/rukh01","id":41190340908163074,"from_user_id":127069188,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://777labo.com/mychecker/&quot; rel=&quot;nofollow&quot;&gt;MYCHEBOT&lt;/a&gt;"},{"from_user_id_str":"107626142","profile_image_url":"http://a1.twimg.com/profile_images/1104968421/SuperMaika1_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:34 +0000","from_user":"MaikaPaPa","id_str":"41190328614666240","metadata":{"result_type":"recent"},"to_user_id":null,"text":"75\u5e74\u524d\u306e\u4eca\u65e52\u670826\u65e5\u672a\u660e\u3001\u82e5\u304d\u9752\u5e74\u5c06\u6821\u3089\u304c\u653f\u6cbb\u8150\u6557\u3068\u8fb2\u6751\u306e\u56f0\u7aae\u306b\u5bfe\u3057\u3066\u6c7a\u8d77\u3057\u307e\u3057\u305f\u3002\u3082\u3061\u308d\u3093\u5f53\u6642\u306fTwitter\u3082FB\u3082\u3001\u307e\u305f\u5f53\u7136\u306a\u304c\u3089Internet\u3082\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u65b9\u3001\u30c1\u30e5\u30cb\u30b8\u30a2\u3001\u30a8\u30b8\u30d7\u30c8\u3001\u4e2d\u6771\u306b\u5e83\u304c\u308b\u53cd\u653f\u5e9c\u30c7\u30e2\u3068\u5f37\u6a29\u4f53\u5236\u306e\u5d29\u58ca\u3002\u73fe\u5728\u306e\u65e5\u672c\u3067\u306f\u8003\u3048\u3089\u308c\u306a\u3044\u3053\u3068\u3067\u3059\u3002","id":41190328614666240,"from_user_id":107626142,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"11111695","profile_image_url":"http://a1.twimg.com/sticky/default_profile_images/default_profile_0_normal.png","created_at":"Fri, 25 Feb 2011 17:38:28 +0000","from_user":"kumatchipooh","id_str":"41190306145775617","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @inosenaoki: \u306a\u308b\u307b\u3069\u306d\u3002 RT @dansrmz @inosenaoki \u3053\u3061\u3089\u304c\u30bd\u30d5\u30c8\u30d0\u30f3\u30af\u526f\u793e\u9577\u306e\u677e\u672c\u5fb9\u4e09\u3055\u3093\u306e\u3001Twitter\u306b\u95a2\u3059\u308b\u8ad6\u8003\u3067\u3059\u3002 \u25b6 &quot;Twitter\u306e2\u30c1\u30e3\u30f3\u30cd\u30eb\u5316\u306f\u9632\u6b62\u51fa\u6765\u308b\u304b&quot; http://t.co/Mwzb8Zf","id":41190306145775617,"from_user_id":11111695,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"212161909","profile_image_url":"http://a1.twimg.com/profile_images/1252895790/natm01_normal.gif","created_at":"Fri, 25 Feb 2011 17:38:28 +0000","from_user":"n34hitman","id_str":"41190303830511616","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Twitter\u30fb\u30d6\u30ed\u30b0\u30a2\u30d5\u30a3\u30ea\u30a8\u30a4\u30c8\u81ea\u52d5\u6295.... http://goo.gl/a4RHB 4054","id":41190303830511616,"from_user_id":212161909,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twibow.net/&quot; rel=&quot;nofollow&quot;&gt;Twibow&lt;/a&gt;"},{"from_user_id_str":"105945593","profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","created_at":"Fri, 25 Feb 2011 17:38:24 +0000","from_user":"nakano_bot","id_str":"41190285710983168","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3053\u306ebot\u306f\u4e0d\u52d5\u7523\u4f1a\u793e\u69d8\u5411\u3051\u306e\u4e0d\u52d5\u7523\u30dd\u30fc\u30bf\u30eb\u30b5\u30a4\u30c8\u3078\u306e\u4e00\u62ec\u8ee2\u9001\uff0bTwitter\u7121\u6599\u8ee2\u9001\u30b5\u30fc\u30d3\u30b9\u306b\u3088\u308a\u3064\u3076\u3084\u304d\u307e\u3059\u3002\u3054\u5229\u7528\u306b\u306a\u308a\u305f\u3044\u5834\u5408\u306f http://bit.ly/demey0 \u306b\u304a\u6c17\u8efd\u306b\u304a\u554f\u3044\u5408\u308f\u305b\u4e0b\u3055\u3044\u3002","id":41190285710983168,"from_user_id":105945593,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.teramax.jp/aboutus.html&quot; rel=&quot;nofollow&quot;&gt;tmxbot&lt;/a&gt;"},{"from_user_id_str":"170904226","profile_image_url":"http://a2.twimg.com/profile_images/1249020397/1789kb_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:21 +0000","from_user":"1789kb","id_str":"41190274428305408","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3068\u308a\u3042\u3048\u305a\u4eca\u56de\u521d\u3081\u3066\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u3067\u898b\u3066\u308f\u304b\u3063\u305f\u306e\u306f\u3001QB\u306f\u5168\u8eab\u304c\u30a2\u30f3\u30d1\u30f3\u30bf\u30a4\u30d7\u3060\u3068\u3044\u3046\u3053\u3068\u3068\u3001\u307e\u3069\u30de\u30ae\u7d42\u4e86\u5f8c\u306eTwitter\u306e\u3056\u308f\u3064\u304d\u304c\u3059\u3054\u3044\u3068\u3044\u3046\u3053\u3068","id":41190274428305408,"from_user_id":170904226,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"166169644","profile_image_url":"http://a1.twimg.com/profile_images/1217017679/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:18 +0000","from_user":"Okkkkkkkkkkun","id_str":"41190262420017152","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3063\u3066Twitter\u3067\u3064\u3076\u3084\u304f\u81ea\u5206\u3082\u76f8\u5f53\u5c0f\u3055\u3044\u306a\u3002","id":41190262420017152,"from_user_id":166169644,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"196623456","profile_image_url":"http://a3.twimg.com/profile_images/1219076661/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:06 +0000","from_user":"NoMoneyClub","id_str":"41190213342601216","metadata":{"result_type":"recent"},"to_user_id":195462431,"text":"@yosal15 \nTwitter\u3084\u3063\u3066\u308b\u3089\u3057\u3044\u3002\u3051\u3069\u3001\u898b\u3064\u304b\u3089\u306a\u3044\u3002","id":41190213342601216,"from_user_id":196623456,"to_user":"yosal15","geo":null,"iso_language_code":"ja","to_user_id_str":"195462431","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"126984048","profile_image_url":"http://a3.twimg.com/profile_images/1254579571/zipyaru-20090829-23-0012_normal.png","created_at":"Fri, 25 Feb 2011 17:38:02 +0000","from_user":"minaduki_naduki","id_str":"41190196418584576","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u203b\u30e1\u30fc\u30eb\u3067\u5973\u306e\u5b50\u53e3\u8aac\u304f\u306e\u306b\u5fd9\u3057\u3044\u3093\u3060\u305d\u3046\u3067\u3059\u3000\u307e\u3058\u3058\u3054\u308d RT @yowano_k: \u5fd9\u3057\u304f\u3066\u3082Twitter\u306b\u9854\u3092\u51fa\u3057\u305f\u304f\u306a\u308b\u50d5\u30a7\u2026\u2026","id":41190196418584576,"from_user_id":126984048,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://seesmic.com/seesmic_desktop/sd2&quot; rel=&quot;nofollow&quot;&gt;Seesmic Desktop&lt;/a&gt;"},{"from_user_id_str":"200568705","profile_image_url":"http://a3.twimg.com/profile_images/1242179765/101230_1355_01_normal.jpg","created_at":"Fri, 25 Feb 2011 17:38:01 +0000","from_user":"hammerstrap","id_str":"41190190428979200","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6628\u65e5\u91d1\u66dc\u65e5\u306f\u732e\u8840\u306b\u5f80\u304f\u3002\u4eca\u306e\u50d5\u306e\u4eba\u9593\u3068\u3057\u3066\u306e\u4fa1\u5024\u306f\u3001\u7cbe\u3005\u3053\u306e\u7a0b\u5ea6\u3002\u8179\u304c\u6e1b\u3063\u305f\u3002\u5374\u8aac\u3002twitter\u306e\u767e\u56db\u5341\u6587\u5b57\u306b\u82db\u3005\u3068\u3057\u3066\u3001\u4e00\u3064\u306e\u4eee\u8aac\u306b\u4fe1\u6191\u6027\u3092\u5f97\u308b\u3002\u6226\u6642\u4e0b\u306e\u7d19\u306e\u7d71\u5236\u3068\u3001\u4e2d\u5cf6\u6566\u306e\u6587\u7ae0\u306e\u95a2\u4fc2\u6027\u3002\u73fe\u5728\u30a6\u30a7\u30d6\u30ed\u30b0\u306b\u3001\u7e8f\u3081\u3066\u3044\u308b\u6700\u4e2d\u3002\u8fd1\u65e5\u516c\u958b\u4e88\u5b9a\u3002","id":41190190428979200,"from_user_id":200568705,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"164970427","profile_image_url":"http://a0.twimg.com/profile_images/1227176662/9192b021ef85ce9902c28955f86e604b_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:59 +0000","from_user":"syuigetsuIT","id_str":"41190184041197569","metadata":{"result_type":"recent"},"to_user_id":141926331,"text":"@iliad_tga \u30a4\u30ea\u30a2\u30b9\u3055\u3093\u304c\u305d\u306e\u8fba\u7406\u89e3\u306e\u3042\u308b\u3053\u3068\u306f\u5206\u304b\u3063\u3066\u307e\u3059\uff57\u3000\u30cd\u30bf\u30d0\u30ec\u4e91\u3005\u306ftwitter\u306e\u6c7a\u5b9a\u7684\u306a\u6b20\u70b9\u3060\u3068\u601d\u3044\u307e\u3059\u306d\u3047\u3002","id":41190184041197569,"from_user_id":164970427,"to_user":"iliad_tga","geo":null,"iso_language_code":"ja","to_user_id_str":"141926331","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"94526795","profile_image_url":"http://a0.twimg.com/profile_images/679411954/akb48_in_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:56 +0000","from_user":"akb48_in","id_str":"41190171248431104","metadata":{"result_type":"recent"},"to_user_id":null,"text":"AKB48\u67cf\u6728\u7531\u7d00 \u304a\u75b2\u308c\u69d8\u3002: \n\u3053\u3093\u3070\u3093\u306f(^O^)\uff0f\u266a\n\u3000\n\u3000\n\u3000\n\u4eca\u65e5\u306e\u516c\u6f14\u697d\u3057\u304b\u3063\u305f\u301c\n\u3000\n\u3000\n\u4e45\u3057\u3076\u308a\u3067\u7dca\u5f35\u3057\u305f\u3051\u3069\u3001\u306f\u3058\u3051\u307e\u304f\u3063\u305f\u305c\u3043\uff01\uff01\n\u3000\n\u3000\n\u3000\nMC\u306f\u565b\u307f\u307e\u304f\u308a\u306e\u30c6\u30f3\u30d1\u308a\u307e\u304f... http://bit.ly/ie8bEa akb48 twitter","id":41190171248431104,"from_user_id":94526795,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"222270374","profile_image_url":"http://a3.twimg.com/profile_images/1250946143/P1040062_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:53 +0000","from_user":"chrxpac","id_str":"41190158455943168","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u5b9a\u671f\u3011Twitter\u306f\uff8a\uff9f\uff7f\uff7a\uff9d\u304b\u3089\u3057\u304b\u3067\u304d\u306a\u3044\u306e\u3067\uff98\uff8c\uff9f\u8fd4\u3057\u304c\u9045\u304f\u306a\u308a\u307e\u3059(\u00b4\u30fb\u03c9\u30fb\uff40)\u3054\u4e86\u627f\u4e0b\u3055\u3044!!","id":41190158455943168,"from_user_id":222270374,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"64009258","profile_image_url":"http://a2.twimg.com/profile_images/1154025023/Mixi___normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:52 +0000","from_user":"Tatsuyuko","id_str":"41190153447944192","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4f01\u696d\u304c\u5c31\u6d3b\u751f\u306bFacebook\u3092\u4f7f\u3063\u3066\u7533\u8acb\u305b\u3088\u3068\u3044\u3044\u3001\u4f01\u696d\u304cFacebook\u3092\u4f7f\u3048\u3068\u4f01\u696d\u304c\u8a00\u3063\u3066\u304d\u305f\u308a\u3059\u308c\u3070\u305d\u308c\u3069\u3053\u308d\u3058\u3083\u306a\u3044\u304b\u3068\u3002\u5c11\u306a\u304f\u3068\u3082\u5c31\u6d3b\u3067Twitter\u306e\u8a00\u52d5\u3084\u30d5\u30a9\u30ed\u30ef\u30fc\u3092\u8abf\u67fb\u3059\u308b\u4f01\u696d\u306f\u304b\u306a\u308a\u591a\u3044\u3067\u3059 RT @Isshee: \u4f01\u696d\u3067\u3082\u540c\u3058\u3067\u3057\u3087 RT","id":41190153447944192,"from_user_id":64009258,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"105145175","profile_image_url":"http://static.twitter.com/images/default_profile_normal.png","created_at":"Fri, 25 Feb 2011 17:37:49 +0000","from_user":"snao813","id_str":"41190141703753728","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @yumisaiki: \u795e\u69d8\u306f\u672c\u5f53\u306b\u4eba\u9593\u3092\u3059\u3070\u3089\u3057\u3044\u30d0\u30e9\u30f3\u30b9\u3067\u914d\u7f6e\u3057\u3066\u304a\u3089\u308c\u308b\u3002\u795d\u5cf6\u307f\u305f\u3044\u306a\u5c0f\u3055\u3044\u3068\u3053\u308d\u306b\u306a\u3093\u3067\u3053\u3093\u306a\u306b\u7acb\u6d3e\u306a\u4eba\u304c\u305f\u304f\u3055\u3093\u3044\u308b\u3093\u3060\u308d\u3046\u3002\u795e\u69d8\u3042\u308a\u304c\u3068\u3046\u3002\u672c\u5f53\u306b\u3042\u308a\u304c\u3068\u3046\u3002\u4eba\u9593\u3063\u3066\u3059\u3070\u3089\u3057\u3044\u3068\u601d\u3048\u305f\u3002twitter\u3082\u3042\u308a\u304c\u3068\u3046\u3002\u3000#kaminoseki","id":41190141703753728,"from_user_id":105145175,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://seesmic.com/seesmic_desktop/sd2&quot; rel=&quot;nofollow&quot;&gt;Seesmic Desktop&lt;/a&gt;"},{"from_user_id_str":"203667204","profile_image_url":"http://a2.twimg.com/profile_images/1254664000/eve_blackcat_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:46 +0000","from_user":"eve_blackcat","id_str":"41190129292943361","metadata":{"result_type":"recent"},"to_user_id":146894340,"text":"@kuroiso02 \u3057\u308a\u3068\u308a\u3068\u304b\uff1f\n\u2026\u3067\u3082Twitter\u3060\u3068\u7d42\u308f\u3089\u306a\u304f\u306a\u308b\u30b1\u30c9\u2026","id":41190129292943361,"from_user_id":203667204,"to_user":"kuroiso02","geo":null,"iso_language_code":"ja","to_user_id_str":"146894340","source":"&lt;a href=&quot;http://twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b for iPhone&lt;/a&gt;"},{"from_user_id_str":"6528403","profile_image_url":"http://a0.twimg.com/profile_images/1240591244/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:45 +0000","from_user":"sortiee","id_str":"41190125924917248","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30a2\u30cb\u30e1\u5b9f\u6cc1\u306ftwitter\u306e\u764c","id":41190125924917248,"from_user_id":6528403,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sites.google.com/site/peraperaprv/Home&quot; rel=&quot;nofollow&quot;&gt;P3:PeraPeraPrv&lt;/a&gt;"},{"from_user_id_str":"186058304","profile_image_url":"http://a0.twimg.com/profile_images/1250454564/IMG_0210_normal.JPG","created_at":"Fri, 25 Feb 2011 17:37:37 +0000","from_user":"00o8o00","id_str":"41190090386448384","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @fuefukioyasumi: \u3082\u3046\u3044\u3044\u3002\u300c\u671d\u751f\u300d\u306a\u3093\u304b\u3044\u3044\u3002BBC\u3082CNN\u3082\u82f1\u8a9e\u653e\u9001\u3060\u3002\u307f\u3093\u306a\u3001\u30c6\u30ec\u30d3\u3092\u3076\u3061\u3063\u3068\u5207\u3063\u3066Twitter\u3092\u898b\u3088\u3046\u3002\u3053\u3053\u306b\u300c\u751f\u304d\u305f\u60c5\u5831\u300d\u304c\u6d41\u308c\u3066\u3044\u308b\u3002\u300c\u751f\u304d\u305f\u53eb\u3073\u300d\u304c\u3042\u308b\u3002\u3053\u3053\u304b\u3089\u3067\u3082\u6b74\u53f2\u306e\u8ee2\u63db\u70b9\u3092\u611f\u3058\u308b\u4e8b\u304c\u3067\u304d\u308b\u306e\u3060\u3002 @gjmorley #libjp","id":41190090386448384,"from_user_id":186058304,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"49219631","profile_image_url":"http://a2.twimg.com/profile_images/1231873117/__2-colornow__2__normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:33 +0000","from_user":"irisgazer","id_str":"41190073227550720","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3067\u3059\u3088\u306d\u3047 RT @minamitaiheiyou: \u6545\u306b\u30cd\u30bf\u30d0\u30ec\u3092\u3059\u308b\u306e\u3082\u81ea\u7531\u3002\u30cd\u30bf\u3070\u308c\u3057\u305f\u4eba\u3092\u30c7\u30a3\u30b9\u308b\u306e\u3082\u81ea\u7531\u3002\u3042\u3068\u306f\u5404\u3005\u306e\u88c1\u91cf\u3067\u4e57\u308a\u5207\u3063\u3066\u304f\u3060\u3055\u3044\u3088\u3081\u3093\u3069\u304f\u3055\u3044\u306a RT @kihirokiro: Twitter\u3067\u30cd\u30bf\u30d0\u30ec\u4e91\u3005\u3044\u3063\u3066\u3082\u5143\u3005Twitter\u3063\u3066\u300c\u500b\u4eba\u306e\u72ec\u308a\u8a00\u300d\u3060\u308d","id":41190073227550720,"from_user_id":49219631,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"98560114","profile_image_url":"http://a0.twimg.com/profile_images/1252332545/IMGP8170_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:32 +0000","from_user":"qess0093","id_str":"41190070706905088","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30b7\u30e5\u30fc\u30c6\u30a3\u304f\u305d\u3046\u305c\u3048\uff57 RT @syu_thi_bot: \u3044\u3064\u307e\u3067Twitter\u3084\u3063\u3066\u308b\u3093\u3060\u3044\uff1f\u3044\u3044\u52a0\u6e1b\u73fe\u5b9f\u306b\u623b\u308a\u306a\u3088\u3002\u3053\u3053\u306f\u30ad\u30df\u305f\u3061\u4e09\u6b21\u5143\u306e\u4eba\u9593\u304c\u3044\u308b\u3079\u304d\u5834\u6240\u3058\u3083\u306a\u3044\u3093\u3060\u3088\u3002\u305d\u3093\u306a\u306e\u57fa\u672c\u3060\u308d\uff01\uff01","id":41190070706905088,"from_user_id":98560114,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"197459334","profile_image_url":"http://a3.twimg.com/profile_images/1210698414/shiratorishoko_normal.png","created_at":"Fri, 25 Feb 2011 17:37:31 +0000","from_user":"SyokoShiratori","id_str":"41190064243478528","metadata":{"result_type":"recent"},"to_user_id":null,"text":"+0.50kg \u540c\u3058\u304f\u30c0\u30a4\u30a8\u30c3\u30c8\u4e2d\u3067\u3059\u3002\u3088\u304f\u3053\u306e\u30b5\u30a4\u30c8\u3067\u4f53\u91cd\u5831\u544a\u3057\u3066\u307e\u3059\u266a  http://bit.ly/fhN2fM RT @msophiah \u3046\u3046\u3046\u30fb\u30fb\u30fb\u304a\u8179\u3059\u3044\u305f\u301c\u30fb\u30fb\u30fb\u6211\u6162\u3001\u6211\u6162\u3001\u6211\u6162\u3002\u30c0\u30a4\u30a8\u30c3\u30c8\u3001\u30c0\u30a4\u30a8\u30c3\u30c8\u3001\u30c0\u30a4\u30a8\u30c3\u30c8\u3002","id":41190064243478528,"from_user_id":197459334,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://mob-mc.com&quot; rel=&quot;nofollow&quot;&gt;\uff08\u4eee\u79f0\uff09\u30c4\u30a4\u30af\u30ea\u30c3\u30af twiclick&lt;/a&gt;"},{"from_user_id_str":"180410237","profile_image_url":"http://a3.twimg.com/profile_images/1254473979/icon_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:30 +0000","from_user":"ka_ph","id_str":"41190062184079360","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u5b9a\u671fpost\u3011\u30d5\u30a7\u30eb\u30c7\u30a3\u30ca\u30f3\u30c8bot( http://twitter.com/ferdinand_bot )\u4f5c\u308a\u307e\u3057\u305f\u3002\u304a\u5b50\u69d8\u306e\u540d\u524d\u304a\u501f\u308a\u3055\u305b\u3066\u304f\u308c\u308b\u65b9\u3044\u307e\u3057\u305f\u3089@ka_ph\u307e\u3067\u304a\u9858\u3044\u3057\u307e\u3059\u3002","id":41190062184079360,"from_user_id":180410237,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"52283906","profile_image_url":"http://a3.twimg.com/profile_images/387644016/10100654519_s_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:26 +0000","from_user":"rolling_bean","id_str":"41190043313913856","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3081\u307e\u3044\u304c\u3057\u307e\u3059\u306d\u301cRT @yurikalin:\u30b3\u30a4\u30c4\u30e9\u5168\u54e1\u3044\u306a\u304f\u306a\u3063\u305f\u3089\u3001\u660e\u308b\u304f\u306a\u308b\u3060\u308d\u3046\u306a\u3041\uff5e\u266a\uff1e\u65e5\u672c\u306e\u30d3\u30b8\u30e7\u30f3 RT roll \u65e5\u7d4c\uff06CSIS\u30b7\u30f3\u30dd\u30b8\u30a6\u30e0\u300c\u5b89\u4fdd\u6539\u5b9a50\u5468\u5e74\u3001\u3069\u3046\u306a\u308b\u65e5\u7c73\u95a2\u4fc2\u300d http://bit.ly/dES8PY\u3000http://bit.ly/ihg0GT","id":41190043313913856,"from_user_id":52283906,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://tabtter.jp&quot; rel=&quot;nofollow&quot;&gt;\u30bf\u30d6\u30c3\u30bf\u30fc&lt;/a&gt;"},{"from_user_id_str":"351896","profile_image_url":"http://a3.twimg.com/profile_images/1179865336/icon12911887173020_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:26 +0000","from_user":"cicada","id_str":"41190043292925952","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4e2d\u5b66\u53d7\u9a13\u7a0b\u5ea6\u306e\u7b97\u6570\u306e\u554f\u984c\u3092\u51fa\u3059BOT http://twitter.com/arithmetic_bot  \u6c17\u306b\u306f\u306a\u308b\u304c\u3001\u3061\u3083\u3093\u3068\u898b\u308b\u65e5\u304c\u6765\u308b\u3060\u308d\u3046\u304b\u30fb\u30fb\u3000#tearai\uff1a\u30ed\u30b3\u30e9\u30dc\u5bae\u5d0e\u770c http://locolabo.com/mz/ #mzlf","id":41190043292925952,"from_user_id":351896,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://locolabo.com/mz/&quot; rel=&quot;nofollow&quot;&gt;\u30ed\u30b3\u30e9\u30dc\u5bae\u5d0e\u770c&lt;/a&gt;"},{"from_user_id_str":"744554","profile_image_url":"http://a1.twimg.com/profile_images/1088753125/11868894_normal.gif","created_at":"Fri, 25 Feb 2011 17:37:20 +0000","from_user":"Febreze","id_str":"41190019020505088","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30cd\u30bf\u30d0\u30ec\u3042\u307e\u308a\u6c17\u306b\u3057\u306a\u3044\u30bf\u30a4\u30d7\u3060\u3051\u3069\u306a\u3093\u304b\u3053\u3046Twitter\u958b\u304f\u3060\u3051\u3067\u30ac\u30f3\u30ac\u30f3\u30cd\u30bf\u30d0\u30ec\u5165\u3063\u3066\u304f\u308b\u306e\u306f\u306a\u3093\u3068\u3082\u8a00\u3048\u306a\u3044\u306a\u3002","id":41190019020505088,"from_user_id":744554,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"203371794","profile_image_url":"http://a1.twimg.com/profile_images/1226537594/___normal.png","created_at":"Fri, 25 Feb 2011 17:37:16 +0000","from_user":"himeko24","id_str":"41190004139114496","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6b21\u3044\u3063\u3066\u307f\u3088\u30fc\u3000\u306f\u3044\u3053\u308c\u3000 \u6fc0\u5b89\u26052010\u5e74\u590f\u65b0\u30c7\u30b6\u30a4\u30f3\u2605\u30bb\u30af\u30b7\u30fc\u306a\u9023\u4f53\u5f0f\u7121\u5730\u6c34\u7740 \u80f8\u30d1\u30c3\u30c9\u4ed8\u304dQ122 http://bit.ly/h72C4i","id":41190004139114496,"from_user_id":203371794,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.google.co.jp&quot; rel=&quot;nofollow&quot;&gt;himeko24&lt;/a&gt;"},{"from_user_id_str":"119988932","profile_image_url":"http://a3.twimg.com/profile_images/1214344633/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:16 +0000","from_user":"7na_love_6sa","id_str":"41190002000007169","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30d6\u30ed\u30b0\u66f4\u65b0\u3057\u307e\u3057\u305f\uff01Twitter\uff06mixi\u304b\u3089\u3082\u30b3\u30e1\u30f3\u30c8\u5b9c\u3057\u304f\u306d\u266a\n\u300c\u30cd\u30a4\u30eb\u30c1\u30a7\u30f3\u30b8\u266a\u300d http://amba.to/hy0Do2","id":41190002000007169,"from_user_id":119988932,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"217408835","profile_image_url":"http://a1.twimg.com/profile_images/1215428655/____4.0157_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:12 +0000","from_user":"nikubenki1123","id_str":"41189985424125952","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @x68k: \u57fa\u672c\u7684\u306bTwitter\u4e0a\u3067\u306f&quot;\u597d\u304d\u306b\u3084\u308c\u3070\u3044\u3044&quot;\u3060\u3051\u3069\u3001\u540d\u524d\u3082\u30a2\u30a4\u30b3\u30f3\u3082\u30a2\u30f3\u30bf\u3058\u3083\u306a\u3044\u305f\u304f\u3055\u3093\u306e\u4eba\u305f\u3061\u306e\u9b42\u304c\u3053\u3082\u3063\u305f\u3082\u306e\u306a\u306e\u3060\u304b\u3089\u3001\u305d\u308c\u3060\u3051\u306f&quot;\u80cc\u8ca0\u3048&quot;\u3068\u601d\u3046\uff1e\u30ad\u30e3\u30e9\u30af\u30bf\u30fc\u30a2\u30ab\u30a6\u30f3\u30c8","id":41189985424125952,"from_user_id":217408835,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://tweetlogix.com&quot; rel=&quot;nofollow&quot;&gt;Tweetlogix&lt;/a&gt;"},{"from_user_id_str":"139137996","profile_image_url":"http://a0.twimg.com/profile_images/1087408006/cut_work_18_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:12 +0000","from_user":"fujiokayouko","id_str":"41189984354566144","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u591c\u4e2d\u306bTwitter\u3092\u306a\u3093\u3068\u306a\u304f\u8997\u3044\u305f\u3089\u3082\u306e\u3059\u3054\u3044\u307e\u3069\u30de\u30aeTL\u3067","id":41189984354566144,"from_user_id":139137996,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://mobile.twitter.com&quot; rel=&quot;nofollow&quot;&gt;Mobile Web&lt;/a&gt;"},{"from_user_id_str":"61221002","profile_image_url":"http://a3.twimg.com/profile_images/554916301/_1259757374_61_normal.png","created_at":"Fri, 25 Feb 2011 17:37:08 +0000","from_user":"hiromk63","id_str":"41189970613903360","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @kenji_kohashi \u7121\u4e8b\u6620\u753b\u88fd\u4f5c\u306e\u5831\u544a\u306f\u3067\u304d\u305f\u3051\u3069\u4eca\u3060\u7de8\u96c6\u306f\u7d9a\u3044\u3066\u307e\u3059w \u305d\u3093\u306a\u3068\u3053\u3067 \u6620\u753b\u300cDON'T STOP!\u300d\u306eTwitter \u30a2\u30ab\u30a6\u30f3\u30c8 @DONTSTOPMOVIE \u3082\u958b\u59cb\u3001\u3082\u3057\u826f\u304b\u3063\u305f\u3089\u30d5\u30a9\u30ed\u30fc\u3057\u3066\u304f\u3060\u3055\u3044\uff01\u50d5\u3082\u542b\u3081\u6620\u753b\u88fd\u4f5c\u95a2\u4fc2\u8005\u304c\u6c17\u9577\u306b\u3064\u3076\u3084\u304d\u307e\u3059","id":41189970613903360,"from_user_id":61221002,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"147393812","profile_image_url":"http://a1.twimg.com/profile_images/1114001122/hana_10_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:07 +0000","from_user":"tubasa_uki","id_str":"41189965924667392","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\uff10\uff10\uff17\u3082\u3073\u3063\u304f\u308a\u3000\u5927\u56fd\u306e\u5927\u7d71\u9818\u9078\u304b\u3089\u3000\u5cf6\u56fd\u306e\u5730\u65b9\u9078\u306e\u9078\u6319\u307e\u3067\u306b\u3082\u3000\u6697\u8e8d\u3057\u3066\u3044\u308b\uff3e\uff3e\u3000\u3053\u306eTwitter \u30b9\u30ad\u30e3\u30f3\u30c0\u30eb\u3084\u60aa\u8cea\u306a\u4e8b\u4ef6\u306b\u3082\u7d61\u3080\u304c\u3000Twitter\u304b\u3089\u767a\u4fe1\u3055\u308c\u305f\u3000\u5e73\u548c\u3078\u306e\u8ca2\u732e\u306f\u3000\u307e\u3055\u306b\u30ce\u30fc\u3079\u30eb\u5e73\u548c\u8cde\u3082\u306e http://bit.ly/esjWDG #dotubo_ss","id":41189965924667392,"from_user_id":147393812,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"96081746","profile_image_url":"http://a0.twimg.com/profile_images/1244505419/illust832_normal.png","created_at":"Fri, 25 Feb 2011 17:37:07 +0000","from_user":"kazukt","id_str":"41189963131387904","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3046\u308b\u304a\u307c\u7d75\u3001\u4ed6\u306e\u4eba\u306e\u3082\u898b\u3066\u3044\u305f\u3089\u3084\u305f\u3089\u30de\u30f3\u30ac\u306e\u30ad\u30e3\u30e9\u30af\u30bf\u30fc\u3067\u3080\u3061\u3083\u304f\u3061\u3083\u4e0a\u624b\u3044\u4eba\u304c\uff01\u2026\u3068\u3001\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u898b\u305f\u3089\u3001\u306a\u3093\u3068\u3054\u672c\u4eba\u304c\u66f8\u3044\u3066\u3044\u3089\u3063\u3057\u3083\u3063\u305f\u3002Twitter\u3063\u3066\u30b9\u30b4\u30a4\u308f\u3002","id":41189963131387904,"from_user_id":96081746,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://janetter.net/&quot; rel=&quot;nofollow&quot;&gt;Janetter&lt;/a&gt;"},{"from_user_id_str":"86306230","profile_image_url":"http://a1.twimg.com/profile_images/593004766/j2j_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:03 +0000","from_user":"excite_j2j","id_str":"41189949927596032","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u79c1\u306f\u3001\u65e9\u7a32\u7530\u5927\u5b66\u30aa\u30fc\u30d7\u30f3\u30ab\u30ec\u30c3\u30b8\u306e\u5b66\u751f\u306e\u8003\u3048\u3066\u3044\u308b\u3001\u5352\u696d\u751fSoudai /\u65e9\u7a32\u7530\u30ab\u30fc\u30c9\u4f1a\u54e1/ Soudai\u5b66\u751f\u89aa/\u3001\u8ab0\u304b\u304c\u30aa\u30fc\u30d7\u30f3\u30ab\u30ec\u30c3\u30b8\u65e9\u7a32\u7530\u5927\u5b662000\u5186\u306e\u5165\u5834\u6599\u306e\u30e1\u30f3\u30d0\u30fc\u3092\u7d39\u4ecb\u3057\u3066\u304f\u308c\u305f\u65b9\u304c\u305a\u3063\u3068\u5b89\u4e0a\u304c\u308a\u3060\u3002 (\u5143\u767a\u8a00 http://bit.ly/esxiwT )","id":41189949927596032,"from_user_id":86306230,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://d.hatena.ne.jp/fn7&quot; rel=&quot;nofollow&quot;&gt;\u65e5\u672c\u8a9e\u65e5\u672c\u8a9e\u7ffb\u8a33\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf&lt;/a&gt;"},{"from_user_id_str":"120927161","profile_image_url":"http://a0.twimg.com/profile_images/1230006483/20110131_13022_26776_normal.jpg","created_at":"Fri, 25 Feb 2011 17:37:00 +0000","from_user":"FRISKFOSSILFANG","id_str":"41189933855158272","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @syu_thi_bot: \u3044\u3064\u307e\u3067Twitter\u3084\u3063\u3066\u308b\u3093\u3060\u3044\uff1f\u3044\u3044\u52a0\u6e1b\u73fe\u5b9f\u306b\u623b\u308a\u306a\u3088\u3002\u3053\u3053\u306f\u30ad\u30df\u305f\u3061\u4e09\u6b21\u5143\u306e\u4eba\u9593\u304c\u3044\u308b\u3079\u304d\u5834\u6240\u3058\u3083\u306a\u3044\u3093\u3060\u3088\u3002\u305d\u3093\u306a\u306e\u57fa\u672c\u3060\u308d\uff01\uff01","id":41189933855158272,"from_user_id":120927161,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"228973151","profile_image_url":"http://a1.twimg.com/sticky/default_profile_images/default_profile_0_normal.png","created_at":"Fri, 25 Feb 2011 17:36:59 +0000","from_user":"daisuke1589","id_str":"41189931887890432","metadata":{"result_type":"recent"},"to_user_id":null,"text":"twitter\u3063\u3066\u52dd\u624b\u306b\u30d5\u30a9\u30ed\u30fc\u3057\u3066\u3082\u3044\u3044\u3093\u3060\u3063\u3051\uff1f","id":41189931887890432,"from_user_id":228973151,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"54314110","profile_image_url":"http://a2.twimg.com/profile_images/1193541240/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:57 +0000","from_user":"Alohazuki","id_str":"41189922668953600","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Twitter\u306e\u5e83\u5cf6\u5f01\u3082\u3042\u3063\u305f\u3093\u3060\u306d\u3002","id":41189922668953600,"from_user_id":54314110,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.flight.co.jp/iPhone/TweetMe/&quot; rel=&quot;nofollow&quot;&gt;TweetMe for iPhone&lt;/a&gt;"},{"from_user_id_str":"72594681","profile_image_url":"http://a3.twimg.com/profile_images/1227240916/____normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:56 +0000","from_user":"uri4ichi","id_str":"41189916922744832","metadata":{"result_type":"recent"},"to_user_id":226852303,"text":"@7_fuka Twitter\u304b\u3076\u308c\u306f\u3001\u3059\u3050\u306bD\u306b\u8d70\u308b\u306e\u3067\u3002\u306a\u3093\u3060\u304b\u5fae\u7b11\u307e\u3057\u3044\u306e\u3067\u3059( \u2579\u25e1\u2579)","id":41189916922744832,"from_user_id":72594681,"to_user":"7_fuka","geo":null,"iso_language_code":"ja","to_user_id_str":"226852303","source":"&lt;a href=&quot;http://sites.google.com/site/yorufukurou/&quot; rel=&quot;nofollow&quot;&gt;YoruFukurou&lt;/a&gt;"},{"from_user_id_str":"168393854","profile_image_url":"http://a3.twimg.com/profile_images/1253554518/GuNp3xVS_normal","created_at":"Fri, 25 Feb 2011 17:36:55 +0000","from_user":"makonyanhime","id_str":"41189913701515264","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6589\u85e4\u3055\u3093\u3082\u30c0\u30e1\u3060...\u4eca\u591c\u306fTwitter\u5909\u3060\u306a\u3041(;_;)","id":41189913701515264,"from_user_id":168393854,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://mobile.twitter.com&quot; rel=&quot;nofollow&quot;&gt;Twitter for Android&lt;/a&gt;"},{"from_user_id_str":"122636787","profile_image_url":"http://a2.twimg.com/profile_images/1189607563/DSC01987_normal.JPG","created_at":"Fri, 25 Feb 2011 17:36:54 +0000","from_user":"enpy1217","id_str":"41189908500594688","metadata":{"result_type":"recent"},"to_user_id":null,"text":"twitter\u4e45\u3057\u3076\u308a\u306b\u958b\u3044\u305f\u3002\u3068\u3066\u3082\u591a\u5fd9\u3060\u3063\u305f\u3002\u75b2\u308c\u305f\u3002\u304a\u98a8\u5442\u306b\u3082\u5165\u308c\u306a\u304b\u3063\u305f\u3002\u30ad\u30bf\u30cd\u2026","id":41189908500594688,"from_user_id":122636787,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.flight.co.jp/iPhone/TweetMe/&quot; rel=&quot;nofollow&quot;&gt;TweetMe for iPhone&lt;/a&gt;"},{"from_user_id_str":"81663694","profile_image_url":"http://a3.twimg.com/profile_images/1177576126/__normal.png","created_at":"Fri, 25 Feb 2011 17:36:51 +0000","from_user":"progmiya","id_str":"41189895494049792","metadata":{"result_type":"recent"},"to_user_id":94050844,"text":"@hirasai_skyhigh \u6674\u308c\u541b\u3002\u30cd\u30bf\u30d0\u30ec\u306f\u898b\u305f\u304f\u306a\u3044\u3051\u3069\u30012ch\u3082twitter\u3082\u3084\u308a\u305f\u3044\u306e\u304c\u4eba\u3068\u8a00\u3046\u3082\u306e\u3088","id":41189895494049792,"from_user_id":81663694,"to_user":"hirasai_skyhigh","geo":null,"iso_language_code":"ja","to_user_id_str":"94050844","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"159237469","profile_image_url":"http://a3.twimg.com/profile_images/1140433484/______2_normal.png","created_at":"Fri, 25 Feb 2011 17:36:50 +0000","from_user":"hikari_juku","id_str":"41189892096532480","metadata":{"result_type":"recent"},"to_user_id":135634241,"text":"@sssukimasuky \n\u4f55\u304b\u3042\u3063\u305f\u98a8\u3067\u3059\u306d\uff08\u7b11\uff09\u3000\u78ba\u304b\u306bTwitter\u306f\u6c17\u8efd\u3067\u3059\u3057\u306d\u3002\u30e1\u30fc\u30eb\u306b\u306a\u308b\u3068\u30d5\u30c3\u30c8\u30ef\u30fc\u30af\u304c\u91cd\u304f\u306a\u308b\u5834\u5408\u3082\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u306d\u3002\u305d\u3046\u8003\u3048\u308b\u3068\u3059\u3054\u3044\u6642\u4ee3\u3060\u3002","id":41189892096532480,"from_user_id":159237469,"to_user":"sssukimasuky","geo":null,"iso_language_code":"ja","to_user_id_str":"135634241","source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"141915990","profile_image_url":"http://a0.twimg.com/profile_images/1248969898/icon679566266564378764images_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:48 +0000","from_user":"adashino_","id_str":"41189886878949376","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @fuefukioyasumi: \u3082\u3046\u3044\u3044\u3002\u300c\u671d\u751f\u300d\u306a\u3093\u304b\u3044\u3044\u3002BBC\u3082CNN\u3082\u82f1\u8a9e\u653e\u9001\u3060\u3002\u307f\u3093\u306a\u3001\u30c6\u30ec\u30d3\u3092\u3076\u3061\u3063\u3068\u5207\u3063\u3066Twitter\u3092\u898b\u3088\u3046\u3002\u3053\u3053\u306b\u300c\u751f\u304d\u305f\u60c5\u5831\u300d\u304c\u6d41\u308c\u3066\u3044\u308b\u3002\u300c\u751f\u304d\u305f\u53eb\u3073\u300d\u304c\u3042\u308b\u3002\u3053\u3053\u304b\u3089\u3067\u3082\u6b74\u53f2\u306e\u8ee2\u63db\u70b9\u3092\u611f\u3058\u308b\u4e8b\u304c\u3067\u304d\u308b\u306e\u3060\u3002 @gjmorley #libjp","id":41189886878949376,"from_user_id":141915990,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"111308629","profile_image_url":"http://a1.twimg.com/profile_images/1137421845/mmooton_normal.png","created_at":"Fri, 25 Feb 2011 17:36:46 +0000","from_user":"mmooton","id_str":"41189877940748288","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @minponjp: \u3010\u3064\u3076\u3084\u304f\u3060\u3051\u306710000\u5186\u5546\u54c1\u5238GET\u3011&lt;&lt;visa\u30ae\u30d5\u30c8\u30ab\u30fc\u30c910000\u5186\u5206\u3092\u6bce\u6708\u62bd\u9078\u3067\u30d7\u30ec\u30bc\u30f3\u30c8&gt;&gt; \u21d2\u8a73\u3057\u304f\u306f\u4e0b\u306e\uff35\uff32\uff2c\u3088\u308a\u2193\u2193\u2193\u2193\u2193 http://minpon.jp/user_data/twitter_campaign.php","id":41189877940748288,"from_user_id":111308629,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"140945098","profile_image_url":"http://a0.twimg.com/profile_images/1198948281/b7664c71-87bc-4187-9d46-a61ab8d41b96_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:46 +0000","from_user":"waruimayuko","id_str":"41189877122867200","metadata":{"result_type":"recent"},"to_user_id":113371008,"text":"@toumeisyoujyo \u3042\u3053\u3061\u3083\u3093Twitter\u3084\u3063\u3066\u305f\u306e\u306d\u3002\u307e\u3060\u304a\u5e2d\u3042\u308b\u305d\u3046\u306a\u306e\u3067\u662f\u975e\uff01","id":41189877122867200,"from_user_id":140945098,"to_user":"toumeisyoujyo","geo":null,"iso_language_code":"ja","to_user_id_str":"113371008","source":"&lt;a href=&quot;http://twimi.jp/?r=via&quot; rel=&quot;nofollow&quot;&gt;twimi\u2606new&lt;/a&gt;"},{"from_user_id_str":"167512527","profile_image_url":"http://a1.twimg.com/profile_images/1172286365/newspaper_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:45 +0000","from_user":"KoranKaget","id_str":"41189871775252480","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://bit.ly/93Eeud RT @motocentrism \u30d6\u30ed\u30b0\u8a18\u4e8b\u66f8\u304d\u307e\u3057\u305f\u30fc\uff1a MotoGP\u3000\u30d6\u30c3\u30af\u30e1\u30fc\u30ab\u30fc\u306b\u898b\u308b\u5404\u30e9\u30a4\u30c0\u30fc\u306e\u4e0b\u99ac\u8a55 - http://goo.gl/xVe6... http://bit.ly/hDYxyx @motogpudpate","id":41189871775252480,"from_user_id":167512527,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"160251772","profile_image_url":"http://a3.twimg.com/profile_images/1150692471/_____normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:45 +0000","from_user":"keikochaki","id_str":"41189870781075456","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u300c\u305a\u3063\u3068twitter\u3084\u3063\u3066\u308b\u3088\u306d\u300d\u3068\u6012\u3089\u308c\u3066\u3057\u307e\u3063\u305f(\u82e6\u7b11)","id":41189870781075456,"from_user_id":160251772,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twtr.jp&quot; rel=&quot;nofollow&quot;&gt;Keitai Web&lt;/a&gt;"},{"from_user_id_str":"211565766","profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default_profile_5_normal.png","created_at":"Fri, 25 Feb 2011 17:36:42 +0000","from_user":"sayap1yo","id_str":"41189858236043264","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u304a\u98df\u4e8b\u4f1a\u884c\u304d\u305f\u304b\u3063\u305f\u3051\u3069\n\u53cb\u9054\u3068\u904a\u3093\u3067\u307e\u3093\u305f\ue056\ue326\n\nTwitter\u898b\u3066\u307e\u3057\u305f\u3051\u3069\n\u3064\u3076\u3084\u304f\u30bf\u30a4\u30df\u30f3\u30b0\n\u5931\u3063\u3066\u305f\u3060\u3051\u3067\u3059( \u00b4 \u25bd ` )\uff89\u7b11","id":41189858236043264,"from_user_id":211565766,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.nibirutech.com&quot; rel=&quot;nofollow&quot;&gt;TwitBird&lt;/a&gt;"},{"from_user_id_str":"19603191","profile_image_url":"http://a1.twimg.com/profile_images/1254077264/116_normal.gif","created_at":"Fri, 25 Feb 2011 17:36:40 +0000","from_user":"Purple_Flash","id_str":"41189851873157120","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @syu_thi_bot: \u3044\u3064\u307e\u3067Twitter\u3084\u3063\u3066\u308b\u3093\u3060\u3044\uff1f\u3044\u3044\u52a0\u6e1b\u73fe\u5b9f\u306b\u623b\u308a\u306a\u3088\u3002\u3053\u3053\u306f\u30ad\u30df\u305f\u3061\u4e09\u6b21\u5143\u306e\u4eba\u9593\u304c\u3044\u308b\u3079\u304d\u5834\u6240\u3058\u3083\u306a\u3044\u3093\u3060\u3088\u3002\u305d\u3093\u306a\u306e\u57fa\u672c\u3060\u308d\uff01\uff01","id":41189851873157120,"from_user_id":19603191,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"215930291","profile_image_url":"http://a0.twimg.com/profile_images/1247906106/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:30 +0000","from_user":"minori_millie","id_str":"41189810055938048","metadata":{"result_type":"recent"},"to_user_id":212972774,"text":"@c_c_chika \u7b11\u3063\u3066\u305d\u3046\u3060\u306a\u3063\u3066\u601d\u3063\u3066\u305f(o^^o)\u30c1\u30ab\u306e\u7b11\u3044\u58f0\u304c\u805e\u3053\u3048\u3066\u304d\u305f\u3082\u3093\u3002mail\u306bTwitter\u3067\u5927\u5fd9\u3057\u3084\u3002","id":41189810055938048,"from_user_id":215930291,"to_user":"c_c_chika","geo":null,"iso_language_code":"ja","to_user_id_str":"212972774","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"197459334","profile_image_url":"http://a3.twimg.com/profile_images/1210698414/shiratorishoko_normal.png","created_at":"Fri, 25 Feb 2011 17:36:30 +0000","from_user":"SyokoShiratori","id_str":"41189809586311168","metadata":{"result_type":"recent"},"to_user_id":null,"text":"+0.90kg \u30c0\u30a4\u30a8\u30c3\u30c8\u5fdc\u63f4\u3057\u3066\u307e\u3059\u3002(*^^*)\u30c0\u30a4\u30a8\u30c3\u30c8\u4f53\u91cd\u5831\u544a\u306e\u3064\u3076\u3084\u304d\u3067\u3059\u3002 http://bit.ly/fhN2fM RT @hayayumi \u3053\u3093\u306a\u6642\u9593\u306b\u3084\u304d\u306b\u304f\u30fc\u266b\u30c0\u30a4\u30a8\u30c3\u30c8\u671f\u9593\u306a\u306e\u306b\u306d....","id":41189809586311168,"from_user_id":197459334,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://mob-mc.com&quot; rel=&quot;nofollow&quot;&gt;\uff08\u4eee\u79f0\uff09\u30c4\u30a4\u30af\u30ea\u30c3\u30af twiclick&lt;/a&gt;"},{"from_user_id_str":"12337665","profile_image_url":"http://a0.twimg.com/profile_images/1146194926/pixiv-icon_normal.png","created_at":"Fri, 25 Feb 2011 17:36:27 +0000","from_user":"t_a_k_i","id_str":"41189797364121600","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Google\u30ea\u30fc\u30c0\u30fc\u3067\u30b5\u30a4\u30c8\u306e\u66f4\u65b0\u30c1\u30a7\u30c3\u30af\u3059\u308b\u3088\u308a\u3001Twitter\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u30d5\u30a9\u30ed\u30fc\u3057\u3066\u66f4\u65b0\u3092\u77e5\u308b\u307b\u3046\u304c\u4fbf\u5229\u3060\u306a\u3053\u308c","id":41189797364121600,"from_user_id":12337665,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sites.google.com/site/yorufukurou/&quot; rel=&quot;nofollow&quot;&gt;YoruFukurou&lt;/a&gt;"},{"from_user_id_str":"104862453","profile_image_url":"http://a3.twimg.com/profile_images/1248609864/Image014_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:25 +0000","from_user":"yuz_ume","id_str":"41189787943714816","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @fuefukioyasumi: \u3082\u3046\u3044\u3044\u3002\u300c\u671d\u751f\u300d\u306a\u3093\u304b\u3044\u3044\u3002BBC\u3082CNN\u3082\u82f1\u8a9e\u653e\u9001\u3060\u3002\u307f\u3093\u306a\u3001\u30c6\u30ec\u30d3\u3092\u3076\u3061\u3063\u3068\u5207\u3063\u3066Twitter\u3092\u898b\u3088\u3046\u3002\u3053\u3053\u306b\u300c\u751f\u304d\u305f\u60c5\u5831\u300d\u304c\u6d41\u308c\u3066\u3044\u308b\u3002\u300c\u751f\u304d\u305f\u53eb\u3073\u300d\u304c\u3042\u308b\u3002\u3053\u3053\u304b\u3089\u3067\u3082\u6b74\u53f2\u306e\u8ee2\u63db\u70b9\u3092\u611f\u3058\u308b\u4e8b\u304c\u3067\u304d\u308b\u306e\u3060\u3002 @gjmorley #libjp","id":41189787943714816,"from_user_id":104862453,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"213846746","profile_image_url":"http://a1.twimg.com/profile_images/1242263342/haruhi1_normal.png","created_at":"Fri, 25 Feb 2011 17:36:23 +0000","from_user":"sloth888jpgame","id_str":"41189778409922560","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u643a\u5e2f\u96fb\u8a71\u7528\u306eTwitter\u3092\u5229\u7528\u3057\u305f\u30b2\u30fc\u30e0\u3092\u77e5\u3063\u3066\u3044\u308b\u4eba\u306f\u3001\u7d39\u4ecb\u3057\u3066\u304f\u3060\u3055\u3044\u3002 #TwitterGame","id":41189778409922560,"from_user_id":213846746,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"17484724","profile_image_url":"http://a2.twimg.com/profile_images/1138677235/iconue_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:22 +0000","from_user":"tsutcho","id_str":"41189777831231490","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30a2\u30aa\u30b7\u30de\u3055\u3093twitter\u306b\u7acb\u3064\u30fb\u30fb\u30fb\u3060\u3068\u30fb\u30fb\u30fb\uff1f\uff12\u756a\u76ee\u306e\u30d5\u30a9\u30ed\u30ef\u30fc\u306e\u5ea7\u3092\u3044\u305f\u3060\u3044\u3066\u304a\u3053\u3046","id":41189777831231490,"from_user_id":17484724,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"220041064","profile_image_url":"http://a1.twimg.com/sticky/default_profile_images/default_profile_0_normal.png","created_at":"Fri, 25 Feb 2011 17:36:21 +0000","from_user":"sloth888jp_bot5","id_str":"41189772521254914","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6642\u3005\u3001TwiAll\uff08\u30c4\u30a4\u30aa\u30fc\u30eb\uff09\u3067Twitter\u306e\u81ea\u52d5\u30d5\u30a9\u30ed\u30fc\u30fb\u30d5\u30a9\u30ed\u30fc\u8fd4\u3057\u3092\u3057\u3066\u3044\u307e\u3059\u3002","id":41189772521254914,"from_user_id":220041064,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twittbot.net/&quot; rel=&quot;nofollow&quot;&gt;twittbot.net&lt;/a&gt;"},{"from_user_id_str":"177693537","profile_image_url":"http://a0.twimg.com/profile_images/1240130924/20110207213206_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:21 +0000","from_user":"Na_Okinawa","id_str":"41189769912397824","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @ebizo66: \u30ea\u30d3\u30a2\u30fb\u30c8\u30ea\u30dd\u30ea\u306eTw\uff1a\u6551\u6025\u8eca\u304c\u6765\u305f\u304c\u3001\u8ca0\u50b7\u8005\u3092\u8eca\u5185\u3067\u6bba\u5bb3\u3057\u3066\u3044\u305f\u3001\u3068\u3002\uff08\u6ec5\u8336\u82e6\u8336\u3060\uff01\uff09http://ow.ly/43pQ2 #libjp","id":41189769912397824,"from_user_id":177693537,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"147006592","profile_image_url":"http://a2.twimg.com/profile_images/1251306448/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:19 +0000","from_user":"takasu_rika","id_str":"41189763532865536","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @kihirokiro: Twitter\u3067\u30cd\u30bf\u30d0\u30ec\u4e91\u3005\u3044\u3063\u3066\u3082\u5143\u3005Twitter\u3063\u3066\u300c\u500b\u4eba\u306e\u72ec\u308a\u8a00\u300d\u3060\u308d","id":41189763532865536,"from_user_id":147006592,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"100239985","profile_image_url":"http://a1.twimg.com/profile_images/733461294/CIMG0207_normal.JPG","created_at":"Fri, 25 Feb 2011 17:36:19 +0000","from_user":"strangebarjun","id_str":"41189762182152192","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Twitter\u3092\u59cb\u3081\u3066\u3001\u305d\u308d\u305d\u308d\u4e00\u5e74\u306b\u306a\u308a\u307e\u3059\u3002\u632f\u308a\u8fd4\u308b\u3068\u3001\u307c\u304f\u306e\u4eba\u9593\u6027\u3092\u305d\u3063\u304f\u308a\u53cd\u6620\u3059\u308b\u304c\u5982\u304f\u3001\u534a\u7aef\u3067\u3059\u306d\u3002\u60c5\u5831\u53ce\u96c6\u30c4\u30fc\u30eb\u3001\u60c5\u5831\u767a\u4fe1\u30c4\u30fc\u30eb\u3001\u30b3\u30df\u30e5\u30cb\u30b1\u30fc\u30b7\u30e7\u30f3\u30c4\u30fc\u30eb\u3001\u3069\u308c\u3082\u6a5f\u80fd\u3057\u5207\u308c\u3066\u3044\u306a\u3044\u306a\u3042\u3001\u3068\u3002\u305d\u3057\u3066\u3042\u308b\u306e\u306f\u300c\u3069\u3053\u304b\u3089\u3082\u76f8\u624b\u306b\u3055\u308c\u3066\u3044\u306a\u3044\u300d\u3068\u3044\u3046\u3001\u65e2\u77e5\u306e\u73fe\u5b9f\u3067\u3059\u3002","id":41189762182152192,"from_user_id":100239985,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"126390384","profile_image_url":"http://a2.twimg.com/profile_images/1176065038/nemunemu_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:18 +0000","from_user":"gesukapper","id_str":"41189757476286464","metadata":{"result_type":"recent"},"to_user_id":80935865,"text":"@tatsugorou \u306a\u3093\u304b\u4e16\u306e\u4e2d\u306b\u306f\u611a\u75f4\u3082\u4e0b\u30cd\u30bf\u3082\u8a00\u3044\u653e\u984c\u306etwitter\u3068\u3044\u3046\u3082\u306e\u304c\u3042\u308b\u305d\u3046\u3067\u3059\u3002","id":41189757476286464,"from_user_id":126390384,"to_user":"tatsugorou","geo":null,"iso_language_code":"ja","to_user_id_str":"80935865","source":"&lt;a href=&quot;http://janetter.net/&quot; rel=&quot;nofollow&quot;&gt;Janetter&lt;/a&gt;"},{"from_user_id_str":"196059029","profile_image_url":"http://a1.twimg.com/profile_images/1208831726/ruka2_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:17 +0000","from_user":"luka_m_bot","id_str":"41189756666777600","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u308f\u305f\u3057\u3082twitter\u306f\u3058\u3081\u307e\u3057\u305f","id":41189756666777600,"from_user_id":196059029,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www24.atpages.jp/aoi2/bot.php&quot; rel=&quot;nofollow&quot;&gt;\u5de1\u308b\u97f3&lt;/a&gt;"},{"from_user_id_str":"88135613","profile_image_url":"http://a3.twimg.com/profile_images/1088552877/P9280150_normal.JPG","created_at":"Fri, 25 Feb 2011 17:36:14 +0000","from_user":"Roko38","id_str":"41189740321587200","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\uff46\uff42\u306b\u30ed\u30b0\u30a4\u30f3\u3059\u308b\u6a5f\u4f1a\u304c\u65e5\u306b\u65e5\u306b\u5897\u3048\u3066\u304d\u305f\uff3e\uff3e \u6163\u308c\u3066\u304f\u308b\u3068\u3042\u3063\u3061\u306e\u304c\u9762\u767d\u3044\uff06\u4f7f\u3044\u52dd\u624b\u304c\u3044\u3044\u3088\u3046\u306a\u6c17\u304c\u3059\u308b\u3002\u8907\u5408\u7684\u306b\u8272\u3005\u51fa\u6765\u307e\u3059\u3088\u306d\u2026\u3063\u3066\u3001\u601d\u3063\u305f\u3053\u3068\u3092\u545f\u304f\u306e\u306fTwitter\u3060\u3063\u305f\u308a\u3067\u3059\u304c\u2026(^_^; \u305d\u3057\u3066\u81ea\u5206\u306e\u5834\u5408\u306f\u30c4\u30a4\u3068\u9023\u52d5\u3057\u3065\u3089\u3044\u72b6\u6cc1\u3060\u3063\u305f\u308a\u3067\u2026\u3002","id":41189740321587200,"from_user_id":88135613,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"110825211","profile_image_url":"http://a2.twimg.com/profile_images/1108977866/o_t_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:12 +0000","from_user":"kou_nanjyo","id_str":"41189731941363712","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @x68k: \u57fa\u672c\u7684\u306bTwitter\u4e0a\u3067\u306f&quot;\u597d\u304d\u306b\u3084\u308c\u3070\u3044\u3044&quot;\u3060\u3051\u3069\u3001\u540d\u524d\u3082\u30a2\u30a4\u30b3\u30f3\u3082\u30a2\u30f3\u30bf\u3058\u3083\u306a\u3044\u305f\u304f\u3055\u3093\u306e\u4eba\u305f\u3061\u306e\u9b42\u304c\u3053\u3082\u3063\u305f\u3082\u306e\u306a\u306e\u3060\u304b\u3089\u3001\u305d\u308c\u3060\u3051\u306f&quot;\u80cc\u8ca0\u3048&quot;\u3068\u601d\u3046\uff1e\u30ad\u30e3\u30e9\u30af\u30bf\u30fc\u30a2\u30ab\u30a6\u30f3\u30c8","id":41189731941363712,"from_user_id":110825211,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://tweetlogix.com&quot; rel=&quot;nofollow&quot;&gt;Tweetlogix&lt;/a&gt;"},{"from_user_id_str":"2095960","profile_image_url":"http://a2.twimg.com/profile_images/1248999075/majiresu2_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:10 +0000","from_user":"guldeen","id_str":"41189726945947648","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3042\u308a\u3083\u307e\u3041\u3002\u25bchttp://bit.ly/et4vVa \uff3b\u89d2\u5ddd\u66f8\u5e97\uff3d\u300c\u30b6\u30fb\u30b9\u30cb\u30fc\u30ab\u30fc\u300d\u4f11\u520a\u3078\u3000\u300c\u6dbc\u5bae\u30cf\u30eb\u30d2\u300d\u751f\u3093\u3060\u30e9\u30ce\u30d9\u96d1\u8a8c18\u5e74\u3067\u5e55 via http://twitter.com/lkj777","id":41189726945947648,"from_user_id":2095960,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"164121549","profile_image_url":"http://a1.twimg.com/profile_images/1251758789/m_108-07ae3_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:09 +0000","from_user":"hachi_touhi","id_str":"41189719299727360","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30cd\u30bf\u30d0\u30ec\u6c17\u306b\u3057\u3066\u305f\u3089Twitter\u3084\u3063\u3066\u3089\u308c\u306a\u3044ww","id":41189719299727360,"from_user_id":164121549,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twicca.r246.jp/&quot; rel=&quot;nofollow&quot;&gt;twicca&lt;/a&gt;"},{"from_user_id_str":"194494659","profile_image_url":"http://a3.twimg.com/profile_images/1249717822/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:36:08 +0000","from_user":"tomonattomo","id_str":"41189715415801856","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3046\u308f\u3001\u660e\u65e5\u671d\u304b\u3089\u30d0\u30a4\u30c8\u3084\u306e\u306b\u306a\u3093\u3060\u3053\u306e\u306d\u3075\u304b\u3057\u3002\u3042\u3001\u591c\u66f4\u304b\u3057\u3002\u30d1\u30d4\u30eb\u30b9\u3068BUMP\u3001\u3048\u307f\u3068Twitter\u306eDM\u3057\u3059\u304e\u305f\u306a\u2026","id":41189715415801856,"from_user_id":194494659,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://mixi.jp/promotion.pl?id=voice_twitter&quot; rel=&quot;nofollow&quot;&gt; mixi \u30dc\u30a4\u30b9 &lt;/a&gt;"},{"from_user_id_str":"97224364","profile_image_url":"http://a3.twimg.com/profile_images/1150074355/fb8bcca60d340862c053a756377bfae8_normal.jpeg","created_at":"Fri, 25 Feb 2011 17:36:06 +0000","from_user":"xxxheat","id_str":"41189709174677504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Twitter\u5b8c\u5168\u306b\u30d0\u30b0\u3063\u3066\u308borz","id":41189709174677504,"from_user_id":97224364,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"}],"max_id":41190705623732224,"since_id":38643906774044672,"refresh_url":"?since_id=41190705623732224&q=twitter","next_page":"?page=2&max_id=41190705623732224&rpp=100&lang=ja&q=twitter","results_per_page":100,"page":1,"completed_in":0.093336,"warning":"adjusted since_id to 38643906774044672 (), requested since_id was older than allowed -- since_id removed for pagination.","since_id_str":"38643906774044672","max_id_str":"41190705623732224","query":"twitter"}
diff --git a/benchmarks/json-data/jp50.json b/benchmarks/json-data/jp50.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/jp50.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"2458313","profile_image_url":"http://a2.twimg.com/profile_images/1203653060/fure091226_normal.png","created_at":"Thu, 27 Jan 2011 20:30:04 +0000","from_user":"19princess","id_str":"30724239224995840","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6d77\u6674\u300c\u672c\u65e5\u306e\u6771\u4eac\u306e\u304a\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3067\u3057\u3087\u3046\u3002\u6700\u9ad8\u6c17\u6e29\u306f8\u5ea6\u3001\u6700\u4f4e\u6c17\u6e29\u306f1\u5ea6\u3067\u3059\u3002\u3042\u306a\u305f\u306e\u4eca\u65e5\u306e\u4eba\u751f\u306b\u3068\u3073\u3063\u304d\u308a\u306e\u304a\u5929\u6c17\u3092\u2665\u300d","id":30724239224995840,"from_user_id":2458313,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://babyprincess.sakura.ne.jp/about/&quot; rel=&quot;nofollow&quot;&gt;\u5929\u4f7f\u5bb6\u306e\u88cf\u5c71&lt;/a&gt;"},{"from_user_id_str":"66578965","profile_image_url":"http://a0.twimg.com/profile_images/1183763267/fossetta_normal.png","created_at":"Thu, 27 Jan 2011 20:00:04 +0000","from_user":"Fossetta_Tokyo","id_str":"30716689779785729","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059!!\u6771\u4eac\u90fd\u3001\u672c\u65e5\u306e\u304a\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3002\u6700\u9ad8\u6c17\u6e298\u5ea6\u3001\u6700\u4f4e\u6c17\u6e291\u5ea6\u3002\u6771\u4eac\u5730\u65b9\u3067\u306f\u3001\u7a7a\u6c17\u306e\u4e7e\u71e5\u3057\u305f\u72b6\u614b\u304c\u7d9a\u3044\u3066\u3044\u307e\u3059\u3002\u706b\u306e\u53d6\u308a\u6271\u3044\u306b\u6ce8\u610f\u3057\u3066\u4e0b\u3055\u3044\u3002\u4f0a\u8c46\u8af8\u5cf6\u3068\u5c0f\u7b20\u539f\u8af8\u5cf6\u306b\u306f\u3001\u5f37\u98a8\u3001\u6ce2\u6d6a\u3001\u4e7e\u71e5\u3001\u971c\u306e\u6ce8\u610f\u5831\u3092\u767a\u8868\u4e2d\u3067\u3059\u3002","id":30716689779785729,"from_user_id":66578965,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bit.ly/Fossetta&quot; rel=&quot;nofollow&quot;&gt;\u30d5\u30a9\u30bb\u30c3\u30bf ver.3.1.1&lt;/a&gt;"},{"from_user_id_str":"104041146","profile_image_url":"http://a2.twimg.com/profile_images/863965118/001jwatokyo_normal.jpg","created_at":"Thu, 27 Jan 2011 19:44:33 +0000","from_user":"jwa_tokyo","id_str":"30712787537756160","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6c17\u8c61\u5e81\u304b\u3089\u6771\u4eac\u306e\u5929\u6c17\u4e88\u5831\u304c\u767a\u8868\u3055\u308c\u307e\u3057\u305f\u3000\u305d\u306e\u5929\u6c17\u4e88\u5831\u3092\u3053\u3053\u3067\u3064\u3076\u3084\u3053\u3046\u304b\u306a\u3041\uff5e\uff1f\u3000\u8003\u3048\u4e2d\u3000\u307e\u3066\u6b21\u53f7\uff08\u7b11","id":30712787537756160,"from_user_id":104041146,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.docodemo.jp/twil/&quot; rel=&quot;nofollow&quot;&gt;Twil2 (Tweet Anytime, Anywhere by Mail)&lt;/a&gt;"},{"from_user_id_str":"144500192","profile_image_url":"http://a3.twimg.com/a/1294874399/images/default_profile_3_normal.png","created_at":"Thu, 27 Jan 2011 18:59:33 +0000","from_user":"kyo4to4","id_str":"30701462774358016","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u90fd \u516b\u4e08\u5cf6 - \u4eca\u65e5\u306e\u5929\u6c17\u306f\u30fb\u30fb\u30fb\u66c7\u306e\u3061\u6674\u3067\u3059\u306e\uff01","id":30701462774358016,"from_user_id":144500192,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/kyo4to4&quot; rel=&quot;nofollow&quot;&gt;lost-sheep-bot&lt;/a&gt;"},{"from_user_id_str":"165724582","profile_image_url":"http://a0.twimg.com/profile_images/1222842347/163087_1256281064506_1753997852_484926_2761052_n_normal.jpg","created_at":"Thu, 27 Jan 2011 17:39:06 +0000","from_user":"Rifqi_19931020","id_str":"30681213748387840","metadata":{"result_type":"recent"},"to_user_id":113796067,"text":"@CHLionRagbaby \u30b1\u30f3\u3061\u3083\u3093\u3001\u671d\u4eca\u307e\u3067\u306e\u81ea\u5206\u306e\u30db\u30fc\u30e0\u30a8\u30ea\u30a2\u304b\u3089\u307e\u3060\u975e\u5e38\u306b\u5bd2\u3044\u3068\u96e8\u304c\u964d\u3063\u3066\u3044\u305f..\u3069\u306e\u3088\u3046\u306b\u73fe\u5728\u306e\u6771\u4eac\u306e\u5929\u6c17\uff1f","id":30681213748387840,"from_user_id":165724582,"to_user":"CHLionRagbaby","geo":null,"iso_language_code":"ja","to_user_id_str":"113796067","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"120911929","profile_image_url":"http://a0.twimg.com/profile_images/772435076/20100312___capture2_normal.png","created_at":"Thu, 27 Jan 2011 17:28:30 +0000","from_user":"Cirno_fan","id_str":"30678546020040705","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u65e5\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u3001\u66c7\u6642\u3005\u6674\u3067\u6700\u9ad8\u6c17\u6e29\u306f8\u2103\uff01 \u6700\u4f4e\u6c17\u6e29\u306f2\u2103\u3060\u3063\u305f\u3088\uff01 RT @mimi22999 \uff08\uff65\u2200\uff65\uff09\uff4c\u3001\u865a\u5f31\u306a\u8005\u306b\u3068\u3063\u3066\u3001\u6717\u3089\u304b\u306a\u9854\u306f\u4e0a\u5929\u6c17\u3068\u540c\u3058\u304f\u3089\u3044\u3046\u308c\u3057\u3044\u3082\u306e\u3060\u3002\u30d5\u30e9\u30f3\u30af\u30ea\u30f3 #tenki #bot","id":30678546020040705,"from_user_id":120911929,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://blog.livedoor.jp/fairycirno/archives/34686.html&quot; rel=&quot;nofollow&quot;&gt;\u5e7b\u60f3\u90f7 \u9727\u306e\u6e56&lt;/a&gt;"},{"from_user_id_str":"65976527","profile_image_url":"http://a0.twimg.com/profile_images/452810990/little_italies_____normal.jpg","created_at":"Thu, 27 Jan 2011 17:00:03 +0000","from_user":"heta_weather01","id_str":"30671388754845696","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u30d8\u30bf\u5929\u3011Tere hommikust.\u30a8\u30b9\u30c8\u30cb\u30a2\u3067\u3059\u3002\u4eca\u65e5\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u6674\u6642\u3005\u66c7\u3067\u660e\u65e5\u306f\u66c7\u308a\u3067\u3059\u3002\u3061\u306a\u307f\u306b\u50d5\u306e\u3068\u3053\u308d\u3067\u306f\u66c7\u308a\u3067\u6c17\u6e29-7\u2103\u3067\u3059\u3002\u3061\u306a\u307f\u306b\u30b9\u30ab\u30a4\u30d7\u306e\u958b\u767a\u672c\u90e8\u306f\u50d5\u306e\u5bb6\u306b\u3042\u308b\u3093\u3067\u3059\u3002","id":30671388754845696,"from_user_id":65976527,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www15.atpages.jp/~kageyanma/&quot; rel=&quot;nofollow&quot;&gt;\u5730\u7403\u306e\u4e2d&lt;/a&gt;"},{"from_user_id_str":"7278433","profile_image_url":"http://a3.twimg.com/profile_images/1218965303/michael-1_normal.png","created_at":"Thu, 27 Jan 2011 16:50:16 +0000","from_user":"shimohiko","id_str":"30668926035689472","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3042\u308a\u3002\n\u3010\u7f8e\u4eba\u5929\u6c17/\u6771\u4eac\u3011\u7f8e\u4eba\u5929\u6c17\u30ad\u30e3\u30b9\u30bf\u30fc\u306e&quot;\u3055\u3042\u3084\u3093\u3055\u3093&quot;\u306b\u3088\u308b\u3068\u300c1/29(\u571f)\u306f\u304f\u3082\u308a\u3067\u3001\u964d\u6c34\u78ba\u738740%\u3001\u6700\u9ad8\u6c17\u6e29\u306f6\u2103\u3067\u6700\u4f4e\u6c17\u6e29\u306f1\u2103\u3067\u3059\u300d\u7f8e\u4eba\u5929\u6c17\u21d2http://bit.ly/djB8th http://twitpic.com/3twnl0 #bt_tenki","id":30668926035689472,"from_user_id":7278433,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bijintenki.jp&quot; rel=&quot;nofollow&quot;&gt;bijintenki.jp&lt;/a&gt;"},{"from_user_id_str":"61770","profile_image_url":"http://a3.twimg.com/profile_images/1206955079/tw172a_normal.png","created_at":"Thu, 27 Jan 2011 16:40:52 +0000","from_user":"rsky","id_str":"30666561853333504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3075\u3068\u591c\u7a7a\u3092\u898b\u4e0a\u3052\u3066\u30aa\u30ea\u30aa\u30f3\u304c\u898b\u3048\u306a\u304f\u3066\u300c\u6771\u4eac\u306b\u306f\u7a7a\u304c\u306a\u3044\u300d\u3068\u667a\u6075\u5b50\u306e\u3088\u3046\u306a\u3053\u3068\u3092\u601d\u3063\u305f\u308f\u3051\u3060\u304c\u3001\u305f\u3076\u3093\u534a\u5206\u3050\u3089\u3044\u306f\u5929\u6c17\u306e\u305b\u3044\u3067\u3059","id":30666561853333504,"from_user_id":61770,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"103259265","profile_image_url":"http://a0.twimg.com/profile_images/767857973/anime_icon_normal.gif","created_at":"Thu, 27 Jan 2011 16:37:42 +0000","from_user":"liveshowonly","id_str":"30665765698928640","metadata":{"result_type":"recent"},"to_user_id":null,"text":"iPhone\u5929\u6c17\u3002\u6771\u4eac4\u2103\u3063\u3066\u7d50\u69cb\u5bd2\u304f\u306a\u3044\u3058\u3083\u3093\u3002\uff08\u78ba\u304b\u306b\u3082\u306e\u51c4\u304f\u5bd2\u3044\u8a33\u3067\u306f\u7121\u3044\uff09\u3002\u798f\u5ca1\u5e02\u306f1\u2103\u3060\u3002\u52dd\u3061\u3060\u305c\u3002Rock'n'roll","id":30665765698928640,"from_user_id":103259265,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"165242761","profile_image_url":"http://a1.twimg.com/profile_images/1147334744/SN3E00600001_normal.jpg","created_at":"Thu, 27 Jan 2011 16:37:35 +0000","from_user":"deuxavril0502","id_str":"30665736556912640","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6b8b\u5ff5\u3001\u79c1\u306f\u6c96\u7e04\u3067\u3059(&gt;_&lt;)\u3067\u3082\u304a\u5929\u6c17\u826f\u3055\u305d\u3046\u3067\u826f\u304b\u3063\u305f\u306d\u3002\u3053\u3061\u3089\u306f\u96e8\u3088\uff5eRT @rinandy2010: \u305d\u3046\u3067\u3059\u3063\u266a\u51fa\u5f35\u3067(^^)\u304a\u306d\u3048\u3055\u307e\u306f\u6771\u4eac\u3067\u3059\u304b\uff1f\u3081\u3063\u3061\u3083\u5929\u6c17\u826f\u304f\u3066\u3073\u3063\u304f\u308a\u3067\u3059\u3002\u624b\u888b\u3068\u304b\u5168\u7136\u3044\u3089\u306a\u3044\u3067\u3059\u306d\u30fc RT @deuxavril0502 \u6771\u4eac\u306a\u306e\u30fc\uff1f","id":30665736556912640,"from_user_id":165242761,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"163900288","profile_image_url":"http://a1.twimg.com/profile_images/1210224823/icon12945064955238_normal.jpg","created_at":"Thu, 27 Jan 2011 16:24:37 +0000","from_user":"nyao_yurichan","id_str":"30662472734089216","metadata":{"result_type":"recent"},"to_user_id":100985873,"text":"@ray_ko302 \u767a\u898b\u3042\u308a\u304c\u3068\u3067\u3059\u3045\u3002\u3053\u3061\u3089\u3067\u3082\u3088\u308d\u3057\u304f\u306d\u3002\u6771\u4eac\u306f\u4eca\u65e5\u3082\u4e7e\u71e5\u3067\u5927\u5909\u3088\u3002\u305d\u3063\u3061\u3068\u771f\u9006\u306e\u5929\u6c17\u3060\u306d\u3002\u30a2\u30a4\u30b9\u30d0\u30fc\u30f3\u304d\u3092\u3064\u3051\u3066\u3088\u306d\u3002","id":30662472734089216,"from_user_id":163900288,"to_user":"ray_ko302","geo":null,"iso_language_code":"ja","to_user_id_str":"100985873","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"49227098","profile_image_url":"http://a3.twimg.com/profile_images/965007882/____normal.jpg","created_at":"Thu, 27 Jan 2011 15:52:26 +0000","from_user":"dosannko6","id_str":"30654371016478720","metadata":{"result_type":"recent"},"to_user_id":108570870,"text":"@peke_hajiP \u4ffa\u304c\u6771\u4eac \u6765\u3066\u6700\u521d\u306b\u9a5a\u3044\u305f\u306e\u304c\u3001\u5929\u6c17\u4e88\u5831\u3067\u82b1\u7c89\u60c5\u5831\u304c\u6d41\u308c\u308b\u3053\u3068\u3067\u3001\u6700\u521d\u306b\u8a66\u3057\u305f\u306e\u304c \u30b4\u30ad\u69d8 \u53ec\u559a\u306e\u5100\u5f0f\u3067\u3059\u304a\uff1f","id":30654371016478720,"from_user_id":49227098,"to_user":"peke_hajip","geo":null,"iso_language_code":"ja","to_user_id_str":"108570870","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"71148934","profile_image_url":"http://a0.twimg.com/profile_images/1209223630/image_normal.jpg","created_at":"Thu, 27 Jan 2011 15:46:49 +0000","from_user":"123keiko","id_str":"30652958311981058","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u9727\u5cf6\u306e\u964d\u7070\u306e\u30cb\u30e5\u30fc\u30b9\u3092\u898b\u3066\u601d\u3044\u51fa\u3057\u307e\u3057\u305f\u3002\u4e0a\u4eac\u3057\u305f\u59cb\u3081\u306e\u9803\u3001\u6771\u4eac\u306f1\u5e74\u4e2d\u3001\u7070\u304c\u964d\u3089\u306a\u3044\u304b\u3089\u7a7a\u6c17\u304c\u6f84\u3093\u3067\u3066\u904e\u3054\u3057\u3084\u3059\u3044\u306a\u3041\u3001\u3068\u601d\u3063\u305f\u306a\u3041\u3001\u3063\u3066\u3002\n\u5b9f\u5bb6\u306f\u51ac\u306e\u5b63\u7bc0\u98a8\u3067\u685c\u5cf6\u306e\u7070\u304c\u964d\u308b\u5730\u533a\u3067\u3057\u305f\u3002\u9e7f\u5150\u5cf6\u306e\u5929\u6c17\u4e88\u5831\u3067\u306f\u3001\u6bce\u65e5\u3001\u685c\u5cf6\u4e0a\u7a7a\u306e\u98a8\u5411\u304d\u4e88\u5831\u304c\u3067\u307e\u3059\u3002\u3053\u308c\u304b\u3089\u306f\u9727\u5cf6\u3082\u304b\u306a\uff1f","id":30652958311981058,"from_user_id":71148934,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"91124773","profile_image_url":"http://a3.twimg.com/profile_images/1139308356/prof101007_3-1_normal.jpg","created_at":"Thu, 27 Jan 2011 15:43:35 +0000","from_user":"sanposuruhito","id_str":"30652146277945345","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u5bb5\u306e\u90fd\u5fc3\u306f\u3001\u8eab\u3082\u5f15\u304d\u7de0\u307e\u308b\u3068\u3044\u3046\u3088\u308a\u306f\u51cd\u3048\u308b\u7a0b\u306e\u51b7\u6c17\u3092\u611f\u3058\u308b\u5bd2\u3044\u591c\u3067\u3059\u3002\u660e\u65e5\u65e5\u4e2d\u306e\u6771\u4eac\u306e\u5929\u6c17\u306f\u3001\u5915\u65b9\u306b\u591a\u5c11\u96f2\u304c\u51fa\u308b\u5834\u6240\u304c\u3042\u308a\u305d\u3046\u306a\u3082\u306e\u306e\u6982\u306d\u6674\u308c\u7a7a\u304c\u5e83\u304c\u308a\u7d9a\u3051\u305d\u3046\u3067\u3059\u3002\u6700\u9ad8\u6c17\u6e29\u306f\u30015-6\u5ea6\u4f4d\u3068\u306a\u308a\u305d\u3046\u3067\u3059\u3002#weather_tokyo","id":30652146277945345,"from_user_id":91124773,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://projects.playwell.jp/go/Saezuri&quot; rel=&quot;nofollow&quot;&gt;Saezuri&lt;/a&gt;"},{"from_user_id_str":"104712480","profile_image_url":"http://a3.twimg.com/profile_images/1204016928/icon5087697006727791368kuro2_normal.jpg","created_at":"Thu, 27 Jan 2011 15:31:51 +0000","from_user":"asongfor_xx","id_str":"30649192296751104","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u7f8e\u4eba\u5929\u6c17\u304b\u3089tweet\u3059\u308b\u3068\u3053\u3093\u306a\u611f\u3058\u306a\u3093\u3060\u306a\u3002 RT asongfor_xx: \u3010\u7f8e\u4eba\u5929\u6c17/\u6771\u4eac\u3011\u7f8e\u4eba\u5929\u6c17\u30ad\u30e3\u30b9\u30bf\u30fc\u306e&quot;\u304b\u306a\u3053\u3055\u3093&quot;\u306b\u3088\u308b\u3068\u300c1/28(\u91d1)\u306f\u6674\u6642\u3005\u304f\u3082\u308a\u3067\u3001\u964d\u6c34\u78ba\u73870%\u3001\u6700\u9ad8\u6c17\u6e29\u306f8\u2103\u3067\u6700\u4f4e\u6c17\u6e29\u306f1\u2103\u3067\u3059\u300d\u7f8e\u4eba\u5929\u6c17\u21d2http://bit.ly/djB8th","id":30649192296751104,"from_user_id":104712480,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b for iPhone&lt;/a&gt;"},{"from_user_id_str":"165965113","profile_image_url":"http://a0.twimg.com/profile_images/1200885316/shogomeguro_normal.jpg","created_at":"Thu, 27 Jan 2011 15:24:35 +0000","from_user":"shogomeguro","id_str":"30647362477105152","metadata":{"result_type":"recent"},"to_user_id":null,"text":"2011.1.26 \u793e\u7a93\u304b\u3089\u3002\u4e0d\u601d\u8b70\u306a\u5929\u6c17\u3067\u3053\u306e\u5f8c\u96ea\u304c\u3061\u3089\u3064\u3044\u305f\u3093\u3060\u3088\u306d\u3002\u6771\u4eac\u306e\u521d\u96ea\u3067\u3057\u305f\u3002 http://instagr.am/p/BO_xn/","id":30647362477105152,"from_user_id":165965113,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://instagr.am&quot; rel=&quot;nofollow&quot;&gt;instagram&lt;/a&gt;"},{"from_user_id_str":"166018520","profile_image_url":"http://a0.twimg.com/profile_images/1207460953/100-40030_normal.jpg","created_at":"Thu, 27 Jan 2011 15:18:17 +0000","from_user":"115nayume","id_str":"30645776254238722","metadata":{"result_type":"recent"},"to_user_id":118384679,"text":"@dancinpea09 \u6771\u4eac\u3001\u660e\u65e5\u3082\u5929\u6c17\u826f\u3044\u307f\u305f\u3044\u3067\u3001\u3088\u304b\u3063\u305f\u3067\u3059\u306d\u30fc\u266a  \u30ca\u30a4\u30b9\u30c8\u30ea\u30c3\u30d7\uff01\u304a\u3084\u3059\u307f\u306a\u3055\u3044\u3002 http://twitpic.com/3tvun3","id":30645776254238722,"from_user_id":166018520,"to_user":"dancinpea09","geo":null,"iso_language_code":"ja","to_user_id_str":"118384679","source":"&lt;a href=&quot;http://tweetli.st/&quot; rel=&quot;nofollow&quot;&gt;TweetList!&lt;/a&gt;"},{"from_user_id_str":"202937674","profile_image_url":"http://a1.twimg.com/profile_images/1218797578/______2_normal.jpg","created_at":"Thu, 27 Jan 2011 15:11:48 +0000","from_user":"ryuusisan","id_str":"30644146498699264","metadata":{"result_type":"recent"},"to_user_id":203058384,"text":"@manaasutakshi \u6771\u4eac\u306f\u964d\u3063\u3066\u306a\u3044\u3093\u3067\u3059\u304b\u30fb\u30fb\u30fb\u5929\u6c17\u4e88\u5831\u306b\u3088\u308b\u3068\u660e\u65e5\u3082\u6771\u4eac\u306f\u964d\u3089\u306a\u3044\u305d\u3046\u3067\u3059\u306d\uff01\uff01\u79c1\u306e\u4f4f\u3093\u3067\u3044\u308b\u3068\u3053\u308d\u306f\u5fae\u5999\u306b\u964d\u308a\u305d\u3046\u3067\u51fa\u52e4\u6642\u306b\u964d\u3063\u3066\u305f\u3089\u3061\u3087\u3063\u3068\u5acc\u3060\u306a\u3041\u3000\u306a\u3093\u3066\u601d\u3044\u307e\u3059","id":30644146498699264,"from_user_id":202937674,"to_user":"manaasutakshi","geo":null,"iso_language_code":"ja","to_user_id_str":"203058384","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"3222182","profile_image_url":"http://a0.twimg.com/profile_images/1199090957/ProfilePhoto_normal.png","created_at":"Thu, 27 Jan 2011 15:09:35 +0000","from_user":"44mune","id_str":"30643589545459713","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u7f8e\u4eba\u5929\u6c17/\u6771\u4eac\u3011\u7f8e\u4eba\u5929\u6c17\u30ad\u30e3\u30b9\u30bf\u30fc\u306e&quot;\u306e\u308a\u3055\u3093&quot;\u306b\u3088\u308b\u3068\u300c1/28(\u91d1)\u306f\u304f\u3082\u308a\u306e\u3061\u6674\u3067\u3001\u964d\u6c34\u78ba\u738710%\u3001\u6700\u9ad8\u6c17\u6e29\u306f9\u2103\u3067\u6700\u4f4e\u6c17\u6e29\u306f2\u2103\u3067\u3059\u300d http://twitpic.com/3tvruh","id":30643589545459713,"from_user_id":3222182,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bijintenki.jp&quot; rel=&quot;nofollow&quot;&gt;bijintenki.jp&lt;/a&gt;"},{"from_user_id_str":"154341982","profile_image_url":"http://a0.twimg.com/profile_images/1155496864/_____normal.jpg","created_at":"Thu, 27 Jan 2011 15:02:39 +0000","from_user":"slave_420_bot","id_str":"30641845490946049","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u30f3\u3068\u3053\u899a\u3048\u3066\u308b\u306e\u306f\u300c\u672d\u5e4c\u300d\u300c\u4ed9\u53f0\u300d\u300c\u6771\u4eac\u300d\u300c\u5927\u962a\u300d\u300c\u540d\u53e4\u5c4b\u300d\u300c\u798f\u5ca1\u300d\u306e\u4eca\u65e5\u3068\u660e\u65e5\u306e\u5929\u6c17\u3060\u306a\u3002\u5929\u6c17\u304c\u77e5\u308a\u305f\u3044\u6642\u306f\u300c\u5834\u6240\u300d\u3068\u300c\u4eca\u65e5\u306e\u5929\u6c17\u300d\u304b\u300c\u660e\u65e5\u306e\u5929\u6c17\u300d\u3092\u304a\u7533\u3057\u4ed8\u3051\u304f\u3060\u3055\u3044\u3001\u304a\u5b22\u69d8\uff1f","id":30641845490946049,"from_user_id":154341982,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bot.syoyu.net/&quot; rel=&quot;nofollow&quot;&gt;\u7adc\u30f6\u5cf0\u90b8\u306e\u3069\u3053\u304b&lt;/a&gt;"},{"from_user_id_str":"72042678","profile_image_url":"http://a3.twimg.com/profile_images/1198771027/larxene_normal.jpg","created_at":"Thu, 27 Jan 2011 15:01:57 +0000","from_user":"larxene_bot","id_str":"30641668772339712","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u65e5\u306e\u5929\u6c17\u306f \u672d\u5e4c\u304c\u6674\u308c \u4ed9\u53f0\u304c\u66c7\u6642\u3005\u96ea \u6771\u4eac\u304c\u6674\u306e\u3061\u66c7 \u540d\u53e4\u5c4b\u304c\u6674\u6642\u3005\u66c7 \u5927\u962a\u304c\u6674\u6642\u3005\u66c7 \u798f\u5ca1\u304c\u6674\u308c \u3089\u3057\u3044\u308f\u3088 \u6ce8\u610f\u3057\u306a\u3055\u3044","id":30641668772339712,"from_user_id":72042678,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www4.kiwi-us.com/~yuuna/larxene_bot_manual/index.html&quot; rel=&quot;nofollow&quot;&gt;\u5fd8\u5374\u306e\u57ce \u5730\u4e0a\u306e12\u968e&lt;/a&gt;"},{"from_user_id_str":"101331893","profile_image_url":"http://a1.twimg.com/sticky/default_profile_images/default_profile_0_normal.png","created_at":"Thu, 27 Jan 2011 15:01:34 +0000","from_user":"yoshiftan","id_str":"30641572240424961","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u5929\u6c17\u4e88\u5831\u3092\u898b\u3066\u3073\u3063\u304f\u308a\uff01\u6691\u305d\u3046\u3060\u306a\u3053\u308a\u3083\u3002","id":30641572240424961,"from_user_id":101331893,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"Keitai Mail"},{"from_user_id_str":"65207550","profile_image_url":"http://a3.twimg.com/profile_images/448731969/_________R_normal.jpg","created_at":"Thu, 27 Jan 2011 15:01:33 +0000","from_user":"kabuyo","id_str":"30641566469066752","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u5929\u6c17\u4e88\u5831\u3067\u306f\u6771\u4eac\u3067\u306f\u4e7e\u71e5\u6ce8\u610f\u5831\u304c\u7d9a\u3044\u3066\u3044\u308b\u3089\u3057\u3044\u306e\u306b\u3001\u306a\u305c\u79c1\u304c\u5e72\u3057\u305f\u6d17\u6fef\u7269\u306f\u96e8\u306b\u6fe1\u308c\u3066\u3057\u307e\u3063\u305f\u306e\u3060\u308d\u3046\u304b\u2025\u3000\u3088\u3063\u307d\u3069\u904b\u304c\u60aa\u3044\u3089\u3057\u3044\u2025","id":30641566469066752,"from_user_id":65207550,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"80309352","profile_image_url":"http://a1.twimg.com/profile_images/1223620418/image_normal.jpg","created_at":"Thu, 27 Jan 2011 14:54:30 +0000","from_user":"mikutyan","id_str":"30639792026812416","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u660e\u65e5\u306e\u5929\u6c17\u6559\u3048\u3066","id":30639792026812416,"from_user_id":80309352,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"80309352","profile_image_url":"http://a1.twimg.com/profile_images/1223620418/image_normal.jpg","created_at":"Thu, 27 Jan 2011 14:53:06 +0000","from_user":"mikutyan","id_str":"30639439847890944","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u660e\u65e5\u306e\u6771\u4eac\u306e\u5929\u6c17\u306a\u3093\u3060\u308d\u3046 \u96e8\u964d\u3063\u305f\u3089\u56f0\u308b\u3002","id":30639439847890944,"from_user_id":80309352,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"120911929","profile_image_url":"http://a0.twimg.com/profile_images/772435076/20100312___capture2_normal.png","created_at":"Thu, 27 Jan 2011 14:47:19 +0000","from_user":"Cirno_fan","id_str":"30637984684449792","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3042\u305f\u3044\u30c1\u30eb\u30ce\uff01\u30dc\u30c3\u30c8\u3060\u3051\u3069\u5929\u6c17\u4e88\u5831\u3082\u3067\u304d\u308b\u3088\uff01\u300c\u6771\u4eac\u306e\u4eca\u65e5\u306e\u5929\u6c17\u6559\u3048\u3066\u300d\u307f\u305f\u3044\u306bTL\u767a\u8a00\u3057\u3066\u304f\u308c\u308c\u3070\u8abf\u3079\u3066\u3042\u3052\u308b\uff01 #followme #followmejp #followmevip #tenki","id":30637984684449792,"from_user_id":120911929,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://blog.livedoor.jp/fairycirno/archives/34686.html&quot; rel=&quot;nofollow&quot;&gt;\u5e7b\u60f3\u90f7 \u9727\u306e\u6e56&lt;/a&gt;"},{"from_user_id_str":"33858777","profile_image_url":"http://a0.twimg.com/profile_images/352864695/muga_normal.jpg","created_at":"Thu, 27 Jan 2011 14:46:12 +0000","from_user":"collonist","id_str":"30637702105796610","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u3063\u3066\u51ac\u306f\u57fa\u672c\u7684\u306b\u6674\u308c\u3066\u308b\u304b\u3089\u3001\u5929\u6c17\u4e88\u5831\u898b\u306a\u304f\u3066\u3082\u5168\u7136\u554f\u984c\u306a\u3044\u3002\u5c71\u5f62\u3060\u3068\u660e\u65e5\u306f\u3069\u3093\u3060\u3051\u96ea\u304c\u964d\u308b\u306e\u304b\u3001\u3069\u3093\u3060\u3051\u5bd2\u3044\u306e\u304b\u628a\u63e1\u3057\u3066\u3068\u304d\u305f\u3044\u306e\u3067\u3001\u5929\u6c17\u4e88\u5831\u306f\u5fc5\u305a\u30c1\u30a7\u30c3\u30af\u3057\u3066\u305f\u306e\u3060\u304c\u3002","id":30637702105796610,"from_user_id":33858777,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"79336228","profile_image_url":"http://a0.twimg.com/profile_images/1130029876/zmanmu_normal.png","created_at":"Thu, 27 Jan 2011 14:30:23 +0000","from_user":"atsuki777","id_str":"30633725041573890","metadata":{"result_type":"recent"},"to_user_id":null,"text":"MXTV\u306e\u5929\u6c17\u4e88\u5831\u521d\u3081\u3066\u898b\u305f\u3051\u3069\u6771\u4eac\u753a\u7530\u516b\u738b\u5b50\u3063\u3066\u5730\u57df\u8868\u793a\u304c\u2026w\u516b\u738b\u5b50\u3068\u753a\u7530\u306f\u6771\u4eac\u3058\u3083\u306a\u3044\u306e\u304bwww","id":30633725041573890,"from_user_id":79336228,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"90576097","profile_image_url":"http://a0.twimg.com/profile_images/1203320254/nanami1_normal.png","created_at":"Thu, 27 Jan 2011 14:28:26 +0000","from_user":"dycroft","id_str":"30633234245099521","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u660e\u65e5\u306e\u304a\u5929\u6c17\u3067\u3059","id":30633234245099521,"from_user_id":90576097,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"147215268","profile_image_url":"http://a2.twimg.com/profile_images/1198555202/ichika-7.4.0-3P_normal.gif","created_at":"Thu, 27 Jan 2011 14:28:23 +0000","from_user":"kiaran5032","id_str":"30633222211637248","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u660e\u65e5\u306e\u304a\u5929\u6c17\u3067\u3059\u3002\u6674\u308c\u6642\u3005\u304f\u3082\u308a #MX","id":30633222211637248,"from_user_id":147215268,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"1741599","profile_image_url":"http://a0.twimg.com/profile_images/1205744888/950637_normal.jpg","created_at":"Thu, 27 Jan 2011 14:28:21 +0000","from_user":"dasaitama","id_str":"30633212535382016","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u3001\u660e\u65e5\u306e\u304a\u5929\u6c17\u3067\u3059","id":30633212535382016,"from_user_id":1741599,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"34140879","profile_image_url":"http://a3.twimg.com/profile_images/1186413535/__6_normal.jpg","created_at":"Thu, 27 Jan 2011 14:28:17 +0000","from_user":"ryuji_chaos","id_str":"30633197016449024","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u660e\u65e5\u306e\u304a\u5929\u6c17\u3067\u3059\u3002","id":30633197016449024,"from_user_id":34140879,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"1400","profile_image_url":"http://a0.twimg.com/profile_images/1198556839/westerndog_20090104_320x320_normal.jpg","created_at":"Thu, 27 Jan 2011 14:28:16 +0000","from_user":"westerndog","id_str":"30633191232503808","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306e\u660e\u65e5\u306e\u304a\u5929\u6c17\u3067\u3059","id":30633191232503808,"from_user_id":1400,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"89239832","profile_image_url":"http://a3.twimg.com/profile_images/519522846/noriko_normal.jpg","created_at":"Thu, 27 Jan 2011 14:15:01 +0000","from_user":"Noriko_Fujimoto","id_str":"30629857234788352","metadata":{"result_type":"recent"},"to_user_id":115645219,"text":"@nossa430402 \u5bcc\u5c71\u306f\u3059\u3054\u3044\u96ea\u307f\u305f\u3044\u3067\u3059\u306d\uff5e\uff08\u5bd2\u3063\uff09\u3000\u6771\u4eac\u306f\u305d\u306e\u5206\u6bce\u65e5\u826f\u3044\u5929\u6c17\u3067\u3059\u3002\u5bd2\u3044\u3051\u3069\u30fb\u30fb\u30fb\u3002","id":30629857234788352,"from_user_id":89239832,"to_user":"nossa430402","geo":null,"iso_language_code":"ja","to_user_id_str":"115645219","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"107265539","profile_image_url":"http://a0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png","created_at":"Thu, 27 Jan 2011 14:01:10 +0000","from_user":"kurumasuki330","id_str":"30626371826884608","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u4eca\u9031\u571f\u66dc\u65e5\u3001\u8eca\u3067\u6771\u4eac\u304b\u3089\u6771\u540d\u3001\u7c73\u539f\u7d4c\u7531\u3067\u91d1\u6ca2\u306e\u5b9f\u5bb6\u3078\u3002\u305d\u3057\u3066\u3001\u6708\u66dc\u65e5\u306b\u6771\u4eac\u3078\u5e30\u308b\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\u3002\u5929\u6c17\u4e88\u5831\u3060\u3068\u4eca\u9031\u672b\u3001\u5317\u9678\u5730\u65b9\u306f\u5927\u96ea\uff01\u5e30\u308c\u308b\u304b\u81ea\u4fe1\u304c\u306a\u304f\u306a\u3063\u3066\u304d\u305f\u3002\u307e\u305f\u3001\u305d\u306e\u6642\u5b9f\u6cc1\u4e2d\u7d99\u3057\u307e\u3059\u3002","id":30626371826884608,"from_user_id":107265539,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twtr.jp&quot; rel=&quot;nofollow&quot;&gt;Keitai Web&lt;/a&gt;"},{"from_user_id_str":"155313166","profile_image_url":"http://a3.twimg.com/profile_images/1167554721/73931_1408370184003_1674923704_920888_5686998_n_normal.jpg","created_at":"Thu, 27 Jan 2011 14:00:50 +0000","from_user":"takuya_aoki","id_str":"30626287127105536","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306f\u3081\u3063\u3061\u3083\u3044\u3044\u5929\u6c17\u3067\u904e\u3054\u3057\u3084\u3059\u3044\u3051\u3069\u30c9\u30e9\u30a4\u30a2\u30a4\u306b\u306f\u3061\u3087\u3063\u3068\u304d\u3064\u3044\u306a\u30fb\u30fb\u30fb\u76ee\u85ac\u304c\u624b\u653e\u305b\u306a\u3044","id":30626287127105536,"from_user_id":155313166,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"179984398","profile_image_url":"http://a1.twimg.com/profile_images/1182382310/g4350_normal.jpg","created_at":"Thu, 27 Jan 2011 13:52:50 +0000","from_user":"aiilabo","id_str":"30624271902449664","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u30d6\u30ed\u30b0\u66f4\u65b0 \u25c6\u611f\u60c5\u3092\u307f\u3064\u3081\u308b\u65b9\u6cd5 - \u3053\u3053\u6570\u65e5\u3001\u6642\u6298\u96e8\u304c\u30d1\u30e9\u30d1\u30e9\u3000\u5fae\u5999\u306a\u5929\u6c17\u306e\u6771\u4eac\u304b\u3089\u3042\u308b\u304c\u307e\u307e\u3067\u3059\u3002 \n\n \u4eca\u65e5\u306f\u3001\u6628\u65e5\u306e\u300c\u30de\u30a4\u30ca\u30b9\u611f\u60c5\u306f\u60aa\u3067\u3059\u304b\uff1f\n.. \u27aa http://am6.jp/e3e9tS","id":30624271902449664,"from_user_id":179984398,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://feedtweet.am6.jp/&quot; rel=&quot;nofollow&quot;&gt;\u261e feedtweet.jp \u261c&lt;/a&gt;"},{"from_user_id_str":"185992391","profile_image_url":"http://a2.twimg.com/profile_images/1192695844/otenki_normal.png","created_at":"Thu, 27 Jan 2011 13:00:37 +0000","from_user":"otenki_luci_bot","id_str":"30611130938298368","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u767a\u58f2\u65e5\u304b\u2026\u2026\u541b\u305f\u3061\u306b\u3068\u3063\u3066\u306f\u591a\u5206\u300190\u65e5\u5f8c\u306e\u3053\u3068\u3060\u3002\u3055\u3066\u660e\u65e5\u306e\u6771\u4eac\u90fd\u306e\u5929\u6c17\u306f\u6674\u306e\u3061\u66c7\u3001\u6700\u9ad8\u6c17\u6e29\u306f8\u5ea6\u3060\u305d\u3046\u3060\u3002\u3055\u3059\u304c\u306b\u4f55\u304b\u7740\u305f\u65b9\u304c\u3044\u3044\u305e\u3001\u30a4\u30fc\u30ce\u30c3\u30af\u3002","id":30611130938298368,"from_user_id":185992391,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/otenki_luci_bot&quot; rel=&quot;nofollow&quot;&gt;\u304a\u3066\u3093\u304d\u308b\u3057\u3075\u3047\u308b&lt;/a&gt;"},{"from_user_id_str":"65976527","profile_image_url":"http://a0.twimg.com/profile_images/452810990/little_italies_____normal.jpg","created_at":"Thu, 27 Jan 2011 13:00:04 +0000","from_user":"heta_weather01","id_str":"30610995843964928","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u30d8\u30bf\u5929\u3011Jo napot.\u30cf\u30f3\u30ac\u30ea\u30fc\u3067\u3059\u3002\u6771\u4eac\u306e\u5929\u6c17\u306f\u6674\u306e\u3061\u66c7\u3067\u660e\u65e5\u306f\u6674\u6642\u3005\u66c7\u3001\u79c1\u306e\u3068\u3053\u308d\u3067\u306f\u66c7\u308a\u3067-2\u2103\u3067\u3059\u3002\u3048\u3001\u3053\u306e\u30d5\u30e9\u30a4\u30d1\u30f3\u3067\u3059\u304b\uff1f\u2026\u3061\u3087\u3063\u3068\u500b\u4eba\u7684\u306b\u6bb4\u308a\u305f\u3044\u4eba\u304c\u3044\u308b\u3093\u3067\u3059\u266a","id":30610995843964928,"from_user_id":65976527,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www15.atpages.jp/~kageyanma/&quot; rel=&quot;nofollow&quot;&gt;\u5730\u7403\u306e\u4e2d&lt;/a&gt;"},{"from_user_id_str":"109740077","profile_image_url":"http://a0.twimg.com/profile_images/1212763349/1d3d3821-6b3a-449f-a636-05b95ce3d5d8_normal.png","created_at":"Thu, 27 Jan 2011 12:59:41 +0000","from_user":"snow_arai","id_str":"30610896141156354","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u6771\u4eac\u306f\u3001\u30ab\u30e9\u30ab\u30e9\u9023\u7d9a\u3000\uff13\u4f4d\u30bf\u30a4 - \u65e9\u8d77\u304d\u2606\u304a\u5929\u6c17\u2606ONAIR\u65e5\u8a18\uff1a\u65e5\u7d4c\u30a6\u30fc\u30de\u30f3\u30aa\u30f3\u30e9\u30a4\u30f3 http://j.mp/hxP3Di","id":30610896141156354,"from_user_id":109740077,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"53407951","profile_image_url":"http://a1.twimg.com/profile_images/397960795/airman_normal.jpg","created_at":"Thu, 27 Jan 2011 12:57:32 +0000","from_user":"Airman2009","id_str":"30610355541508096","metadata":{"result_type":"recent"},"to_user_id":null,"text":". @04mmy22 @qsk1 \u98a8\u3068\u96f2\u30fb\u30fb\u30fb\u98db\u884c\u6a5f\u306e\u5927\u5c0f\u554f\u308f\u305a\u3001\u3053\u308c\u3070\u304b\u308a\u306f\u3069\u3046\u3057\u3088\u3046\u3082\u7121\u3044\u3067\u3059\u3088\u306d\u3002 \u6700\u8fd1\u306e\u5357\u6771\u4eac\u306e\u5929\u6c17\u306f\u5909\u3067\u3059\u306d\u3002\u3002\u3002","id":30610355541508096,"from_user_id":53407951,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sourceforge.jp/projects/tween/wiki/FrontPage&quot; rel=&quot;nofollow&quot;&gt;Tween&lt;/a&gt;"},{"from_user_id_str":"111826019","profile_image_url":"http://a1.twimg.com/profile_images/1121742732/DVC00052_normal.jpg","created_at":"Thu, 27 Jan 2011 12:51:12 +0000","from_user":"nijiks","id_str":"30608762859421696","metadata":{"result_type":"recent"},"to_user_id":100014282,"text":"@sanaeru  \u79c1\u3053\u3093\u306a\u5929\u6c17\u306e\u4e2d\uff64\u4e8c\u6cca\u4e09\u65e5\u3067\u660e\u65e5\u304b\u3089\u6771\u4eac\u884c\u304f\u3093\u3067\u3059\u3051\u3069\u2026\uff61\u65e5\u66dc\u65e5\u98db\u884c\u6a5f\u98db\u3076\u304b\u3057\u3089\u2026\uff1f","id":30608762859421696,"from_user_id":111826019,"to_user":"sanaeru","geo":null,"iso_language_code":"ja","to_user_id_str":"100014282","source":"&lt;a href=&quot;http://z.twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b/twipple&lt;/a&gt;"},{"from_user_id_str":"164951488","profile_image_url":"http://a3.twimg.com/profile_images/799082230/twitter_normal.jpg","created_at":"Thu, 27 Jan 2011 12:47:49 +0000","from_user":"minorif_jp","id_str":"30607912309096448","metadata":{"result_type":"recent"},"to_user_id":105078670,"text":"@ecco_HIRADO \u5e73\u6238\u725b\u3063\u3066\u5143\u306f\u30aa\u30e9\u30f3\u30c0\u304b\u3089\u304d\u305f\u725b\u306a\u3093\u3060\u306d\u3002\u304a\u3044\u3057\u305d\u3046\u2026\u3002\u5e73\u6238\u306f\u3088\u304b\u6240\u305f\u3043\u3002\u3042\u305f\u3044\u3052\u3047\u3093\u5b9f\u5bb6\u3093\u65b9\u306f\u30c0\u30d6\u30eb\u706b\u5c71\u3084\u9ce5\u30a4\u30f3\u30d5\u30eb\u3067\u5927\u5909\u3084\u3063\u3069\u3002\u6771\u4eac\u3093\u826f\u304b\u3068\u3053\u306f\u5929\u6c17\u306e\u5fc3\u914d\u305b\u305a\u66ae\u3089\u305b\u308b\u3068\u3053\u3058\u3083\u3063\u3069\u3093\u3002","id":30607912309096448,"from_user_id":164951488,"to_user":"ecco_HIRADO","geo":null,"iso_language_code":"ja","to_user_id_str":"105078670","source":"&lt;a href=&quot;http://z.twipple.jp/&quot; rel=&quot;nofollow&quot;&gt;\u3064\u3044\u3063\u3077\u308b/twipple&lt;/a&gt;"},{"from_user_id_str":"10456803","profile_image_url":"http://a1.twimg.com/profile_images/145280215/vot_icon_normal.png","created_at":"Thu, 27 Jan 2011 12:43:37 +0000","from_user":"vot_","id_str":"30606853377363968","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3086\u3063\u304f\u308a\u5929\u6c17\u4e88\u5831\u3067\u3059\u3002\u6771\u4eac\u90fd,\u5927\u5cf6\u5730\u65b9\u300228\u65e5\uff08\u91d1\u66dc\u65e5\u306e\u5929\u6c17\u306f\u6674\u308c\u306e\u3061\u66c7\u308a\u3001\u6700\u9ad8\u6c17\u6e29\u306f7\u5ea6 \u6700\u4f4e\u6c17\u6e29\u306f1\u5ea6\u3067\u3057\u3087\u3046\u3002","id":30606853377363968,"from_user_id":10456803,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://voiceoftwitter.com&quot; rel=&quot;nofollow&quot;&gt;\uff56\uff4f\uff49\uff43\uff45 \uff4f\uff46 \uff54\uff57\uff49\uff54\uff54\uff45\uff52&lt;/a&gt;"},{"from_user_id_str":"23900716","profile_image_url":"http://a3.twimg.com/profile_images/1092646332/twitter_icon_normal.png","created_at":"Thu, 27 Jan 2011 12:38:00 +0000","from_user":"keiyama","id_str":"30605442639990784","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3010\u7f8e\u4eba\u5929\u6c17/\u6771\u4eac\u3011\u7f8e\u4eba\u5929\u6c17\u30ad\u30e3\u30b9\u30bf\u30fc\u306e&quot;\u30c8\u30e2\u30b3\u3055\u3093&quot;\u306b\u3088\u308b\u3068\u300c1/27(\u6728)\u306f\u304f\u3082\u308a\u306e\u3061\u6674\u3067\u3001\u964d\u6c34\u78ba\u738710%\u3001\u6700\u9ad8\u6c17\u6e29\u306f9\u2103\u3067\u6700\u4f4e\u6c17\u6e29\u306f2\u2103\u3067\u3059\u300d\u7f8e\u4eba\u5929\u6c17\u21d2http://bit.ly/djB8th http://twitpic.com/3tuekm #bt_tenki","id":30605442639990784,"from_user_id":23900716,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://bijintenki.jp&quot; rel=&quot;nofollow&quot;&gt;bijintenki.jp&lt;/a&gt;"},{"from_user_id_str":"32018516","profile_image_url":"http://a0.twimg.com/profile_images/1089472069/237_normal.jpg","created_at":"Thu, 27 Jan 2011 12:36:28 +0000","from_user":"DigJandG","id_str":"30605057460281344","metadata":{"result_type":"recent"},"to_user_id":196050661,"text":"@kosumoworld55 \u5929\u6c17\u4e88\u5831\u3092\u898b\u3066\u3044\u3064\u3082\u601d\u3046\u3093\u3060\u3002\u4f55\u3067\u6a2a\u6d5c\u3042\u305f\u308a\u306f\u3044\u3064\u3082\u597d\u3044\u5929\u6c17\u306a\u3093\u3060\u3002\u6771\u4eac\u3082\u3002\u3061\u306a\u307f\u306b\u516c\u9b5a\u306f\u3042\u3093\u307e\u308a\u597d\u304d\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u306a\u3093\u304b\u81ed\u304f\u3063\u3066\u3002\u3067\u3082\u3001\u7435\u7436\u6e56\u3067\u516c\u9b5a\u3063\u3066\u3042\u307e\u308a\u805e\u304b\u306a\u3044\u69d8\u306a\u30fb\u30fb\u30fb\u3002\u4ffa\u304c\u91e3\u308a\u3092\u3057\u306a\u3044\u304b\u3089\u304b\u306a\uff1f","id":30605057460281344,"from_user_id":32018516,"to_user":"kosumoworld55","geo":null,"iso_language_code":"ja","to_user_id_str":"196050661","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"90935348","profile_image_url":"http://a1.twimg.com/sticky/default_profile_images/default_profile_0_normal.png","created_at":"Thu, 27 Jan 2011 12:34:34 +0000","from_user":"sorakeiko","id_str":"30604575937396737","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u95a2\u6771\u5730\u65b9\u306e\u660e\u65e5\u306e\u5929\u6c17\u2015\u7d9a\u304d\u3002\u660e\u65e5\u671d\u6700\u4f4e\u6c17\u6e29\u30fb\u8ed2\u4e26\u307f\u6c37\u70b9\u4e0b\u30fb\u5b87\u90fd\u5bae\u3001\u6c34\u6238\u30de\u30a4\u30ca\u30b95\u5ea6\u30fb\u6771\u4eac\u3001\u6a2a\u6d5c1\u5ea6\u3002\u6700\u9ad8\u6c17\u6e29\u30fb\u4eca\u65e5\u3088\u308a3\u5ea6\u524d\u5f8c\u4f4e\u304f5\uff5e8\u5ea6\u30fb\u6771\u4eac\u3001\u5343\u84498\u5ea6\u3002\u5411\u3053\u3046\u4e00\u9031\u9593\u30fb\u4e7e\u71e5\u3057\u305f\u6674\u308c\u7d9a\u304f\u30fb\uff08\u571f\uff09\u4f0a\u8c46\u8af8\u5cf6\u306b\u51b7\u305f\u3044\u96e8\u3084\u96ea\u304c\u898b\u3089\u308c\u305d\u3046\u3060\u304c\u3001\u95a2\u6771\u306e\u4e7e\u3044\u305f\u72b6\u614b\u7d9a\u304f\u3002","id":30604575937396737,"from_user_id":90935348,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"6113557","profile_image_url":"http://a3.twimg.com/profile_images/1227080026/profile_red_herencia_normal.png","created_at":"Thu, 27 Jan 2011 12:33:57 +0000","from_user":"fmoto7","id_str":"30604423327653888","metadata":{"result_type":"recent"},"to_user_id":null,"text":"&quot;\u6771\u4eac\u6c34\u904b\u7528\u30bb\u30f3\u30bf\u30fc\u306f\u3001\u524d\u534a\u6226\u304c\u7d42\u308f\u3063\u305f\u3068\u3053\u308d\u3067\u4e00\u6c17\u306b\u6c34\u5727\u9ad8\u3081\u3001\u5f8c\u534a\u6226\u59cb\u307e\u308b\u3068\u6c34\u5727\u4e0b\u3052\u3001\u7d42\u308f\u308b\u3068\u307e\u305f\u3059\u3050\u4e0a\u3052\u308b\u3002\u30c6\u30ec\u30d3\u306e\u8996\u8074\u3001\u305d\u306e\u65e5\u306e\u5929\u6c17\u306a\u3069\u30e9\u30a4...&quot; http://tumblr.com/xjy1cwiwrm","id":30604423327653888,"from_user_id":6113557,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tumblr.com/&quot; rel=&quot;nofollow&quot;&gt;Tumblr&lt;/a&gt;"},{"from_user_id_str":"118092912","profile_image_url":"http://a3.twimg.com/profile_images/1225330653/____normal.PNG","created_at":"Thu, 27 Jan 2011 12:29:13 +0000","from_user":"saechuchun","id_str":"30603231042207744","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u3067\u3082\u5730\u9707\u306e\u8a71\u984c\u306e\u3068\u304d\u306e\u300c\u3082\u3057\u6771\u4eac\u3067\u76f4\u4e0b\u578b\u5730\u9707\u304c\u8d77\u304d\u305f\u3089\u300d\u3068\u304b\u5929\u6c17\u4e88\u5831\u306e\u3068\u304d\u306f\u897f\u3067\u96e8\u3060\u308d\u3046\u3068\u300c\u6771\u4eac\u3067\u306f\u301c\u65e5\u9593\u4e7e\u71e5\u3057\u3066\u307e\u3059\u306d\u30fc\u300d\u3068\u304b\u305d\u3046\u3044\u3046\u30ad\u30fc\u5c40\u306e\u95a2\u6771\u4e2d\u5fc3\u4e3b\u7fa9\u306f\u597d\u304d\u3067\u306f\u306a\u3044","id":30603231042207744,"from_user_id":118092912,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twtr.jp&quot; rel=&quot;nofollow&quot;&gt;Keitai Web&lt;/a&gt;"}],"max_id":30724239224995840,"since_id":28179956995457024,"refresh_url":"?since_id=30724239224995840&q=%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97","next_page":"?page=2&max_id=30724239224995840&rpp=50&lang=ja&q=%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97","results_per_page":50,"page":1,"completed_in":0.170202,"warning":"adjusted since_id to 28179956995457024 (), requested since_id was older than allowed -- since_id removed for pagination.","since_id_str":"28179956995457024","max_id_str":"30724239224995840","query":"%E6%9D%B1%E4%BA%AC%E3%80%80%E5%A4%A9%E6%B0%97"}
diff --git a/benchmarks/json-data/numbers.json b/benchmarks/json-data/numbers.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/numbers.json
@@ -0,0 +1,1 @@
+[1.15, 1.3224999999999998, 1.5208749999999998, 1.7490062499999994, 2.0113571874999994, 2.313060765624999, 2.6600198804687487, 3.0590228625390607, 3.5178762919199196, 4.045557735707907, 4.652391396064092, 5.350250105473706, 6.152787621294761, 7.075705764488975, 8.137061629162321, 9.357620873536668, 10.761264004567169, 12.375453605252241, 14.231771646040077, 16.36653739294609, 18.821518001888, 21.644745702171196, 24.891457557496874, 28.625176191121405, 32.918952619789614, 37.856795512758055, 43.535314839671756, 50.06561206562252, 57.57545387546589, 66.21177195678577, 76.14353775030362, 87.56506841284916, 100.69982867477653, 115.804802975993, 133.17552342239193, 153.15185193575073, 176.1246297261133, 202.5433241850303, 232.9248228127848, 267.86354623470254, 308.04307816990786, 354.24953989539404, 407.3869708797031, 468.49501651165855, 538.7692689884072, 619.5846593366683, 712.5223582371685, 819.4007119727437, 942.3108187686552, 1083.6574415839534, 1246.2060578215462, 1433.136966494778, 1648.1075114689947, 1895.323638189344, 2179.622183917745, 2506.565511505407, 2882.5503382312177, 3314.9328889659, 3812.172822310785, 4383.998745657402, 5041.598557506012, 5797.838341131914, 6667.5140923017, 7667.641206146955, 8817.787387068996, 10140.455495129345, 11661.523819398746, 13410.752392308557, 15422.365251154839, 17735.720038828065, 20396.078044652273, 23455.489751350113, 26973.813214052625, 31019.885196160518, 35672.867975584595, 41023.79817192228, 47177.36789771062, 54253.97308236721, 62392.06904472228, 71750.87940143062, 82513.5113116452, 94890.53800839197, 109124.11870965076, 125492.73651609836, 144316.6469935131, 165964.14404254008, 190858.76564892105, 219487.5804962592, 252410.71757069806, 290272.32520630275, 333813.17398724816, 383885.1500853353, 441467.9225981356, 507688.1109878559, 583841.3276360342, 671417.5267814393, 772130.1557986551, 887949.6791684533, 1021142.1310437213, 1174313.4507002793, 1350460.4683053212, 1553029.5385511192, 1785983.969333787, 2053881.564733855, 2361963.7994439327, 2716258.369360523, 3123697.124764601, 3592251.6934792907, 4131089.447501184, 4750752.864626361, 5463365.794320315, 6282870.663468362, 7225301.262988616, 8309096.452436907, 9555460.920302443, 10988780.058347808, 12637097.067099977, 14532661.627164973, 16712560.871239718, 19219445.001925673, 22102361.752214525, 25417716.0150467, 29230373.417303704, 33614929.42989926, 38657168.84438414, 44455744.17104176, 51124105.79669802, 58792721.66620272, 67611629.91613312, 77753374.40355308, 89416380.56408603, 102828837.64869894, 118253163.29600377, 135991137.79040432, 156389808.45896497, 179848279.7278097, 206825521.68698114, 237849349.94002828, 273526752.4310325, 314555765.2956874, 361739130.09004045, 415999999.60354644, 478399999.5440784, 550159999.4756901, 632683999.3970436, 727586599.3066001, 836724589.20259, 962233277.5829784, 1106568269.2204251, 1272553509.6034887, 1463436536.044012, 1682952016.4506137, 1935394818.9182055, 2225704041.755936, 2559559648.019326, 2943493595.222225, 3385017634.5055585, 3892770279.681392, 4476685821.6336, 5148188694.87864, 5920416999.1104355, 6808479548.977001, 7829751481.32355, 9004214203.522081, 10354846334.050394, 11908073284.157951, 13694284276.781643, 15748426918.29889, 18110690956.04372, 20827294599.450275, 23951388789.367817, 27544097107.772987, 31675711673.938934, 36427068425.02977, 41891128688.78423, 48174797992.10186, 55401017690.91714, 63711170344.5547, 73267845896.2379, 84258022780.67358, 96896726197.77461, 111431235127.4408, 128145920396.5569, 147367808456.04044, 169472979724.44647, 194893926683.11343, 224128015685.58044, 257747218038.41748, 296409300744.1801, 340870695855.80707, 392001300234.1781, 450801495269.3048, 518421719559.70044, 596184977493.6555, 685612724117.7037, 788454632735.3593, 906722827645.6631, 1042731251792.5125, 1199140939561.3892, 1379012080495.5974, 1585863892569.937, 1823743476455.4275, 2097304997923.7415, 2411900747612.3022, 2773685859754.1475, 3189738738717.2695, 3668199549524.8594, 4218429481953.5884, 4851193904246.626, 5578872989883.619, 6415703938366.162, 7378059529121.086, 8484768458489.248, 9757483727262.635, 11221106286352.03, 12904272229304.832, 14839913063700.555, 17065900023255.637, 19625785026743.98, 22569652780755.58, 25955100697868.91, 29848365802549.246, 34325620672931.63, 39474463773871.375, 45395633339952.07, 52204978340944.88, 60035725092086.61, 69041083855899.59, 79397246434284.53, 91306833399427.2, 105002858409341.27, 120753287170742.45, 138866280246353.81, 159696222283306.88, 183650655625802.88, 211198253969673.3, 242877992065124.28, 279309690874892.9, 321206144506126.8, 369387066182045.8, 424795126109352.6, 488514395025755.5, 561791554279618.75, 646060287421561.5, 742969330534795.8, 854414730115015.0, 982576939632267.1, 1129963480577107.2, 1299458002663673.2, 1494376703063224.0, 1718533208522707.5, 1976313189801113.5, 2272760168271280.5, 2613674193511972.0, 3005725322538767.5, 3456584120919582.5, 3975071739057519.5, 4571332499916147.0, 5257032374903569.0, 6045587231139104.0, 6952425315809969.0, 7995289113181464.0, 9194582480158682.0, 1.0573769852182484e+16, 1.2159835330009856e+16, 1.3983810629511332e+16, 1.6081382223938032e+16, 1.8493589557528736e+16, 2.1267627991158044e+16, 2.4457772189831748e+16, 2.8126438018306508e+16, 3.234540372105248e+16, 3.719721427921035e+16, 4.27767964210919e+16, 4.919331588425568e+16, 5.657231326689403e+16, 6.505816025692813e+16, 7.481688429546734e+16, 8.603941693978744e+16, 9.894532948075555e+16, 1.1378712890286886e+17, 1.3085519823829918e+17, 1.5048347797404406e+17, 1.7305599967015066e+17, 1.9901439962067325e+17, 2.288665595637742e+17, 2.6319654349834032e+17, 3.026760250230913e+17, 3.48077428776555e+17, 4.002890430930382e+17, 4.603323995569939e+17, 5.29382259490543e+17, 6.087895984141244e+17, 7.00108038176243e+17, 8.051242439026793e+17, 9.258928804880812e+17, 1.0647768125612933e+18, 1.224493334445487e+18, 1.4081673346123103e+18, 1.6193924348041567e+18, 1.8623013000247798e+18, 2.1416464950284966e+18, 2.462893469282771e+18, 2.8323274896751867e+18, 3.257176613126464e+18, 3.7457531050954337e+18, 4.3076160708597484e+18, 4.95375848148871e+18, 5.696822253712016e+18, 6.551345591768818e+18, 7.53404743053414e+18, 8.66415454511426e+18, 9.963777726881399e+18, 1.1458344385913608e+19, 1.3177096043800648e+19, 1.5153660450370744e+19, 1.7426709517926355e+19, 2.0040715945615307e+19, 2.30468233374576e+19, 2.650384683807624e+19, 3.047942386378767e+19, 3.505133744335582e+19, 4.030903805985919e+19, 4.635539376883806e+19, 5.330870283416377e+19, 6.130500825928833e+19, 7.0500759498181575e+19, 8.10758734229088e+19, 9.323725443634512e+19, 1.0722284260179688e+20, 1.233062689920664e+20, 1.4180220934087634e+20, 1.6307254074200778e+20, 1.8753342185330894e+20, 2.1566343513130526e+20, 2.4801295040100103e+20, 2.8521489296115116e+20, 3.2799712690532385e+20, 3.7719669594112236e+20, 4.337762003322907e+20, 4.988426303821342e+20, 5.7366902493945437e+20, 6.597193786803724e+20, 7.586772854824282e+20, 8.724788783047925e+20, 1.0033507100505113e+21, 1.1538533165580878e+21, 1.326931314041801e+21, 1.5259710111480708e+21, 1.7548666628202813e+21, 2.0180966622433234e+21, 2.3208111615798217e+21, 2.668932835816795e+21, 3.0692727611893135e+21, 3.529663675367711e+21, 4.059113226672867e+21, 4.667980210673796e+21, 5.368177242274866e+21, 6.173403828616095e+21, 7.099414402908508e+21, 8.164326563344784e+21, 9.388975547846502e+21, 1.0797321880023475e+22, 1.2416920162026996e+22, 1.4279458186331043e+22, 1.64213769142807e+22, 1.8884583451422802e+22, 2.171727096913622e+22, 2.497486161450665e+22, 2.872109085668265e+22, 3.3029254485185042e+22, 3.798364265796279e+22, 4.368118905665721e+22, 5.0233367415155795e+22, 5.7768372527429155e+22, 6.643362840654352e+22, 7.639867266752504e+22, 8.78584735676538e+22, 1.0103724460280185e+23, 1.1619283129322213e+23, 1.3362175598720545e+23, 1.5366501938528623e+23, 1.7671477229307915e+23, 2.0322198813704103e+23, 2.3370528635759717e+23, 2.687610793112367e+23, 3.090752412079222e+23, 3.554365273891105e+23, 4.0875200649747705e+23, 4.700648074720986e+23, 5.405745285929133e+23, 6.216607078818502e+23, 7.149098140641278e+23, 8.221462861737468e+23, 9.454682290998088e+23, 1.0872884634647801e+24, 1.250381732984497e+24, 1.4379389929321714e+24, 1.653629841871997e+24, 1.9016743181527962e+24, 2.1869254658757156e+24, 2.5149642857570727e+24, 2.8922089286206334e+24, 3.326040267913728e+24, 3.824946308100787e+24, 4.3986882543159046e+24, 5.05849149246329e+24, 5.817265216332783e+24, 6.6898549987827e+24, 7.693333248600105e+24, 8.84733323589012e+24, 1.0174433221273637e+25, 1.1700598204464681e+25, 1.3455687935134384e+25, 1.547404112540454e+25, 1.779514729421522e+25, 2.04644193883475e+25, 2.353408229659962e+25, 2.7064194641089563e+25, 3.1123823837253e+25, 3.5792397412840944e+25, 4.116125702476708e+25, 4.733544557848214e+25, 5.443576241525446e+25, 6.260112677754262e+25, 7.199129579417401e+25, 8.27899901633001e+25, 9.52084886877951e+25, 1.0948976199096437e+26, 1.25913226289609e+26, 1.4480021023305035e+26, 1.665202417680079e+26, 1.9149827803320907e+26, 2.202230197381904e+26, 2.5325647269891895e+26, 2.9124494360375676e+26, 3.349316851443203e+26, 3.8517143791596826e+26, 4.429471536033635e+26, 5.09389226643868e+26, 5.857976106404481e+26, 6.736672522365153e+26, 7.747173400719924e+26, 8.909249410827912e+26, 1.0245636822452099e+27, 1.1782482345819913e+27, 1.35498546976929e+27, 1.5582332902346833e+27, 1.7919682837698857e+27, 2.0607635263353683e+27, 2.3698780552856732e+27, 2.725359763578524e+27, 3.1341637281153025e+27, 3.6042882873325974e+27, 4.1449315304324867e+27, 4.7666712599973594e+27, 5.481671948996963e+27, 6.303922741346507e+27, 7.249511152548482e+27, 8.336937825430755e+27, 9.587478499245366e+27, 1.102560027413217e+28, 1.2679440315251995e+28, 1.4581356362539794e+28, 1.6768559816920761e+28, 1.9283843789458875e+28, 2.2176420357877703e+28, 2.5502883411559357e+28, 2.932831592329326e+28, 3.3727563311787245e+28, 3.8786697808555327e+28, 4.460470247983863e+28, 5.129540785181441e+28, 5.8989719029586575e+28, 6.783817688402455e+28, 7.801390341662823e+28, 8.971598892912247e+28, 1.0317338726849081e+29, 1.1864939535876443e+29, 1.3644680466257909e+29, 1.5691382536196593e+29, 1.8045089916626083e+29, 2.0751853404119993e+29, 2.3864631414737988e+29, 2.7444326126948684e+29, 3.1560975045990984e+29, 3.629512130288963e+29, 4.173938949832307e+29, 4.800029792307153e+29, 5.520034261153225e+29, 6.348039400326208e+29, 7.300245310375139e+29, 8.39528210693141e+29, 9.65457442297112e+29, 1.1102760586416787e+30, 1.2768174674379305e+30, 1.46834008755362e+30, 1.6885911006866628e+30, 1.941879765789662e+30, 2.2331617306581113e+30, 2.568135990256828e+30, 2.9533563887953516e+30, 3.396359847114654e+30, 3.905813824181852e+30, 4.491685897809129e+30, 5.165438782480498e+30, 5.940254599852573e+30, 6.831292789830458e+30, 7.855986708305026e+30, 9.034384714550779e+30, 1.0389542421733396e+31, 1.1947973784993405e+31, 1.3740169852742412e+31, 1.5801195330653773e+31, 1.817137463025184e+31, 2.0897080824789613e+31, 2.4031642948508052e+31, 2.7636389390784257e+31, 3.1781847799401893e+31, 3.6549124969312175e+31, 4.2031493714709e+31, 4.833621777191535e+31, 5.558665043770264e+31, 6.392464800335803e+31, 7.3513345203861735e+31, 8.454034698444098e+31, 9.722139903210713e+31, 1.1180460888692319e+32, 1.2857530021996165e+32, 1.478615952529559e+32, 1.7004083454089925e+32, 1.9554695972203414e+32, 2.2487900368033926e+32, 2.586108542323901e+32, 2.974024823672486e+32, 3.420128547223359e+32, 3.933147829306862e+32, 4.523120003702891e+32, 5.2015880042583246e+32, 5.981826204897073e+32, 6.879100135631634e+32, 7.910965155976377e+32, 9.097609929372833e+32, 1.0462251418778757e+33, 1.2031589131595571e+33, 1.3836327501334904e+33, 1.591177662653514e+33, 1.8298543120515409e+33, 2.104332458859272e+33, 2.4199823276881623e+33, 2.7829796768413863e+33, 3.200426628367594e+33, 3.6804906226227334e+33, 4.232564216016143e+33, 4.867448848418564e+33, 5.597566175681348e+33, 6.437201102033549e+33, 7.402781267338582e+33, 8.513198457439368e+33, 9.790178226055273e+33, 1.1258704959963564e+34, 1.2947510703958096e+34, 1.488963730955181e+34, 1.712308290598458e+34, 1.9691545341882266e+34, 2.2645277143164603e+34, 2.604206871463929e+34, 2.994837902183518e+34, 3.4440635875110457e+34, 3.960673125637702e+34, 4.554774094483357e+34, 5.237990208655861e+34, 6.023688739954239e+34, 6.927242050947375e+34, 7.96632835858948e+34, 9.161277612377902e+34, 1.0535469254234585e+35, 1.2115789642369772e+35, 1.3933158088725236e+35, 1.6023131802034022e+35, 1.8426601572339122e+35, 2.119059180818999e+35, 2.4369180579418488e+35, 2.8024557666331258e+35, 3.2228241316280944e+35, 3.706247751372308e+35, 4.262184914078154e+35, 4.901512651189877e+35, 5.636739548868358e+35, 6.482250481198611e+35, 7.454588053378403e+35, 8.572776261385162e+35, 9.858692700592935e+35, 1.1337496605681875e+36, 1.3038121096534156e+36, 1.499383926101428e+36, 1.7242915150166418e+36, 1.982935242269138e+36, 2.2803755286095084e+36]
diff --git a/benchmarks/json-data/twitter1.json b/benchmarks/json-data/twitter1.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/twitter1.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"80430860","profile_image_url":"http://a2.twimg.com/profile_images/536455139/icon32_normal.png","created_at":"Wed, 26 Jan 2011 07:07:02 +0000","from_user":"kazu_yamamoto","id_str":"30159761706061824","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell Server Pages \u3063\u3066\u3001\u307e\u3060\u7d9a\u3044\u3066\u3044\u305f\u306e\u304b\uff01","id":30159761706061824,"from_user_id":80430860,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"}],"max_id":30159761706061824,"since_id":0,"refresh_url":"?since_id=30159761706061824&q=haskell","next_page":"?page=2&max_id=30159761706061824&rpp=1&q=haskell","results_per_page":1,"page":1,"completed_in":0.012606,"since_id_str":"0","max_id_str":"30159761706061824","query":"haskell"}
diff --git a/benchmarks/json-data/twitter10.json b/benchmarks/json-data/twitter10.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/twitter10.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"207858021","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 04:30:38 +0000","from_user":"pboudarga","id_str":"30120402839666689","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Rolla Sushi Grill (27737 Bouquet Canyon Road, #106, Btw Haskell Canyon and Rosedell Drive, Saugus) http://4sq.com/gqqdhs","id":30120402839666689,"from_user_id":207858021,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"69988683","profile_image_url":"http://a0.twimg.com/profile_images/1211955817/avatar_7888_normal.gif","created_at":"Wed, 26 Jan 2011 04:25:23 +0000","from_user":"YNK33","id_str":"30119083059978240","metadata":{"result_type":"recent"},"to_user_id":null,"text":"hsndfile 0.5.0: Free and open source Haskell bindings for libsndfile http://bit.ly/gHaBWG Mac Os","id":30119083059978240,"from_user_id":69988683,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"81492","profile_image_url":"http://a1.twimg.com/profile_images/423894208/Picture_7_normal.jpg","created_at":"Wed, 26 Jan 2011 04:24:28 +0000","from_user":"satzz","id_str":"30118851488251904","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Emacs\u306e\u30e2\u30fc\u30c9\u8868\u793a\u304c\u4eca(Ruby Controller Outputz RoR Flymake REl hs)\u3068\u306a\u3063\u3066\u3066\u3088\u304f\u308f\u304b\u3089\u306a\u3044\u3093\u3060\u3051\u3069\u6700\u5f8c\u306eREl\u3068\u304bhs\u3063\u3066\u4f55\u3060\u308d\u3046\u2026haskell\u3068\u304b2\u5e74\u4ee5\u4e0a\u66f8\u3044\u3066\u306a\u3044\u3051\u3069\u2026","id":30118851488251904,"from_user_id":81492,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"9518356","profile_image_url":"http://a2.twimg.com/profile_images/119165723/ocaml-icon_normal.png","created_at":"Wed, 26 Jan 2011 04:19:19 +0000","from_user":"planet_ocaml","id_str":"30117557788741632","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I so miss #haskell type classes in #ocaml - i want to do something like refinement. Also why does ocaml not have... http://bit.ly/geYRwt","id":30117557788741632,"from_user_id":9518356,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"218059","profile_image_url":"http://a1.twimg.com/profile_images/1053837723/twitter-icon9_normal.jpg","created_at":"Wed, 26 Jan 2011 04:16:32 +0000","from_user":"aprikip","id_str":"30116854940835840","metadata":{"result_type":"recent"},"to_user_id":null,"text":"yatex-mode\u3084haskell-mode\u306e\u3053\u3068\u3067\u3059\u306d\u3001\u308f\u304b\u308a\u307e\u3059\u3002","id":30116854940835840,"from_user_id":218059,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sites.google.com/site/yorufukurou/&quot; rel=&quot;nofollow&quot;&gt;YoruFukurou&lt;/a&gt;"},{"from_user_id_str":"216363","profile_image_url":"http://a1.twimg.com/profile_images/72454310/Tim-Avatar_normal.png","created_at":"Wed, 26 Jan 2011 04:15:30 +0000","from_user":"dysinger","id_str":"30116594684264448","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell in Hawaii tonight for me... #fun","id":30116594684264448,"from_user_id":216363,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.nambu.com/&quot; rel=&quot;nofollow&quot;&gt;Nambu&lt;/a&gt;"},{"from_user_id_str":"1774820","profile_image_url":"http://a2.twimg.com/profile_images/61169291/dan_desert_thumb_normal.jpg","created_at":"Wed, 26 Jan 2011 04:13:36 +0000","from_user":"DanMil","id_str":"30116117682851840","metadata":{"result_type":"recent"},"to_user_id":1594784,"text":"@ojrac @chewedwire @tomheon Haskell isn't a language, it's a belief system.  A seductive one...","id":30116117682851840,"from_user_id":1774820,"to_user":"ojrac","geo":null,"iso_language_code":"en","to_user_id_str":"1594784","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"659256","profile_image_url":"http://a0.twimg.com/profile_images/746976711/angular-final_normal.jpg","created_at":"Wed, 26 Jan 2011 04:11:06 +0000","from_user":"djspiewak","id_str":"30115488931520512","metadata":{"result_type":"recent"},"to_user_id":null,"text":"One of the very nice things about Haskell as opposed to SML is the reduced proliferation of identifiers (e.g. andb, orb, etc). #typeclasses","id":30115488931520512,"from_user_id":659256,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 04:06:12 +0000","from_user":"listwarenet","id_str":"30114255890026496","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-cafe/84752-re-haskell-cafe-gpl-license-of-h-matrix-and-prelude-numeric.html Re: Haskell-c","id":30114255890026496,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"1594784","profile_image_url":"http://a2.twimg.com/profile_images/378515773/square-profile_normal.jpg","created_at":"Wed, 26 Jan 2011 04:01:29 +0000","from_user":"ojrac","id_str":"30113067333324800","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tomheon: @ojrac @chewedwire Don't worry, learning Haskell will not give you any clear idea what monad means.","id":30113067333324800,"from_user_id":1594784,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"}],"max_id":30120402839666689,"since_id":0,"refresh_url":"?since_id=30120402839666689&q=haskell","next_page":"?page=2&max_id=30120402839666689&rpp=10&q=haskell","results_per_page":10,"page":1,"completed_in":0.012714,"since_id_str":"0","max_id_str":"30120402839666689","query":"haskell"}
diff --git a/benchmarks/json-data/twitter100.json b/benchmarks/json-data/twitter100.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/twitter100.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"3646730","profile_image_url":"http://a3.twimg.com/profile_images/404973767/avatar_normal.jpg","created_at":"Wed, 26 Jan 2011 04:35:07 +0000","from_user":"nicolaslara","id_str":"30121530767708160","metadata":{"result_type":"recent"},"to_user_id":18616016,"text":"@josej30 Python y Clojure. Obviamente son diferentes, y cada uno tiene sus ventajas y desventajas. De Haskell faltar\u00eda pattern matching","id":30121530767708160,"from_user_id":3646730,"to_user":"josej30","geo":null,"iso_language_code":"es","to_user_id_str":"18616016","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"207858021","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 04:30:38 +0000","from_user":"pboudarga","id_str":"30120402839666689","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Rolla Sushi Grill (27737 Bouquet Canyon Road, #106, Btw Haskell Canyon and Rosedell Drive, Saugus) http://4sq.com/gqqdhs","id":30120402839666689,"from_user_id":207858021,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"69988683","profile_image_url":"http://a0.twimg.com/profile_images/1211955817/avatar_7888_normal.gif","created_at":"Wed, 26 Jan 2011 04:25:23 +0000","from_user":"YNK33","id_str":"30119083059978240","metadata":{"result_type":"recent"},"to_user_id":null,"text":"hsndfile 0.5.0: Free and open source Haskell bindings for libsndfile http://bit.ly/gHaBWG Mac Os","id":30119083059978240,"from_user_id":69988683,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"81492","profile_image_url":"http://a1.twimg.com/profile_images/423894208/Picture_7_normal.jpg","created_at":"Wed, 26 Jan 2011 04:24:28 +0000","from_user":"satzz","id_str":"30118851488251904","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Emacs\u306e\u30e2\u30fc\u30c9\u8868\u793a\u304c\u4eca(Ruby Controller Outputz RoR Flymake REl hs)\u3068\u306a\u3063\u3066\u3066\u3088\u304f\u308f\u304b\u3089\u306a\u3044\u3093\u3060\u3051\u3069\u6700\u5f8c\u306eREl\u3068\u304bhs\u3063\u3066\u4f55\u3060\u308d\u3046\u2026haskell\u3068\u304b2\u5e74\u4ee5\u4e0a\u66f8\u3044\u3066\u306a\u3044\u3051\u3069\u2026","id":30118851488251904,"from_user_id":81492,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"9518356","profile_image_url":"http://a2.twimg.com/profile_images/119165723/ocaml-icon_normal.png","created_at":"Wed, 26 Jan 2011 04:19:19 +0000","from_user":"planet_ocaml","id_str":"30117557788741632","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I so miss #haskell type classes in #ocaml - i want to do something like refinement. Also why does ocaml not have... http://bit.ly/geYRwt","id":30117557788741632,"from_user_id":9518356,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"218059","profile_image_url":"http://a1.twimg.com/profile_images/1053837723/twitter-icon9_normal.jpg","created_at":"Wed, 26 Jan 2011 04:16:32 +0000","from_user":"aprikip","id_str":"30116854940835840","metadata":{"result_type":"recent"},"to_user_id":null,"text":"yatex-mode\u3084haskell-mode\u306e\u3053\u3068\u3067\u3059\u306d\u3001\u308f\u304b\u308a\u307e\u3059\u3002","id":30116854940835840,"from_user_id":218059,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sites.google.com/site/yorufukurou/&quot; rel=&quot;nofollow&quot;&gt;YoruFukurou&lt;/a&gt;"},{"from_user_id_str":"216363","profile_image_url":"http://a1.twimg.com/profile_images/72454310/Tim-Avatar_normal.png","created_at":"Wed, 26 Jan 2011 04:15:30 +0000","from_user":"dysinger","id_str":"30116594684264448","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell in Hawaii tonight for me... #fun","id":30116594684264448,"from_user_id":216363,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.nambu.com/&quot; rel=&quot;nofollow&quot;&gt;Nambu&lt;/a&gt;"},{"from_user_id_str":"1774820","profile_image_url":"http://a2.twimg.com/profile_images/61169291/dan_desert_thumb_normal.jpg","created_at":"Wed, 26 Jan 2011 04:13:36 +0000","from_user":"DanMil","id_str":"30116117682851840","metadata":{"result_type":"recent"},"to_user_id":1594784,"text":"@ojrac @chewedwire @tomheon Haskell isn't a language, it's a belief system.  A seductive one...","id":30116117682851840,"from_user_id":1774820,"to_user":"ojrac","geo":null,"iso_language_code":"en","to_user_id_str":"1594784","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"659256","profile_image_url":"http://a0.twimg.com/profile_images/746976711/angular-final_normal.jpg","created_at":"Wed, 26 Jan 2011 04:11:06 +0000","from_user":"djspiewak","id_str":"30115488931520512","metadata":{"result_type":"recent"},"to_user_id":null,"text":"One of the very nice things about Haskell as opposed to SML is the reduced proliferation of identifiers (e.g. andb, orb, etc). #typeclasses","id":30115488931520512,"from_user_id":659256,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 04:06:12 +0000","from_user":"listwarenet","id_str":"30114255890026496","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-cafe/84752-re-haskell-cafe-gpl-license-of-h-matrix-and-prelude-numeric.html Re: Haskell-c","id":30114255890026496,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"1594784","profile_image_url":"http://a2.twimg.com/profile_images/378515773/square-profile_normal.jpg","created_at":"Wed, 26 Jan 2011 04:01:29 +0000","from_user":"ojrac","id_str":"30113067333324800","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tomheon: @ojrac @chewedwire Don't worry, learning Haskell will not give you any clear idea what monad means.","id":30113067333324800,"from_user_id":1594784,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"207589736","profile_image_url":"http://a3.twimg.com/profile_images/1225527428/headshot_1_normal.jpg","created_at":"Wed, 26 Jan 2011 04:00:13 +0000","from_user":"ashleevelazq101","id_str":"30112747555397632","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Federal investigation finds safety violations at The Acadia Hospital: By Meg Haskell, BDN Staff The investigatio... http://bit.ly/dONnpn","id":30112747555397632,"from_user_id":207589736,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Wed, 26 Jan 2011 03:58:00 +0000","from_user":"Hackage","id_str":"30112192346984448","metadata":{"result_type":"recent"},"to_user_id":null,"text":"streams 0.4, added by EdwardKmett: Various Haskell 2010 stream comonads http://bit.ly/idBkPe","id":30112192346984448,"from_user_id":17671137,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17489366","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 03:58:00 +0000","from_user":"aapnoot","id_str":"30112191881420800","metadata":{"result_type":"recent"},"to_user_id":null,"text":"streams 0.4, added by EdwardKmett: Various Haskell 2010 stream comonads http://bit.ly/idBkPe","id":30112191881420800,"from_user_id":17489366,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"8530482","profile_image_url":"http://a2.twimg.com/profile_images/137867266/n608671563_7396_normal.jpg","created_at":"Wed, 26 Jan 2011 03:50:12 +0000","from_user":"jeffmclamb","id_str":"30110229207187456","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Angel - daemon to run and monitor processes like daemontools or god, written in Haskell http://ff.im/-wNyLk","id":30110229207187456,"from_user_id":8530482,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://friendfeed.com&quot; rel=&quot;nofollow&quot;&gt;FriendFeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 03:46:01 +0000","from_user":"tomheon","id_str":"30109174645919744","metadata":{"result_type":"recent"},"to_user_id":1594784,"text":"@ojrac @chewedwire Don't worry, learning Haskell will not give you any clear idea what monad means.","id":30109174645919744,"from_user_id":177539201,"to_user":"ojrac","geo":null,"iso_language_code":"en","to_user_id_str":"1594784","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"1594784","profile_image_url":"http://a2.twimg.com/profile_images/378515773/square-profile_normal.jpg","created_at":"Wed, 26 Jan 2011 03:44:34 +0000","from_user":"ojrac","id_str":"30108808684503040","metadata":{"result_type":"recent"},"to_user_id":128028225,"text":"@chewedwire @tomheon Why are you making me curious about Haskell? I LIKE not knowing what monad means!!","id":30108808684503040,"from_user_id":1594784,"to_user":"chewedwire","geo":null,"iso_language_code":"en","to_user_id_str":"128028225","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"23750094","profile_image_url":"http://a0.twimg.com/profile_images/951373780/Moeinthecar_normal.jpg","created_at":"Wed, 26 Jan 2011 03:41:54 +0000","from_user":"shokalshab","id_str":"30108140443795456","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Magnitude Cheer @ Gymnastics Olympica USA (7735 Haskell Ave., btw Saticoy &amp; Strathern, Van Nuys) http://4sq.com/gmXfaL","id":30108140443795456,"from_user_id":23750094,"geo":null,"iso_language_code":"en","place":{"id":"4e4a2a2f86cb2946","type":"poi","full_name":"Gymnastics Olympica USA, Van Nuys"},"to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"8135112","profile_image_url":"http://a0.twimg.com/profile_images/1165240350/LIMITED_normal.jpg","created_at":"Wed, 26 Jan 2011 03:41:35 +0000","from_user":"Claricei","id_str":"30108059208515584","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @kristenmchugh22: @KeithOlbermann Ryan looks like Jughead w/o the hat. And sounds as mealy-mouthed as Eddie Haskell.","id":30108059208515584,"from_user_id":8135112,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:40:02 +0000","from_user":"chewedwire","id_str":"30107670367182848","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon Cool, I'll take a look. I feel like I should mention this: http://bit.ly/hVstDM","id":30107670367182848,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"8679778","profile_image_url":"http://a3.twimg.com/profile_images/1195318056/me_nyc_12_18_10_icon_normal.jpg","created_at":"Wed, 26 Jan 2011 03:38:42 +0000","from_user":"kristenmchugh22","id_str":"30107332381777920","metadata":{"result_type":"recent"},"to_user_id":756269,"text":"@KeithOlbermann Ryan looks like Jughead w/o the hat. And sounds as mealy-mouthed as Eddie Haskell.","id":30107332381777920,"from_user_id":8679778,"to_user":"KeithOlbermann","geo":null,"iso_language_code":"en","to_user_id_str":"756269","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"103316559","profile_image_url":"http://a1.twimg.com/profile_images/1179458751/bc3beab4-d59d-4e78-b13b-50747986cfa2_normal.png","created_at":"Wed, 26 Jan 2011 03:36:15 +0000","from_user":"cityslikr","id_str":"30106719153557504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"&quot;Social safety net into a hammock.&quot; So says Eddie Haskell with the GOP response. #SOTU","id":30106719153557504,"from_user_id":103316559,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://blackberry.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Twitter for BlackBerry\u00ae&lt;/a&gt;"},{"from_user_id_str":"169063143","profile_image_url":"http://a0.twimg.com/profile_images/1160506212/9697_1_normal.gif","created_at":"Wed, 26 Jan 2011 03:31:52 +0000","from_user":"wrkforce_safety","id_str":"30105614919143424","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Federal investigation finds safety violations at The Acadia Hospital: By Meg Haskell, BDN Staff The investigatio... http://bit.ly/gA60C1","id":30105614919143424,"from_user_id":169063143,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 03:29:40 +0000","from_user":"tomheon","id_str":"30105060960632832","metadata":{"result_type":"recent"},"to_user_id":128028225,"text":"@chewedwire Great book on Haskell: http://oreilly.com/catalog/9780596514983","id":30105060960632832,"from_user_id":177539201,"to_user":"chewedwire","geo":null,"iso_language_code":"en","to_user_id_str":"128028225","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"782692","profile_image_url":"http://a0.twimg.com/profile_images/1031304589/Profile.2007.1_normal.jpg","created_at":"Wed, 26 Jan 2011 03:29:19 +0000","from_user":"turnageb","id_str":"30104974591533057","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @ovillalon: Paul Ryan solves the mystery of whatever happened to Eddie Haskell. #sotu","id":30104974591533057,"from_user_id":782692,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:28:04 +0000","from_user":"chewedwire","id_str":"30104657267265536","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon I always loved the pattern matching in SML and it looks like Haskell is MUCH better at it. I'm messing around now at tryhaskell.org","id":30104657267265536,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"12834082","profile_image_url":"http://a3.twimg.com/profile_images/1083036140/mugshot_normal.png","created_at":"Wed, 26 Jan 2011 03:28:01 +0000","from_user":"ovillalon","id_str":"30104647213518848","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Paul Ryan solves the mystery of whatever happened to Eddie Haskell. #sotu","id":30104647213518848,"from_user_id":12834082,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"13540930","profile_image_url":"http://a1.twimg.com/profile_images/1205312219/23467_350321383101_821143101_5114147_3010041_n_normal.jpg","created_at":"Wed, 26 Jan 2011 03:26:02 +0000","from_user":"goodfox","id_str":"30104146455560192","metadata":{"result_type":"recent"},"to_user_id":10226179,"text":"@billykeene22 Bordeaux is one of my heroes. I was so excited when he accepted the invitation to campus. He's been a great friend to Haskell.","id":30104146455560192,"from_user_id":13540930,"to_user":"billykeene22","geo":null,"iso_language_code":"en","to_user_id_str":"10226179","source":"&lt;a href=&quot;http://www.ubertwitter.com/bb/download.php&quot; rel=&quot;nofollow&quot;&gt;\u00dcberTwitter&lt;/a&gt;"},{"from_user_id_str":"18616016","profile_image_url":"http://a2.twimg.com/profile_images/1173522726/214397343_normal.jpg","created_at":"Wed, 26 Jan 2011 03:25:18 +0000","from_user":"josej30","id_str":"30103962313031681","metadata":{"result_type":"recent"},"to_user_id":14870909,"text":"@cris7ian Ahh bueno multiparadigma ya es respetable :) Empezar\u00e9 a explotar la parte funcional de los lenguajes ahora #Haskell","id":30103962313031681,"from_user_id":18616016,"to_user":"Cris7ian","geo":null,"iso_language_code":"es","to_user_id_str":"14870909","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"14870909","profile_image_url":"http://a2.twimg.com/profile_images/1176930429/oso_yo_normal.png","created_at":"Wed, 26 Jan 2011 03:23:43 +0000","from_user":"Cris7ian","id_str":"30103562360983553","metadata":{"result_type":"recent"},"to_user_id":18616016,"text":"@josej30 hahaha no, es multiparadigma y es bastante lazy. Nothing like haskell, pero s\u00ed, el de Flash","id":30103562360983553,"from_user_id":14870909,"to_user":"josej30","geo":null,"iso_language_code":"es","to_user_id_str":"18616016","source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"2421643","profile_image_url":"http://a0.twimg.com/profile_images/1190361665/ernestgrumbles-17_normal.jpg","created_at":"Wed, 26 Jan 2011 03:20:24 +0000","from_user":"ernestgrumbles","id_str":"30102730756333568","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Wow... WolframAlpha did not know who Eddie Haskell is.  Guess I'll never use that &quot;knowledge engine&quot; again.","id":30102730756333568,"from_user_id":2421643,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:14:21 +0000","from_user":"chewedwire","id_str":"30101204428132352","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon How is Haskell better/different from CL or Scheme? I honestly don't know, although I'm becoming more curious.","id":30101204428132352,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"13540930","profile_image_url":"http://a1.twimg.com/profile_images/1205312219/23467_350321383101_821143101_5114147_3010041_n_normal.jpg","created_at":"Wed, 26 Jan 2011 03:06:54 +0000","from_user":"goodfox","id_str":"30099329809129473","metadata":{"result_type":"recent"},"to_user_id":null,"text":"A day of vision &amp; speeches. #SOTU now. And a wonderful Haskell Convocation address earlier today by Sinte Gleske President Lionel Bordeaux.","id":30099329809129473,"from_user_id":13540930,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.ubertwitter.com/bb/download.php&quot; rel=&quot;nofollow&quot;&gt;\u00dcberTwitter&lt;/a&gt;"},{"from_user_id_str":"119185220","profile_image_url":"http://a0.twimg.com/profile_images/1089027228/dfg_normal.jpg","created_at":"Wed, 26 Jan 2011 03:03:38 +0000","from_user":"LaLiciouz_03","id_str":"30098510623805440","metadata":{"result_type":"recent"},"to_user_id":null,"text":"The Game with the girl room 330 Haskell follow us...","id":30098510623805440,"from_user_id":119185220,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"18616016","profile_image_url":"http://a2.twimg.com/profile_images/1173522726/214397343_normal.jpg","created_at":"Wed, 26 Jan 2011 02:57:25 +0000","from_user":"josej30","id_str":"30096946144215040","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Voy a extra\u00f1ar Haskell cuando regrese al mundo imperativo. Hay alg\u00fan lenguaje imperativo que tenga este poder funcional? #ci3661","id":30096946144215040,"from_user_id":18616016,"geo":null,"iso_language_code":"es","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Wed, 26 Jan 2011 02:55:32 +0000","from_user":"Hackage","id_str":"30096471814574080","metadata":{"result_type":"recent"},"to_user_id":null,"text":"comonad-transformers 0.9.0, added by EdwardKmett: Haskell 98 comonad transformers http://bit.ly/h6xIsf","id":30096471814574080,"from_user_id":17671137,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 02:48:12 +0000","from_user":"tomheon","id_str":"30094626920603649","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Every time I look at Haskell I love it more.","id":30094626920603649,"from_user_id":177539201,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"60792568","profile_image_url":"http://a0.twimg.com/profile_images/1203647517/glenda-flash_normal.jpg","created_at":"Wed, 26 Jan 2011 02:40:42 +0000","from_user":"r_takaishi","id_str":"30092735935422464","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell\u3088\u308aD\u8a00\u8a9e\u304c\u4e0a\u3068\u306f\u601d\u308f\u306a\u304b\u3063\u305f\uff0e http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html","id":30092735935422464,"from_user_id":60792568,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twmode.sf.net/&quot; rel=&quot;nofollow&quot;&gt;twmode&lt;/a&gt;"},{"from_user_id_str":"160145510","profile_image_url":"http://a0.twimg.com/profile_images/1218108166/going_galt_normal.jpg","created_at":"Wed, 26 Jan 2011 02:39:31 +0000","from_user":"wtp1787","id_str":"30092439653974018","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @KLSouth: Eddie Haskell Goes to Washington...  &quot;You look really nice tonight, Ms Cleaver&quot;","id":30092439653974018,"from_user_id":160145510,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"96616016","profile_image_url":"http://a1.twimg.com/profile_images/1196978169/Picture0002_normal.jpg","created_at":"Wed, 26 Jan 2011 02:39:20 +0000","from_user":"MelissaRNMBA","id_str":"30092392203816960","metadata":{"result_type":"recent"},"to_user_id":14862975,"text":"@KLSouth At least Eddie Haskell was entertaining.","id":30092392203816960,"from_user_id":96616016,"to_user":"KLSouth","geo":null,"iso_language_code":"en","to_user_id_str":"14862975","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"14862975","profile_image_url":"http://a0.twimg.com/profile_images/421596393/kls_4_normal.JPG","created_at":"Wed, 26 Jan 2011 02:38:29 +0000","from_user":"KLSouth","id_str":"30092178327871489","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Eddie Haskell Goes to Washington...  &quot;You look really nice tonight, Ms Cleaver&quot;","id":30092178327871489,"from_user_id":14862975,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 02:36:17 +0000","from_user":"listwarenet","id_str":"30091626869161984","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-beginners/84641-haskell-beginners-wildcards-in-expressions.html Haskell-beginners -  Wild","id":30091626869161984,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"24538048","profile_image_url":"http://a2.twimg.com/profile_images/1117267605/rope_normal.jpg","created_at":"Wed, 26 Jan 2011 02:23:14 +0000","from_user":"dbph","id_str":"30088341030440960","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @dnene: Skilled Calisthenics. Haskell code that outputs python which spits ruby which emits the haskell source. http://j.mp/YlQUL via @mfeathers","id":30088341030440960,"from_user_id":24538048,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"158951567","profile_image_url":"http://a3.twimg.com/profile_images/962721419/Logo_3_normal.jpg","created_at":"Wed, 26 Jan 2011 01:58:31 +0000","from_user":"YubaVetTech","id_str":"30082124207886336","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Dr. Haskell has just been awarded the prestigious Hayward Award for \u2018Excellence in Education\u2019. This award honors... http://fb.me/QgQCxd74","id":30082124207886336,"from_user_id":158951567,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.facebook.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Facebook&lt;/a&gt;"},{"from_user_id_str":"158951567","profile_image_url":"http://a3.twimg.com/profile_images/962721419/Logo_3_normal.jpg","created_at":"Wed, 26 Jan 2011 01:56:04 +0000","from_user":"YubaVetTech","id_str":"30081505476743168","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Dr. Haskell has just been awarded the prestigous Haward Award for Excellence in Education. This award honors... http://fb.me/PC9mYmCR","id":30081505476743168,"from_user_id":158951567,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.facebook.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Facebook&lt;/a&gt;"},{"from_user_id_str":"2331498","profile_image_url":"http://a3.twimg.com/profile_images/494632120/me_normal.jpg","created_at":"Wed, 26 Jan 2011 01:43:50 +0000","from_user":"Verus","id_str":"30078427155406848","metadata":{"result_type":"recent"},"to_user_id":79273052,"text":"@kami_joe \u3044\u3084\uff0c\u8ab2\u984c\u306f\u89e3\u6c7a\u5bfe\u8c61(\u30d1\u30ba\u30eb\u3068\u304b)\u3092\u4e0e\u3048\u3089\u308c\u3066\uff0c\u554f\u984c\u5b9a\u7fa9\u3068\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0(\u6307\u5b9a\u8a00\u8a9e\u306fC++\u3082\u3057\u304f\u306fJava)\u3068\u3044\u3046\u3044\u308f\u3070\u666e\u901a\u306a\u8ab2\u984c\u3067\u306f\u3042\u308b\u3093\u3060\u3051\u3069\uff0e\u95a2\u6570\u578b\u8a00\u8a9e\u306fHaskell\u306e\u6388\u696d\u304c\u307e\u305f\u5225\u306b\u3042\u308b\u306e\uff0e","id":30078427155406848,"from_user_id":2331498,"to_user":"kami_joe","geo":null,"iso_language_code":"ja","to_user_id_str":"79273052","source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"79151233","profile_image_url":"http://a2.twimg.com/a/1295051201/images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 01:40:37 +0000","from_user":"cz_newdrafts","id_str":"30077617361125376","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell programming language http://bit.ly/gpPAwB","id":30077617361125376,"from_user_id":79151233,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://tommorris.org/&quot; rel=&quot;nofollow&quot;&gt;tommorris' hacksample&lt;/a&gt;"},{"from_user_id_str":"2331498","profile_image_url":"http://a3.twimg.com/profile_images/494632120/me_normal.jpg","created_at":"Wed, 26 Jan 2011 01:02:57 +0000","from_user":"Verus","id_str":"30068139416879104","metadata":{"result_type":"recent"},"to_user_id":9252720,"text":"@shukukei Java\u3068C\u306f\u3042\u308b\u7a0b\u5ea6\u66f8\u3051\u3066\u3042\u305f\u308a\u307e\u3048\u306a\u3068\u3053\u308d\u304c\u3042\u308b\u304b\u3089\u306a\u30fc\uff0ePython\u306f\u500b\u4eba\u7684\u306b\u611f\u899a\u304c\u5408\u308f\u306a\u3044\uff0e\u611f\u899a\u306a\u306e\u3067\uff0c\u3082\u3046\u3069\u3046\u3057\u3088\u3046\u3082\u306a\u3044\uff57 \u3044\u307e\u306fScala\u3068Haskell\u3092\u3082\u3063\u3068\u6975\u3081\u305f\u3044\u3068\u3053\u308d\uff0e","id":30068139416879104,"from_user_id":2331498,"to_user":"shukukei","geo":null,"iso_language_code":"ja","to_user_id_str":"9252720","source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"2781460","profile_image_url":"http://a0.twimg.com/profile_images/82526625/.joeyicon_normal.jpg","created_at":"Wed, 26 Jan 2011 01:02:35 +0000","from_user":"joeyhess","id_str":"30068046538219520","metadata":{"result_type":"recent"},"to_user_id":null,"text":"just figured out that I can use parameterized types to remove a dependency loop in git-annex's type definitions. whee #haskell","id":30068046538219520,"from_user_id":2781460,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://identi.ca&quot; rel=&quot;nofollow&quot;&gt;identica&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 00:54:22 +0000","from_user":"listwarenet","id_str":"30065977920061440","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-beginners/84466-haskell-beginners-bytestring-question.html Haskell-beginners -  Bytestrin","id":30065977920061440,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"1291845","profile_image_url":"http://a0.twimg.com/profile_images/1225743404/ThinOxygen-small-opaque-solidarity_normal.png","created_at":"Wed, 26 Jan 2011 00:52:07 +0000","from_user":"_aaron_","id_str":"30065412242669568","metadata":{"result_type":"recent"},"to_user_id":null,"text":"wanted: librly licensed high level native compiled lang with min runtime (otherwise cobra/mono would be perfect) for win. lua? haskell? ooc?","id":30065412242669568,"from_user_id":1291845,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"5912444","profile_image_url":"http://a2.twimg.com/profile_images/546261026/ssf0xg11_normal.jpg","created_at":"Wed, 26 Jan 2011 00:45:45 +0000","from_user":"shelarcy","id_str":"30063810773516288","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @Hackage: download 0.3.1.1, added by MagnusTherning: High-level file download based on URLs http://bit.ly/eHfiJB","id":30063810773516288,"from_user_id":5912444,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"135993","profile_image_url":"http://a2.twimg.com/profile_images/1190667086/myface2010small_normal.jpg","created_at":"Wed, 26 Jan 2011 00:41:00 +0000","from_user":"kudzu_naoki","id_str":"30062613287141376","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tanakh: \u9b54\u6cd5Haskell\u5c11\u5973\u5019\u88dc\u3092\u63a2\u3059\u306e\u3082\u5927\u5909\u306a\u3093\u3060","id":30062613287141376,"from_user_id":135993,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"52620546","profile_image_url":"http://a1.twimg.com/profile_images/434693356/twitter-icon_normal.png","created_at":"Wed, 26 Jan 2011 00:40:25 +0000","from_user":"omasanori","id_str":"30062465656033280","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u9b54\u6cd5Haskell\u5c11\u5973\u306e\u4e00\u65e5\u306fGHC HEAD\u306e\u30d3\u30eb\u30c9\u304b\u3089\u59cb\u307e\u308b","id":30062465656033280,"from_user_id":52620546,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.movatwi.jp&quot; rel=&quot;nofollow&quot;&gt;www.movatwi.jp&lt;/a&gt;"},{"from_user_id_str":"52620546","profile_image_url":"http://a1.twimg.com/profile_images/434693356/twitter-icon_normal.png","created_at":"Wed, 26 Jan 2011 00:37:12 +0000","from_user":"omasanori","id_str":"30061656331526144","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tanakh: \u50d5\u3068\u5951\u7d04\u3057\u3066\u9b54\u6cd5Haskell\u5c11\u5973\u306b\u306a\u308d\u3046\u3088\uff01","id":30061656331526144,"from_user_id":52620546,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"135993","profile_image_url":"http://a2.twimg.com/profile_images/1190667086/myface2010small_normal.jpg","created_at":"Wed, 26 Jan 2011 00:35:42 +0000","from_user":"kudzu_naoki","id_str":"30061282665168896","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tanakh: \u50d5\u3068\u5951\u7d04\u3057\u3066\u9b54\u6cd5Haskell\u5c11\u5973\u306b\u306a\u308d\u3046\u3088\uff01","id":30061282665168896,"from_user_id":135993,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"1631333","profile_image_url":"http://a1.twimg.com/profile_images/81268862/profile300_normal.jpg","created_at":"Wed, 26 Jan 2011 00:30:02 +0000","from_user":"qnighy","id_str":"30059855884582913","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tanakh: \u50d5\u3068\u5951\u7d04\u3057\u3066\u9b54\u6cd5Haskell\u5c11\u5973\u306b\u306a\u308d\u3046\u3088\uff01","id":30059855884582913,"from_user_id":1631333,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"9093754","profile_image_url":"http://a1.twimg.com/profile_images/99435906/PHD_3d_col_blk_normal.jpg","created_at":"Wed, 26 Jan 2011 00:26:20 +0000","from_user":"phdwine","id_str":"30058925516656640","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Last weekend of Tri Nations Tasting with PHD wines at Haskell Vineyards. Hope you didn't miss the Pinot Noir tasting last week !","id":30058925516656640,"from_user_id":9093754,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"2119923","profile_image_url":"http://a2.twimg.com/profile_images/1096701078/djayprofile_normal.jpg","created_at":"Wed, 26 Jan 2011 00:21:14 +0000","from_user":"djay75","id_str":"30057639543050240","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @dnene: Skilled Calisthenics. Haskell code that outputs python which spits ruby which emits the haskell source. http://j.mp/YlQUL via @mfeathers","id":30057639543050240,"from_user_id":2119923,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"134323731","profile_image_url":"http://a2.twimg.com/profile_images/1225818824/IMG00518-20110125-1547_normal.jpg","created_at":"Wed, 26 Jan 2011 00:19:30 +0000","from_user":"PrinceOfBrkeley","id_str":"30057205554216960","metadata":{"result_type":"recent"},"to_user_id":167093027,"text":"@PayThaPrince go to haskell.","id":30057205554216960,"from_user_id":134323731,"to_user":"PayThaPrince","geo":null,"iso_language_code":"en","to_user_id_str":"167093027","source":"&lt;a href=&quot;http://blackberry.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Twitter for BlackBerry\u00ae&lt;/a&gt;"},{"from_user_id_str":"705857","profile_image_url":"http://a1.twimg.com/profile_images/429483912/ben_twitter_normal.jpg","created_at":"Wed, 26 Jan 2011 00:03:28 +0000","from_user":"bennadel","id_str":"30053166972141569","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Using #Homebrew to install Haskell - the last of the Seven Languages (in Seven Weeks) http://bit.ly/eA9Cv1 This has been some journey.","id":30053166972141569,"from_user_id":705857,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"251466","profile_image_url":"http://a2.twimg.com/profile_images/1194100934/pass_normal.jpg","created_at":"Wed, 26 Jan 2011 00:02:54 +0000","from_user":"simonszu","id_str":"30053025502466048","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Ouh yeah! Ich werde doch produktiv sein, diese Semesterferien. Ich werde funktional Programmieren lernen. #haskell, Baby.","id":30053025502466048,"from_user_id":251466,"geo":null,"iso_language_code":"de","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"357786","profile_image_url":"http://a0.twimg.com/profile_images/612044841/FM_2010_normal.jpg","created_at":"Tue, 25 Jan 2011 23:59:13 +0000","from_user":"diligiant","id_str":"30052100973006848","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @paulrbrown: &quot;...we only discovered a single bug after compilation.&quot; (http://t.co/K0wlEYz) #haskell","id":30052100973006848,"from_user_id":357786,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"101597523","profile_image_url":"http://a1.twimg.com/profile_images/1206183256/2010-12-12-204902_normal.jpg","created_at":"Tue, 25 Jan 2011 23:54:46 +0000","from_user":"wlad_kent","id_str":"30050977964892160","metadata":{"result_type":"recent"},"to_user_id":86297184,"text":"@Nilson_Neto Isso eh bem basico. quando vc estiver estudando recurs\u00e3o em Haskell, ai vc vai ver oq eh papo de nerd - kkk - 1\u00ba periodo isso.","id":30050977964892160,"from_user_id":101597523,"to_user":"Nilson_Neto","geo":null,"iso_language_code":"pt","to_user_id_str":"86297184","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Tue, 25 Jan 2011 23:51:22 +0000","from_user":"listwarenet","id_str":"30050123383832577","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-cafe/84336-haskell-cafe-monomorphic-let-bindings-and-darcs.html Haskell-cafe -  Monomorph","id":30050123383832577,"from_user_id":144546280,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"5776901","profile_image_url":"http://a0.twimg.com/profile_images/472682157/lucabw_normal.JPG","created_at":"Tue, 25 Jan 2011 23:48:40 +0000","from_user":"lsbardel","id_str":"30049446469312512","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Very interesting technology stack these guys use http://bit.ly/ghAjS7 #python #redis #haskell","id":30049446469312512,"from_user_id":5776901,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"3005901","profile_image_url":"http://a0.twimg.com/profile_images/278943006/Lone_Pine_Peak_-_Peter_200x200_normal.jpg","created_at":"Tue, 25 Jan 2011 23:45:48 +0000","from_user":"pmonks","id_str":"30048721110573056","metadata":{"result_type":"recent"},"to_user_id":203834278,"text":"@techielicous Haskell: http://bit.ly/gy3oFi  ;-)","id":30048721110573056,"from_user_id":3005901,"to_user":"techielicous","geo":null,"iso_language_code":"en","to_user_id_str":"203834278","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"162697074","profile_image_url":"http://a2.twimg.com/profile_images/826205838/ryan3_normal.jpg","created_at":"Tue, 25 Jan 2011 23:44:47 +0000","from_user":"TheRonaldMCD","id_str":"30048468781244416","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Aldi Food Market (4122 Gaston Ave, Haskell, Dallas) http://4sq.com/ekqRY7","id":30048468781244416,"from_user_id":162697074,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"203834278","profile_image_url":"http://a0.twimg.com/profile_images/1223375080/me_normal.jpg","created_at":"Tue, 25 Jan 2011 23:44:04 +0000","from_user":"techielicous","id_str":"30048286589067264","metadata":{"result_type":"recent"},"to_user_id":3005901,"text":"@pmonks I was thinking Haskell or Scheme","id":30048286589067264,"from_user_id":203834278,"to_user":"pmonks","geo":null,"iso_language_code":"en","to_user_id_str":"3005901","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"537690","profile_image_url":"http://a3.twimg.com/profile_images/45665122/nushiostamp_normal.jpg","created_at":"Tue, 25 Jan 2011 23:38:14 +0000","from_user":"nushio","id_str":"30046818658164737","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u305d\u3046\u3044\u3084\u5951\u7d04\u306b\u3088\u308b\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u3068\u304b\u3042\u3063\u305f\u306a\u3002Haskell\u306a\u3093\u304b\u3088\u308a\u3042\u3063\u3061\u306e\u65b9\u304c\u9b54\u6cd5\u5c11\u5973\u547c\u3070\u308f\u308a\u306b\u3075\u3055\u308f\u3057\u3044\u3002","id":30046818658164737,"from_user_id":537690,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"181192","profile_image_url":"http://a2.twimg.com/profile_images/1089890701/q530888600_9828_normal.jpg","created_at":"Tue, 25 Jan 2011 23:38:03 +0000","from_user":"aodag","id_str":"30046772223016960","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @omasanori: \u300c\u3082\u3046\u4f55\u5e74\u3082Haskell\u306e\u3053\u3068\u3057\u304b\u8003\u3048\u3066\u306a\u304b\u3063\u305f\u304b\u3089\u306a\u3001\u30eb\u30fc\u30d7\u306e\u4f7f\u3044\u65b9\u5fd8\u308c\u3066\u305f\u300d","id":30046772223016960,"from_user_id":181192,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.movatwi.jp&quot; rel=&quot;nofollow&quot;&gt;www.movatwi.jp&lt;/a&gt;"},{"from_user_id_str":"5886055","profile_image_url":"http://a3.twimg.com/profile_images/85531669/ichi_normal.jpg","created_at":"Tue, 25 Jan 2011 23:37:53 +0000","from_user":"kanaya","id_str":"30046729243983873","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u9e97\u3057\u3044\u3002\u201c@omasanori: \u300c\u3082\u3046\u4f55\u5e74\u3082Haskell\u306e\u3053\u3068\u3057\u304b\u8003\u3048\u3066\u306a\u304b\u3063\u305f\u304b\u3089\u306a\u3001\u30eb\u30fc\u30d7\u306e\u4f7f\u3044\u65b9\u5fd8\u308c\u3066\u305f\u300d\u201d","id":30046729243983873,"from_user_id":5886055,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/app/twitter/id333903271?mt=8&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPad&lt;/a&gt;"},{"from_user_id_str":"52620546","profile_image_url":"http://a1.twimg.com/profile_images/434693356/twitter-icon_normal.png","created_at":"Tue, 25 Jan 2011 23:36:26 +0000","from_user":"omasanori","id_str":"30046367187476481","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u300c\u3082\u3046\u4f55\u5e74\u3082Haskell\u306e\u3053\u3068\u3057\u304b\u8003\u3048\u3066\u306a\u304b\u3063\u305f\u304b\u3089\u306a\u3001\u30eb\u30fc\u30d7\u306e\u4f7f\u3044\u65b9\u5fd8\u308c\u3066\u305f\u300d","id":30046367187476481,"from_user_id":52620546,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.movatwi.jp&quot; rel=&quot;nofollow&quot;&gt;www.movatwi.jp&lt;/a&gt;"},{"from_user_id_str":"1659992","profile_image_url":"http://a1.twimg.com/profile_images/504488750/1_normal.jpg","created_at":"Tue, 25 Jan 2011 23:16:13 +0000","from_user":"finalfusion","id_str":"30041278544609280","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @necocen: Haskell\u306e\u30df\u30b5\u30ef\u3001\u3068\u3044\u3046\u3082\u306e\u3092\u8003\u3048\u3066\u307f\u3066\u3071\u3063\u3068\u3057\u306a\u3044","id":30041278544609280,"from_user_id":1659992,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"272513","profile_image_url":"http://a2.twimg.com/profile_images/320244078/Mike_Painting2_normal.png","created_at":"Tue, 25 Jan 2011 23:05:09 +0000","from_user":"mikehadlow","id_str":"30038492373319680","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Just written the same simple program in C#, F# and Haskell: 18, 12 and 9 LoC respectively. And I'm much better at C# than F# or Haskell.","id":30038492373319680,"from_user_id":272513,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"89393264","profile_image_url":"http://a0.twimg.com/profile_images/1169486472/020_portland_me_normal.jpg","created_at":"Tue, 25 Jan 2011 23:01:28 +0000","from_user":"newsportlandme","id_str":"30037564589084673","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Governor's Choice to Run Maine DOC Under Scrutiny - MPBN: State Rep. Anne Haskell, a Portland Democrat, says Mai... http://bit.ly/fO30gC","id":30037564589084673,"from_user_id":89393264,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"38138","profile_image_url":"http://a3.twimg.com/profile_images/1212565885/Screen_shot_2011-01-11_at_5.28.47_PM_normal.png","created_at":"Tue, 25 Jan 2011 22:59:55 +0000","from_user":"michaelneale","id_str":"30037174615281664","metadata":{"result_type":"recent"},"to_user_id":null,"text":"The haskell EvilMangler http://t.co/P2Tls7J","id":30037174615281664,"from_user_id":38138,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"45692","profile_image_url":"http://a3.twimg.com/profile_images/1177741507/dogkarno_r_normal.jpg","created_at":"Tue, 25 Jan 2011 22:45:06 +0000","from_user":"karno","id_str":"30033448286552064","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell\u3063\u3066\u95a2\u6570\u306b\u30ab\u30ec\u30fc\u7c89\u3076\u3061\u8fbc\u3080\u3068\u304b\u306a\u3093\u3068\u304b","id":30033448286552064,"from_user_id":45692,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://yubitter.com/&quot; rel=&quot;nofollow&quot;&gt;yubitter&lt;/a&gt;"},{"from_user_id_str":"27605","profile_image_url":"http://a2.twimg.com/profile_images/15826632/meron_normal.jpg","created_at":"Tue, 25 Jan 2011 22:44:23 +0000","from_user":"celeron1ghz","id_str":"30033268761956352","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @necocen: Haskell\u306e\u30df\u30b5\u30ef\u3001\u3068\u3044\u3046\u3082\u306e\u3092\u8003\u3048\u3066\u307f\u3066\u3071\u3063\u3068\u3057\u306a\u3044","id":30033268761956352,"from_user_id":27605,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"12901","profile_image_url":"http://a1.twimg.com/profile_images/56091349/haruhi_nagato-Y_normal.jpg","created_at":"Tue, 25 Jan 2011 22:43:30 +0000","from_user":"necocen","id_str":"30033044035346432","metadata":{"result_type":"recent"},"to_user_id":null,"text":"\u307e\u3042Haskell\u77e5\u3089\u3093\u3057\u306d","id":30033044035346432,"from_user_id":12901,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"12901","profile_image_url":"http://a1.twimg.com/profile_images/56091349/haruhi_nagato-Y_normal.jpg","created_at":"Tue, 25 Jan 2011 22:42:54 +0000","from_user":"necocen","id_str":"30032894856531968","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell\u306e\u30df\u30b5\u30ef\u3001\u3068\u3044\u3046\u3082\u306e\u3092\u8003\u3048\u3066\u307f\u3066\u3071\u3063\u3068\u3057\u306a\u3044","id":30032894856531968,"from_user_id":12901,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"10821270","profile_image_url":"http://a0.twimg.com/profile_images/1195474259/Salto_Marlon_normal.jpg","created_at":"Tue, 25 Jan 2011 22:35:09 +0000","from_user":"jjedMoriAnktah","id_str":"30030942106025984","metadata":{"result_type":"recent"},"to_user_id":null,"text":"&quot;A Haskell program that outputs a Python program that outputs a Ruby program that outputs the original Haskell program&quot; http://is.gd/E6Julu","id":30030942106025984,"from_user_id":10821270,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"7554762","profile_image_url":"http://a0.twimg.com/profile_images/100515212/ajay-photo_normal.jpg","created_at":"Tue, 25 Jan 2011 22:34:30 +0000","from_user":"comatose_kid","id_str":"30030780205899776","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @bumptech: Bump Dev Blog - Why we use Haskell at Bump http://devblog.bu.mp/haskell-at-bump","id":30030780205899776,"from_user_id":7554762,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"148474705","profile_image_url":"http://a0.twimg.com/profile_images/1119234716/fur_hat_-_gilbeys_vodka_-_life_-_11-30-1962_normal.JPG","created_at":"Tue, 25 Jan 2011 22:29:19 +0000","from_user":"landmvintage","id_str":"30029476003840000","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @faerymoongodess: Magnificent Miriam Haskell Baroque Pearl Necklace by @MercyMadge http://etsy.me/hqRl51","id":30029476003840000,"from_user_id":148474705,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"37715508","profile_image_url":"http://a1.twimg.com/profile_images/1207891411/ballerina_normal.jpg","created_at":"Tue, 25 Jan 2011 22:24:52 +0000","from_user":"faerymoongodess","id_str":"30028356326002688","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Magnificent Miriam Haskell Baroque Pearl Necklace by @MercyMadge http://etsy.me/hqRl51","id":30028356326002688,"from_user_id":37715508,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Tue, 25 Jan 2011 22:17:16 +0000","from_user":"Hackage","id_str":"30026442456694784","metadata":{"result_type":"recent"},"to_user_id":null,"text":"base16-bytestring 0.1.0.0, added by BryanOSullivan: Fast base16 (hex) encoding and deconding for ByteStrings http://bit.ly/eu75TN","id":30026442456694784,"from_user_id":17671137,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"199750997","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Tue, 25 Jan 2011 22:12:07 +0000","from_user":"benreads","id_str":"30025146991382528","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Writing Systems Software in a Functional Language -- brief, but fun. I want to see how well they can make Systems Haskell perform at scale.","id":30025146991382528,"from_user_id":199750997,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"35359797","profile_image_url":"http://a1.twimg.com/profile_images/1173453785/48893_521140819_1896062_q_normal.jpg","created_at":"Tue, 25 Jan 2011 22:09:45 +0000","from_user":"jcawthorne1","id_str":"30024549265309696","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Just saw Jeff Haskell give the middle finger!! Lol awesome","id":30024549265309696,"from_user_id":35359797,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"13540930","profile_image_url":"http://a1.twimg.com/profile_images/1205312219/23467_350321383101_821143101_5114147_3010041_n_normal.jpg","created_at":"Tue, 25 Jan 2011 22:06:44 +0000","from_user":"goodfox","id_str":"30023790381498369","metadata":{"result_type":"recent"},"to_user_id":null,"text":"At the Haskell Convocation. (@ Haskell Indian Nations U Auditorium) http://4sq.com/eKKXyn","id":30023790381498369,"from_user_id":13540930,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"14674418","profile_image_url":"http://a2.twimg.com/profile_images/238230125/IMG_1030-1_normal.jpg","created_at":"Tue, 25 Jan 2011 22:02:31 +0000","from_user":"sanityinc","id_str":"30022731919523840","metadata":{"result_type":"recent"},"to_user_id":371289,"text":"@xshay Haskell's great, but Clojure's similarly lazy in all the ways that matter, and is more practical for day-to-day use.","id":30022731919523840,"from_user_id":14674418,"to_user":"xshay","geo":null,"iso_language_code":"en","to_user_id_str":"371289","source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"371289","profile_image_url":"http://a2.twimg.com/profile_images/1113482439/me-brisbane_normal.jpg","created_at":"Tue, 25 Jan 2011 21:58:29 +0000","from_user":"xshay","id_str":"30021714444292096","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Just made a lazy sequence of prime numbers in haskell. I'm smitten.","id":30021714444292096,"from_user_id":371289,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"199453873","profile_image_url":"http://a3.twimg.com/a/1294785484/images/default_profile_3_normal.png","created_at":"Tue, 25 Jan 2011 21:48:40 +0000","from_user":"stackfeed","id_str":"30019243982454784","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Practical Scala reference manual, for searching things like method names: Hello, \n\nInspired by\nHaskell API Searc... http://bit.ly/g4zWZQ","id":30019243982454784,"from_user_id":199453873,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17489366","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Tue, 25 Jan 2011 21:45:32 +0000","from_user":"aapnoot","id_str":"30018455189065728","metadata":{"result_type":"recent"},"to_user_id":null,"text":"download 0.3.1, added by MagnusTherning: High-level file download based on URLs http://bit.ly/i8mYvi","id":30018455189065728,"from_user_id":17489366,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17489366","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Tue, 25 Jan 2011 21:45:31 +0000","from_user":"aapnoot","id_str":"30018452601180160","metadata":{"result_type":"recent"},"to_user_id":null,"text":"download 0.3.1.1, added by MagnusTherning: High-level file download based on URLs http://bit.ly/eHfiJB","id":30018452601180160,"from_user_id":17489366,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Tue, 25 Jan 2011 21:45:31 +0000","from_user":"Hackage","id_str":"30018451867176960","metadata":{"result_type":"recent"},"to_user_id":null,"text":"download 0.3.1, added by MagnusTherning: High-level file download based on URLs http://bit.ly/i8mYvi","id":30018451867176960,"from_user_id":17671137,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"138502705","profile_image_url":"http://a1.twimg.com/profile_images/1083845614/yclogo_normal.gif","created_at":"Tue, 25 Jan 2011 21:45:04 +0000","from_user":"newsyc100","id_str":"30018340839755777","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell improves log processing 4x over Python http://devblog.bu.mp/haskell-at-bump (http://bit.ly/gQxxR8)","id":30018340839755777,"from_user_id":138502705,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://news.ycombinator.com&quot; rel=&quot;nofollow&quot;&gt;newsyc&lt;/a&gt;"},{"from_user_id_str":"1578246","profile_image_url":"http://a0.twimg.com/profile_images/59312315/avatar_simpson_small_normal.jpg","created_at":"Tue, 25 Jan 2011 21:43:32 +0000","from_user":"magthe","id_str":"30017953801969665","metadata":{"result_type":"recent"},"to_user_id":null,"text":"New version of download uploaded to #hackage #haskell","id":30017953801969665,"from_user_id":1578246,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://api.supertweet.net&quot; rel=&quot;nofollow&quot;&gt;MyAuth API Proxy&lt;/a&gt;"},{"from_user_id_str":"135838970","profile_image_url":"http://a2.twimg.com/profile_images/1079929891/logo_normal.png","created_at":"Tue, 25 Jan 2011 21:37:51 +0000","from_user":"reward999","id_str":"30016525180084224","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Found Great Dane (Main &amp; Haskell- Dallas): We found a great dane. 214-712-0000 http://bit.ly/fQ8iBw","id":30016525180084224,"from_user_id":135838970,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"137719265","profile_image_url":"http://a2.twimg.com/profile_images/1092224079/8__4__normal.jpg","created_at":"Tue, 25 Jan 2011 21:34:22 +0000","from_user":"WeiMatas","id_str":"30015646020411392","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Fourth day Rez party Eddie Haskell County in second life \u2013 which took place in cabaret Tadd","id":30015646020411392,"from_user_id":137719265,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://dlvr.it&quot; rel=&quot;nofollow&quot;&gt;dlvr.it&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Tue, 25 Jan 2011 21:33:21 +0000","from_user":"listwarenet","id_str":"30015392571195392","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-cafe/83889-haskell-cafe-gpl-license-of-h-matrix-and-prelude-numeric.html Haskell-cafe -","id":30015392571195392,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"}],"max_id":30121530767708160,"since_id":0,"refresh_url":"?since_id=30121530767708160&q=haskell","next_page":"?page=2&max_id=30121530767708160&rpp=100&q=haskell","results_per_page":100,"page":1,"completed_in":1.195569,"since_id_str":"0","max_id_str":"30121530767708160","query":"haskell"}
diff --git a/benchmarks/json-data/twitter20.json b/benchmarks/json-data/twitter20.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/twitter20.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"166199691","profile_image_url":"http://a2.twimg.com/profile_images/1252958188/38_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:26 +0000","from_user":"_classicc","id_str":"41191052790603776","metadata":{"result_type":"recent"},"to_user_id":null,"text":"my twitter is actin slow today.","id":41191052790603776,"from_user_id":166199691,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"138835410","profile_image_url":"http://a1.twimg.com/profile_images/1250985094/243321801_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:26 +0000","from_user":"amereronday","id_str":"41191050307567616","metadata":{"result_type":"recent"},"to_user_id":null,"text":"twitter jail, here i come.","id":41191050307567616,"from_user_id":138835410,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"359548","profile_image_url":"http://a2.twimg.com/profile_images/53612334/don_otvos_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:26 +0000","from_user":"donnyo","id_str":"41191050110451712","metadata":{"result_type":"recent"},"to_user_id":7074534,"text":"@stlsmallbiz I see there is currently a Twitter promo too....tempting....","id":41191050110451712,"from_user_id":359548,"to_user":"stlsmallbiz","geo":null,"iso_language_code":"en","place":{"id":"82b7b2f97b12261d","type":"poi","full_name":"Yammer Inc, San Francisco"},"to_user_id_str":"7074534","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"122523770","profile_image_url":"http://a0.twimg.com/profile_images/1073533262/11646_1076222405045_1810798478_156114_3663737_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:26 +0000","from_user":"msBreChan","id_str":"41191049720238080","metadata":{"result_type":"recent"},"to_user_id":null,"text":"so twitter gt spam now -_-","id":41191049720238080,"from_user_id":122523770,"geo":{"type":"Point","coordinates":[35.2213,-80.8276]},"iso_language_code":"en","place":{"id":"4d5ed95f830e9b41","type":"neighborhood","full_name":"Elizabeth, Charlotte"},"to_user_id_str":null,"source":"&lt;a href=&quot;http://mobile.twitter.com&quot; rel=&quot;nofollow&quot;&gt;Twitter for Android&lt;/a&gt;"},{"from_user_id_str":"229024950","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_6_normal.png","created_at":"Fri, 25 Feb 2011 17:41:25 +0000","from_user":"NinaMaechik","id_str":"41191047853912064","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Glad I can remember my twitter password!  LOL!  Hugs to Nick from his aunties...","id":41191047853912064,"from_user_id":229024950,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"215545822","profile_image_url":"http://a2.twimg.com/profile_images/1239909540/RTL_normal.png","created_at":"Fri, 25 Feb 2011 17:41:25 +0000","from_user":"RightToLaugh","id_str":"41191047371558912","metadata":{"result_type":"recent"},"to_user_id":null,"text":"#Bacon wrapped dates http://bit.ly/hUxVC9 Just like my grandma used to make http://twitter.com/#","id":41191047371558912,"from_user_id":215545822,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"217845526","profile_image_url":"http://a0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png","created_at":"Fri, 25 Feb 2011 17:41:25 +0000","from_user":"TheShoeLooker","id_str":"41191047052804096","metadata":{"result_type":"recent"},"to_user_id":38033240,"text":"@ShoeDazzle love love love to twitter or blog about your deals and shoes!\ntheshoelooker.blogspot.com","id":41191047052804096,"from_user_id":217845526,"to_user":"shoedazzle","geo":null,"iso_language_code":"en","to_user_id_str":"38033240","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"24953438","profile_image_url":"http://a3.twimg.com/profile_images/1181252763/76820_10150100014748783_677998782_7386695_4377006_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:25 +0000","from_user":"liljermaine32","id_str":"41191046025056256","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Twitter fam I gotta question 4 ya is texas south or midwest #arguments","id":41191046025056256,"from_user_id":24953438,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://mobile.twitter.com&quot; rel=&quot;nofollow&quot;&gt;Twitter for Android&lt;/a&gt;"},{"from_user_id_str":"122451024","profile_image_url":"http://a2.twimg.com/profile_images/1143400129/100706-ETCanada_201134_1__normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:25 +0000","from_user":"Kim_DEon","id_str":"41191045161164801","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Help @CARE @EvaLongoria and ME use Twitter to change the lives of girls in poverty across the world! Ready? Go to http://TwitChange.com NOW!","id":41191045161164801,"from_user_id":122451024,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"128351479","profile_image_url":"http://a3.twimg.com/profile_images/1150198829/Kirby_Photo__edit__normal.JPG","created_at":"Fri, 25 Feb 2011 17:41:24 +0000","from_user":"TheDaveKirby","id_str":"41191043894493184","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Maybe its time to clean house...MY HOUSE http://bit.ly/ejG22P","id":41191043894493184,"from_user_id":128351479,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"87512773","profile_image_url":"http://a0.twimg.com/profile_images/1252511106/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:24 +0000","from_user":"supportthehood","id_str":"41191043206610946","metadata":{"result_type":"recent"},"to_user_id":2467330,"text":"@eastcoastmp3 #FF  it's the way twitter works !!!","id":41191043206610946,"from_user_id":87512773,"to_user":"eastcoastmp3","geo":null,"iso_language_code":"en","to_user_id_str":"2467330","source":"&lt;a href=&quot;http://twitter.com/&quot; rel=&quot;nofollow&quot;&gt;Twitter for iPhone&lt;/a&gt;"},{"from_user_id_str":"149894545","profile_image_url":"http://a0.twimg.com/profile_images/1219334400/patrick_camo_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:24 +0000","from_user":"suburbpat","id_str":"41191040912330752","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I havent had a rib session on twitter in a while.......I wanna Rib with a nigga with alot followers lol","id":41191040912330752,"from_user_id":149894545,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"97749622","profile_image_url":"http://a0.twimg.com/profile_images/1254640781/IMG1633A_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:24 +0000","from_user":"jrricardosantos","id_str":"41191040547430400","metadata":{"result_type":"recent"},"to_user_id":101017476,"text":"@yofzs pq tirou o CAPS LOCK? kkkk tava bem legal...hehehe eu estou no t\u00e9dio...kkk tbm estou no twitter e msn..aff!!","id":41191040547430400,"from_user_id":97749622,"to_user":"yofzs","geo":null,"iso_language_code":"en","to_user_id_str":"101017476","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"94381536","profile_image_url":"http://a1.twimg.com/profile_images/1174777929/41509_100001699300415_3521888_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:23 +0000","from_user":"DonNieves","id_str":"41191038978752512","metadata":{"result_type":"recent"},"to_user_id":151926400,"text":"@TiiH13 cheira meu ovo, no email, no orkut, no msn, no facebook, no twitter, no skype, no spark, no ICQ e no google talk","id":41191038978752512,"from_user_id":94381536,"to_user":"TiiH13","geo":null,"iso_language_code":"en","to_user_id_str":"151926400","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"211858432","profile_image_url":"http://a3.twimg.com/profile_images/1231906180/JonasBrothers_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:23 +0000","from_user":"OriginalJBfans","id_str":"41191038328651776","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I literally forgot about this twitter... so whats occuring followers?","id":41191038328651776,"from_user_id":211858432,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"90317132","profile_image_url":"http://a3.twimg.com/profile_images/1230085056/254101635_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:23 +0000","from_user":"Just2smooth","id_str":"41191036936126464","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Wassup twitter","id":41191036936126464,"from_user_id":90317132,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://ubersocial.com&quot; rel=&quot;nofollow&quot;&gt;\u00dcberSocial&lt;/a&gt;"},{"from_user_id_str":"144771504","profile_image_url":"http://a1.twimg.com/profile_images/1243343836/image_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:23 +0000","from_user":"ima_b_b_badman","id_str":"41191036638339072","metadata":{"result_type":"recent"},"to_user_id":null,"text":"i been M.I.A. all day twitter my bad","id":41191036638339072,"from_user_id":144771504,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"207922664","profile_image_url":"http://a2.twimg.com/profile_images/1237106108/258356167_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:22 +0000","from_user":"itsthecarter_","id_str":"41191036013391873","metadata":{"result_type":"recent"},"to_user_id":null,"text":"twitter is a stupid addiction.","id":41191036013391873,"from_user_id":207922664,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://ubersocial.com&quot; rel=&quot;nofollow&quot;&gt;\u00dcberSocial&lt;/a&gt;"},{"from_user_id_str":"150000649","profile_image_url":"http://a0.twimg.com/profile_images/1237789059/belllaa_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:22 +0000","from_user":"angelicabrvo","id_str":"41191035707207680","metadata":{"result_type":"recent"},"to_user_id":null,"text":"que hubo twitter? huy que feoxd","id":41191035707207680,"from_user_id":150000649,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://blackberry.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Twitter for BlackBerry\u00ae&lt;/a&gt;"},{"from_user_id_str":"185713003","profile_image_url":"http://a2.twimg.com/profile_images/1191421540/163229_177015295661467_154687431227587_492170_2147500_n_normal.jpg","created_at":"Fri, 25 Feb 2011 17:41:22 +0000","from_user":"downbytheshores","id_str":"41191033945595905","metadata":{"result_type":"recent"},"to_user_id":null,"text":"follow us on twitter\nwww.twitter.com/downbytheshores http://fb.me/DhDS915e","id":41191033945595905,"from_user_id":185713003,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.facebook.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Facebook&lt;/a&gt;"}],"max_id":41191052790603776,"since_id":38643906774044672,"refresh_url":"?since_id=41191052790603776&q=twitter","next_page":"?page=2&max_id=41191052790603776&rpp=20&lang=en&q=twitter","results_per_page":20,"page":1,"completed_in":0.128719,"warning":"adjusted since_id to 38643906774044672 (), requested since_id was older than allowed -- since_id removed for pagination.","since_id_str":"38643906774044672","max_id_str":"41191052790603776","query":"twitter"}
diff --git a/benchmarks/json-data/twitter50.json b/benchmarks/json-data/twitter50.json
new file mode 100644
--- /dev/null
+++ b/benchmarks/json-data/twitter50.json
@@ -0,0 +1,1 @@
+{"results":[{"from_user_id_str":"207858021","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 04:30:38 +0000","from_user":"pboudarga","id_str":"30120402839666689","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Rolla Sushi Grill (27737 Bouquet Canyon Road, #106, Btw Haskell Canyon and Rosedell Drive, Saugus) http://4sq.com/gqqdhs","id":30120402839666689,"from_user_id":207858021,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"69988683","profile_image_url":"http://a0.twimg.com/profile_images/1211955817/avatar_7888_normal.gif","created_at":"Wed, 26 Jan 2011 04:25:23 +0000","from_user":"YNK33","id_str":"30119083059978240","metadata":{"result_type":"recent"},"to_user_id":null,"text":"hsndfile 0.5.0: Free and open source Haskell bindings for libsndfile http://bit.ly/gHaBWG Mac Os","id":30119083059978240,"from_user_id":69988683,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"81492","profile_image_url":"http://a1.twimg.com/profile_images/423894208/Picture_7_normal.jpg","created_at":"Wed, 26 Jan 2011 04:24:28 +0000","from_user":"satzz","id_str":"30118851488251904","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Emacs\u306e\u30e2\u30fc\u30c9\u8868\u793a\u304c\u4eca(Ruby Controller Outputz RoR Flymake REl hs)\u3068\u306a\u3063\u3066\u3066\u3088\u304f\u308f\u304b\u3089\u306a\u3044\u3093\u3060\u3051\u3069\u6700\u5f8c\u306eREl\u3068\u304bhs\u3063\u3066\u4f55\u3060\u308d\u3046\u2026haskell\u3068\u304b2\u5e74\u4ee5\u4e0a\u66f8\u3044\u3066\u306a\u3044\u3051\u3069\u2026","id":30118851488251904,"from_user_id":81492,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.hootsuite.com&quot; rel=&quot;nofollow&quot;&gt;HootSuite&lt;/a&gt;"},{"from_user_id_str":"9518356","profile_image_url":"http://a2.twimg.com/profile_images/119165723/ocaml-icon_normal.png","created_at":"Wed, 26 Jan 2011 04:19:19 +0000","from_user":"planet_ocaml","id_str":"30117557788741632","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I so miss #haskell type classes in #ocaml - i want to do something like refinement. Also why does ocaml not have... http://bit.ly/geYRwt","id":30117557788741632,"from_user_id":9518356,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"218059","profile_image_url":"http://a1.twimg.com/profile_images/1053837723/twitter-icon9_normal.jpg","created_at":"Wed, 26 Jan 2011 04:16:32 +0000","from_user":"aprikip","id_str":"30116854940835840","metadata":{"result_type":"recent"},"to_user_id":null,"text":"yatex-mode\u3084haskell-mode\u306e\u3053\u3068\u3067\u3059\u306d\u3001\u308f\u304b\u308a\u307e\u3059\u3002","id":30116854940835840,"from_user_id":218059,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://sites.google.com/site/yorufukurou/&quot; rel=&quot;nofollow&quot;&gt;YoruFukurou&lt;/a&gt;"},{"from_user_id_str":"216363","profile_image_url":"http://a1.twimg.com/profile_images/72454310/Tim-Avatar_normal.png","created_at":"Wed, 26 Jan 2011 04:15:30 +0000","from_user":"dysinger","id_str":"30116594684264448","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell in Hawaii tonight for me... #fun","id":30116594684264448,"from_user_id":216363,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.nambu.com/&quot; rel=&quot;nofollow&quot;&gt;Nambu&lt;/a&gt;"},{"from_user_id_str":"1774820","profile_image_url":"http://a2.twimg.com/profile_images/61169291/dan_desert_thumb_normal.jpg","created_at":"Wed, 26 Jan 2011 04:13:36 +0000","from_user":"DanMil","id_str":"30116117682851840","metadata":{"result_type":"recent"},"to_user_id":1594784,"text":"@ojrac @chewedwire @tomheon Haskell isn't a language, it's a belief system.  A seductive one...","id":30116117682851840,"from_user_id":1774820,"to_user":"ojrac","geo":null,"iso_language_code":"en","to_user_id_str":"1594784","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"659256","profile_image_url":"http://a0.twimg.com/profile_images/746976711/angular-final_normal.jpg","created_at":"Wed, 26 Jan 2011 04:11:06 +0000","from_user":"djspiewak","id_str":"30115488931520512","metadata":{"result_type":"recent"},"to_user_id":null,"text":"One of the very nice things about Haskell as opposed to SML is the reduced proliferation of identifiers (e.g. andb, orb, etc). #typeclasses","id":30115488931520512,"from_user_id":659256,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 04:06:12 +0000","from_user":"listwarenet","id_str":"30114255890026496","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-cafe/84752-re-haskell-cafe-gpl-license-of-h-matrix-and-prelude-numeric.html Re: Haskell-c","id":30114255890026496,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"1594784","profile_image_url":"http://a2.twimg.com/profile_images/378515773/square-profile_normal.jpg","created_at":"Wed, 26 Jan 2011 04:01:29 +0000","from_user":"ojrac","id_str":"30113067333324800","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @tomheon: @ojrac @chewedwire Don't worry, learning Haskell will not give you any clear idea what monad means.","id":30113067333324800,"from_user_id":1594784,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"207589736","profile_image_url":"http://a3.twimg.com/profile_images/1225527428/headshot_1_normal.jpg","created_at":"Wed, 26 Jan 2011 04:00:13 +0000","from_user":"ashleevelazq101","id_str":"30112747555397632","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Federal investigation finds safety violations at The Acadia Hospital: By Meg Haskell, BDN Staff The investigatio... http://bit.ly/dONnpn","id":30112747555397632,"from_user_id":207589736,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Wed, 26 Jan 2011 03:58:00 +0000","from_user":"Hackage","id_str":"30112192346984448","metadata":{"result_type":"recent"},"to_user_id":null,"text":"streams 0.4, added by EdwardKmett: Various Haskell 2010 stream comonads http://bit.ly/idBkPe","id":30112192346984448,"from_user_id":17671137,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"17489366","profile_image_url":"http://a3.twimg.com/sticky/default_profile_images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 03:58:00 +0000","from_user":"aapnoot","id_str":"30112191881420800","metadata":{"result_type":"recent"},"to_user_id":null,"text":"streams 0.4, added by EdwardKmett: Various Haskell 2010 stream comonads http://bit.ly/idBkPe","id":30112191881420800,"from_user_id":17489366,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"8530482","profile_image_url":"http://a2.twimg.com/profile_images/137867266/n608671563_7396_normal.jpg","created_at":"Wed, 26 Jan 2011 03:50:12 +0000","from_user":"jeffmclamb","id_str":"30110229207187456","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Angel - daemon to run and monitor processes like daemontools or god, written in Haskell http://ff.im/-wNyLk","id":30110229207187456,"from_user_id":8530482,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://friendfeed.com&quot; rel=&quot;nofollow&quot;&gt;FriendFeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 03:46:01 +0000","from_user":"tomheon","id_str":"30109174645919744","metadata":{"result_type":"recent"},"to_user_id":1594784,"text":"@ojrac @chewedwire Don't worry, learning Haskell will not give you any clear idea what monad means.","id":30109174645919744,"from_user_id":177539201,"to_user":"ojrac","geo":null,"iso_language_code":"en","to_user_id_str":"1594784","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"1594784","profile_image_url":"http://a2.twimg.com/profile_images/378515773/square-profile_normal.jpg","created_at":"Wed, 26 Jan 2011 03:44:34 +0000","from_user":"ojrac","id_str":"30108808684503040","metadata":{"result_type":"recent"},"to_user_id":128028225,"text":"@chewedwire @tomheon Why are you making me curious about Haskell? I LIKE not knowing what monad means!!","id":30108808684503040,"from_user_id":1594784,"to_user":"chewedwire","geo":null,"iso_language_code":"en","to_user_id_str":"128028225","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"23750094","profile_image_url":"http://a0.twimg.com/profile_images/951373780/Moeinthecar_normal.jpg","created_at":"Wed, 26 Jan 2011 03:41:54 +0000","from_user":"shokalshab","id_str":"30108140443795456","metadata":{"result_type":"recent"},"to_user_id":null,"text":"I'm at Magnitude Cheer @ Gymnastics Olympica USA (7735 Haskell Ave., btw Saticoy &amp; Strathern, Van Nuys) http://4sq.com/gmXfaL","id":30108140443795456,"from_user_id":23750094,"geo":null,"iso_language_code":"en","place":{"id":"4e4a2a2f86cb2946","type":"poi","full_name":"Gymnastics Olympica USA, Van Nuys"},"to_user_id_str":null,"source":"&lt;a href=&quot;http://foursquare.com&quot; rel=&quot;nofollow&quot;&gt;foursquare&lt;/a&gt;"},{"from_user_id_str":"8135112","profile_image_url":"http://a0.twimg.com/profile_images/1165240350/LIMITED_normal.jpg","created_at":"Wed, 26 Jan 2011 03:41:35 +0000","from_user":"Claricei","id_str":"30108059208515584","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @kristenmchugh22: @KeithOlbermann Ryan looks like Jughead w/o the hat. And sounds as mealy-mouthed as Eddie Haskell.","id":30108059208515584,"from_user_id":8135112,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:40:02 +0000","from_user":"chewedwire","id_str":"30107670367182848","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon Cool, I'll take a look. I feel like I should mention this: http://bit.ly/hVstDM","id":30107670367182848,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"8679778","profile_image_url":"http://a3.twimg.com/profile_images/1195318056/me_nyc_12_18_10_icon_normal.jpg","created_at":"Wed, 26 Jan 2011 03:38:42 +0000","from_user":"kristenmchugh22","id_str":"30107332381777920","metadata":{"result_type":"recent"},"to_user_id":756269,"text":"@KeithOlbermann Ryan looks like Jughead w/o the hat. And sounds as mealy-mouthed as Eddie Haskell.","id":30107332381777920,"from_user_id":8679778,"to_user":"KeithOlbermann","geo":null,"iso_language_code":"en","to_user_id_str":"756269","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"103316559","profile_image_url":"http://a1.twimg.com/profile_images/1179458751/bc3beab4-d59d-4e78-b13b-50747986cfa2_normal.png","created_at":"Wed, 26 Jan 2011 03:36:15 +0000","from_user":"cityslikr","id_str":"30106719153557504","metadata":{"result_type":"recent"},"to_user_id":null,"text":"&quot;Social safety net into a hammock.&quot; So says Eddie Haskell with the GOP response. #SOTU","id":30106719153557504,"from_user_id":103316559,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://blackberry.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Twitter for BlackBerry\u00ae&lt;/a&gt;"},{"from_user_id_str":"169063143","profile_image_url":"http://a0.twimg.com/profile_images/1160506212/9697_1_normal.gif","created_at":"Wed, 26 Jan 2011 03:31:52 +0000","from_user":"wrkforce_safety","id_str":"30105614919143424","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Federal investigation finds safety violations at The Acadia Hospital: By Meg Haskell, BDN Staff The investigatio... http://bit.ly/gA60C1","id":30105614919143424,"from_user_id":169063143,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 03:29:40 +0000","from_user":"tomheon","id_str":"30105060960632832","metadata":{"result_type":"recent"},"to_user_id":128028225,"text":"@chewedwire Great book on Haskell: http://oreilly.com/catalog/9780596514983","id":30105060960632832,"from_user_id":177539201,"to_user":"chewedwire","geo":null,"iso_language_code":"en","to_user_id_str":"128028225","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"782692","profile_image_url":"http://a0.twimg.com/profile_images/1031304589/Profile.2007.1_normal.jpg","created_at":"Wed, 26 Jan 2011 03:29:19 +0000","from_user":"turnageb","id_str":"30104974591533057","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @ovillalon: Paul Ryan solves the mystery of whatever happened to Eddie Haskell. #sotu","id":30104974591533057,"from_user_id":782692,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:28:04 +0000","from_user":"chewedwire","id_str":"30104657267265536","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon I always loved the pattern matching in SML and it looks like Haskell is MUCH better at it. I'm messing around now at tryhaskell.org","id":30104657267265536,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"12834082","profile_image_url":"http://a3.twimg.com/profile_images/1083036140/mugshot_normal.png","created_at":"Wed, 26 Jan 2011 03:28:01 +0000","from_user":"ovillalon","id_str":"30104647213518848","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Paul Ryan solves the mystery of whatever happened to Eddie Haskell. #sotu","id":30104647213518848,"from_user_id":12834082,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"13540930","profile_image_url":"http://a1.twimg.com/profile_images/1205312219/23467_350321383101_821143101_5114147_3010041_n_normal.jpg","created_at":"Wed, 26 Jan 2011 03:26:02 +0000","from_user":"goodfox","id_str":"30104146455560192","metadata":{"result_type":"recent"},"to_user_id":10226179,"text":"@billykeene22 Bordeaux is one of my heroes. I was so excited when he accepted the invitation to campus. He's been a great friend to Haskell.","id":30104146455560192,"from_user_id":13540930,"to_user":"billykeene22","geo":null,"iso_language_code":"en","to_user_id_str":"10226179","source":"&lt;a href=&quot;http://www.ubertwitter.com/bb/download.php&quot; rel=&quot;nofollow&quot;&gt;\u00dcberTwitter&lt;/a&gt;"},{"from_user_id_str":"18616016","profile_image_url":"http://a2.twimg.com/profile_images/1173522726/214397343_normal.jpg","created_at":"Wed, 26 Jan 2011 03:25:18 +0000","from_user":"josej30","id_str":"30103962313031681","metadata":{"result_type":"recent"},"to_user_id":14870909,"text":"@cris7ian Ahh bueno multiparadigma ya es respetable :) Empezar\u00e9 a explotar la parte funcional de los lenguajes ahora #Haskell","id":30103962313031681,"from_user_id":18616016,"to_user":"Cris7ian","geo":null,"iso_language_code":"es","to_user_id_str":"14870909","source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"14870909","profile_image_url":"http://a2.twimg.com/profile_images/1176930429/oso_yo_normal.png","created_at":"Wed, 26 Jan 2011 03:23:43 +0000","from_user":"Cris7ian","id_str":"30103562360983553","metadata":{"result_type":"recent"},"to_user_id":18616016,"text":"@josej30 hahaha no, es multiparadigma y es bastante lazy. Nothing like haskell, pero s\u00ed, el de Flash","id":30103562360983553,"from_user_id":14870909,"to_user":"josej30","geo":null,"iso_language_code":"es","to_user_id_str":"18616016","source":"&lt;a href=&quot;http://www.echofon.com/&quot; rel=&quot;nofollow&quot;&gt;Echofon&lt;/a&gt;"},{"from_user_id_str":"2421643","profile_image_url":"http://a0.twimg.com/profile_images/1190361665/ernestgrumbles-17_normal.jpg","created_at":"Wed, 26 Jan 2011 03:20:24 +0000","from_user":"ernestgrumbles","id_str":"30102730756333568","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Wow... WolframAlpha did not know who Eddie Haskell is.  Guess I'll never use that &quot;knowledge engine&quot; again.","id":30102730756333568,"from_user_id":2421643,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"128028225","profile_image_url":"http://a1.twimg.com/profile_images/1224994593/Coding_Drunk_normal.jpg","created_at":"Wed, 26 Jan 2011 03:14:21 +0000","from_user":"chewedwire","id_str":"30101204428132352","metadata":{"result_type":"recent"},"to_user_id":177539201,"text":"@tomheon How is Haskell better/different from CL or Scheme? I honestly don't know, although I'm becoming more curious.","id":30101204428132352,"from_user_id":128028225,"to_user":"tomheon","geo":null,"iso_language_code":"en","to_user_id_str":"177539201","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"13540930","profile_image_url":"http://a1.twimg.com/profile_images/1205312219/23467_350321383101_821143101_5114147_3010041_n_normal.jpg","created_at":"Wed, 26 Jan 2011 03:06:54 +0000","from_user":"goodfox","id_str":"30099329809129473","metadata":{"result_type":"recent"},"to_user_id":null,"text":"A day of vision &amp; speeches. #SOTU now. And a wonderful Haskell Convocation address earlier today by Sinte Gleske President Lionel Bordeaux.","id":30099329809129473,"from_user_id":13540930,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.ubertwitter.com/bb/download.php&quot; rel=&quot;nofollow&quot;&gt;\u00dcberTwitter&lt;/a&gt;"},{"from_user_id_str":"119185220","profile_image_url":"http://a0.twimg.com/profile_images/1089027228/dfg_normal.jpg","created_at":"Wed, 26 Jan 2011 03:03:38 +0000","from_user":"LaLiciouz_03","id_str":"30098510623805440","metadata":{"result_type":"recent"},"to_user_id":null,"text":"The Game with the girl room 330 Haskell follow us...","id":30098510623805440,"from_user_id":119185220,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"18616016","profile_image_url":"http://a2.twimg.com/profile_images/1173522726/214397343_normal.jpg","created_at":"Wed, 26 Jan 2011 02:57:25 +0000","from_user":"josej30","id_str":"30096946144215040","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Voy a extra\u00f1ar Haskell cuando regrese al mundo imperativo. Hay alg\u00fan lenguaje imperativo que tenga este poder funcional? #ci3661","id":30096946144215040,"from_user_id":18616016,"geo":null,"iso_language_code":"es","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"17671137","profile_image_url":"http://a2.twimg.com/profile_images/290264834/Haskell-logo-outer-glow_normal.png","created_at":"Wed, 26 Jan 2011 02:55:32 +0000","from_user":"Hackage","id_str":"30096471814574080","metadata":{"result_type":"recent"},"to_user_id":null,"text":"comonad-transformers 0.9.0, added by EdwardKmett: Haskell 98 comonad transformers http://bit.ly/h6xIsf","id":30096471814574080,"from_user_id":17671137,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&gt;twitterfeed&lt;/a&gt;"},{"from_user_id_str":"177539201","profile_image_url":"http://a0.twimg.com/profile_images/1178368800/img_normal.jpeg","created_at":"Wed, 26 Jan 2011 02:48:12 +0000","from_user":"tomheon","id_str":"30094626920603649","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Every time I look at Haskell I love it more.","id":30094626920603649,"from_user_id":177539201,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"60792568","profile_image_url":"http://a0.twimg.com/profile_images/1203647517/glenda-flash_normal.jpg","created_at":"Wed, 26 Jan 2011 02:40:42 +0000","from_user":"r_takaishi","id_str":"30092735935422464","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell\u3088\u308aD\u8a00\u8a9e\u304c\u4e0a\u3068\u306f\u601d\u308f\u306a\u304b\u3063\u305f\uff0e http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html","id":30092735935422464,"from_user_id":60792568,"geo":null,"iso_language_code":"ja","to_user_id_str":null,"source":"&lt;a href=&quot;http://twmode.sf.net/&quot; rel=&quot;nofollow&quot;&gt;twmode&lt;/a&gt;"},{"from_user_id_str":"160145510","profile_image_url":"http://a0.twimg.com/profile_images/1218108166/going_galt_normal.jpg","created_at":"Wed, 26 Jan 2011 02:39:31 +0000","from_user":"wtp1787","id_str":"30092439653974018","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @KLSouth: Eddie Haskell Goes to Washington...  &quot;You look really nice tonight, Ms Cleaver&quot;","id":30092439653974018,"from_user_id":160145510,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"96616016","profile_image_url":"http://a1.twimg.com/profile_images/1196978169/Picture0002_normal.jpg","created_at":"Wed, 26 Jan 2011 02:39:20 +0000","from_user":"MelissaRNMBA","id_str":"30092392203816960","metadata":{"result_type":"recent"},"to_user_id":14862975,"text":"@KLSouth At least Eddie Haskell was entertaining.","id":30092392203816960,"from_user_id":96616016,"to_user":"KLSouth","geo":null,"iso_language_code":"en","to_user_id_str":"14862975","source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"14862975","profile_image_url":"http://a0.twimg.com/profile_images/421596393/kls_4_normal.JPG","created_at":"Wed, 26 Jan 2011 02:38:29 +0000","from_user":"KLSouth","id_str":"30092178327871489","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Eddie Haskell Goes to Washington...  &quot;You look really nice tonight, Ms Cleaver&quot;","id":30092178327871489,"from_user_id":14862975,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 02:36:17 +0000","from_user":"listwarenet","id_str":"30091626869161984","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-beginners/84641-haskell-beginners-wildcards-in-expressions.html Haskell-beginners -  Wild","id":30091626869161984,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"24538048","profile_image_url":"http://a2.twimg.com/profile_images/1117267605/rope_normal.jpg","created_at":"Wed, 26 Jan 2011 02:23:14 +0000","from_user":"dbph","id_str":"30088341030440960","metadata":{"result_type":"recent"},"to_user_id":null,"text":"RT @dnene: Skilled Calisthenics. Haskell code that outputs python which spits ruby which emits the haskell source. http://j.mp/YlQUL via @mfeathers","id":30088341030440960,"from_user_id":24538048,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"},{"from_user_id_str":"158951567","profile_image_url":"http://a3.twimg.com/profile_images/962721419/Logo_3_normal.jpg","created_at":"Wed, 26 Jan 2011 01:58:31 +0000","from_user":"YubaVetTech","id_str":"30082124207886336","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Dr. Haskell has just been awarded the prestigious Hayward Award for \u2018Excellence in Education\u2019. This award honors... http://fb.me/QgQCxd74","id":30082124207886336,"from_user_id":158951567,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.facebook.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Facebook&lt;/a&gt;"},{"from_user_id_str":"158951567","profile_image_url":"http://a3.twimg.com/profile_images/962721419/Logo_3_normal.jpg","created_at":"Wed, 26 Jan 2011 01:56:04 +0000","from_user":"YubaVetTech","id_str":"30081505476743168","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Dr. Haskell has just been awarded the prestigous Haward Award for Excellence in Education. This award honors... http://fb.me/PC9mYmCR","id":30081505476743168,"from_user_id":158951567,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://www.facebook.com/twitter&quot; rel=&quot;nofollow&quot;&gt;Facebook&lt;/a&gt;"},{"from_user_id_str":"2331498","profile_image_url":"http://a3.twimg.com/profile_images/494632120/me_normal.jpg","created_at":"Wed, 26 Jan 2011 01:43:50 +0000","from_user":"Verus","id_str":"30078427155406848","metadata":{"result_type":"recent"},"to_user_id":79273052,"text":"@kami_joe \u3044\u3084\uff0c\u8ab2\u984c\u306f\u89e3\u6c7a\u5bfe\u8c61(\u30d1\u30ba\u30eb\u3068\u304b)\u3092\u4e0e\u3048\u3089\u308c\u3066\uff0c\u554f\u984c\u5b9a\u7fa9\u3068\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0(\u6307\u5b9a\u8a00\u8a9e\u306fC++\u3082\u3057\u304f\u306fJava)\u3068\u3044\u3046\u3044\u308f\u3070\u666e\u901a\u306a\u8ab2\u984c\u3067\u306f\u3042\u308b\u3093\u3060\u3051\u3069\uff0e\u95a2\u6570\u578b\u8a00\u8a9e\u306fHaskell\u306e\u6388\u696d\u304c\u307e\u305f\u5225\u306b\u3042\u308b\u306e\uff0e","id":30078427155406848,"from_user_id":2331498,"to_user":"kami_joe","geo":null,"iso_language_code":"ja","to_user_id_str":"79273052","source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"79151233","profile_image_url":"http://a2.twimg.com/a/1295051201/images/default_profile_2_normal.png","created_at":"Wed, 26 Jan 2011 01:40:37 +0000","from_user":"cz_newdrafts","id_str":"30077617361125376","metadata":{"result_type":"recent"},"to_user_id":null,"text":"Haskell programming language http://bit.ly/gpPAwB","id":30077617361125376,"from_user_id":79151233,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://tommorris.org/&quot; rel=&quot;nofollow&quot;&gt;tommorris' hacksample&lt;/a&gt;"},{"from_user_id_str":"2331498","profile_image_url":"http://a3.twimg.com/profile_images/494632120/me_normal.jpg","created_at":"Wed, 26 Jan 2011 01:02:57 +0000","from_user":"Verus","id_str":"30068139416879104","metadata":{"result_type":"recent"},"to_user_id":9252720,"text":"@shukukei Java\u3068C\u306f\u3042\u308b\u7a0b\u5ea6\u66f8\u3051\u3066\u3042\u305f\u308a\u307e\u3048\u306a\u3068\u3053\u308d\u304c\u3042\u308b\u304b\u3089\u306a\u30fc\uff0ePython\u306f\u500b\u4eba\u7684\u306b\u611f\u899a\u304c\u5408\u308f\u306a\u3044\uff0e\u611f\u899a\u306a\u306e\u3067\uff0c\u3082\u3046\u3069\u3046\u3057\u3088\u3046\u3082\u306a\u3044\uff57 \u3044\u307e\u306fScala\u3068Haskell\u3092\u3082\u3063\u3068\u6975\u3081\u305f\u3044\u3068\u3053\u308d\uff0e","id":30068139416879104,"from_user_id":2331498,"to_user":"shukukei","geo":null,"iso_language_code":"ja","to_user_id_str":"9252720","source":"&lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt;"},{"from_user_id_str":"2781460","profile_image_url":"http://a0.twimg.com/profile_images/82526625/.joeyicon_normal.jpg","created_at":"Wed, 26 Jan 2011 01:02:35 +0000","from_user":"joeyhess","id_str":"30068046538219520","metadata":{"result_type":"recent"},"to_user_id":null,"text":"just figured out that I can use parameterized types to remove a dependency loop in git-annex's type definitions. whee #haskell","id":30068046538219520,"from_user_id":2781460,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://identi.ca&quot; rel=&quot;nofollow&quot;&gt;identica&lt;/a&gt;"},{"from_user_id_str":"144546280","profile_image_url":"http://a1.twimg.com/a/1295051201/images/default_profile_1_normal.png","created_at":"Wed, 26 Jan 2011 00:54:22 +0000","from_user":"listwarenet","id_str":"30065977920061440","metadata":{"result_type":"recent"},"to_user_id":null,"text":"http://www.listware.net/201101/haskell-beginners/84466-haskell-beginners-bytestring-question.html Haskell-beginners -  Bytestrin","id":30065977920061440,"from_user_id":144546280,"geo":null,"iso_language_code":"no","to_user_id_str":null,"source":"&lt;a href=&quot;http://1e10.org/cloud/&quot; rel=&quot;nofollow&quot;&gt;1e10&lt;/a&gt;"},{"from_user_id_str":"1291845","profile_image_url":"http://a0.twimg.com/profile_images/1225743404/ThinOxygen-small-opaque-solidarity_normal.png","created_at":"Wed, 26 Jan 2011 00:52:07 +0000","from_user":"_aaron_","id_str":"30065412242669568","metadata":{"result_type":"recent"},"to_user_id":null,"text":"wanted: librly licensed high level native compiled lang with min runtime (otherwise cobra/mono would be perfect) for win. lua? haskell? ooc?","id":30065412242669568,"from_user_id":1291845,"geo":null,"iso_language_code":"en","to_user_id_str":null,"source":"&lt;a href=&quot;http://twitter.com/&quot;&gt;web&lt;/a&gt;"}],"max_id":30120402839666689,"since_id":0,"refresh_url":"?since_id=30120402839666689&q=haskell","next_page":"?page=2&max_id=30120402839666689&rpp=50&q=haskell","results_per_page":50,"page":1,"completed_in":0.291696,"since_id_str":"0","max_id_str":"30120402839666689","query":"haskell"}
diff --git a/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/ReadInt.hs b/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/ReadInt.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/ReadInt.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE BangPatterns #-}
+
+-- Copyright     : Erik de Castro Lopo <erikd@mega-nerd.com>
+-- License       : BSD3
+
+module Network.Wai.Handler.Warp.ReadInt (
+    readInt
+  , readInt64
+  ) where
+
+-- This function lives in its own file because the MagicHash pragma interacts
+-- poorly with the CPP pragma.
+
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as S
+import Data.Int (Int64)
+import GHC.Prim
+import GHC.Types
+import GHC.Word
+
+{-# INLINE readInt #-}
+readInt :: Integral a => ByteString -> a
+readInt bs = fromIntegral $ readInt64 bs
+
+-- This function is used to parse the Content-Length field of HTTP headers and
+-- is a performance hot spot. It should only be replaced with something
+-- significantly and provably faster.
+--
+-- It needs to be able work correctly on 32 bit CPUs for file sizes > 2G so we
+-- use Int64 here and then make a generic 'readInt' that allows conversion to
+-- Int and Integer.
+
+{-# NOINLINE readInt64 #-}
+readInt64 :: ByteString -> Int64
+readInt64 bs = S.foldl' (\ !i !c -> i * 10 + fromIntegral (mhDigitToInt c)) 0
+             $ S.takeWhile isDigit bs
+
+data Table = Table !Addr#
+
+{-# NOINLINE mhDigitToInt #-}
+mhDigitToInt :: Word8 -> Int
+#if MIN_VERSION_base(4,16,0)
+mhDigitToInt (W8# i) = I# (word2Int# (word8ToWord# (indexWord8OffAddr# addr (word2Int# (word8ToWord# i)))))
+#else
+mhDigitToInt (W8# i) = I# (word2Int# (indexWord8OffAddr# addr (word2Int# i)))
+#endif
+  where
+    !(Table addr) = table
+    table :: Table
+    table = Table
+        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+        \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
+
+isDigit :: Word8 -> Bool
+isDigit w = w >= 48 && w <= 57
diff --git a/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/RequestHeader.hs b/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/RequestHeader.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/warp-3.0.1.1/Network/Wai/Handler/Warp/RequestHeader.hs
@@ -0,0 +1,172 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE BangPatterns #-}
+
+module Network.Wai.Handler.Warp.RequestHeader (
+      parseHeaderLines
+    , parseByteRanges
+    ) where
+
+import Control.Exception (Exception, throwIO)
+import Control.Monad (when)
+import Data.Typeable (Typeable)
+import qualified Data.ByteString as S
+import qualified Data.ByteString.Char8 as B (unpack, readInteger)
+import Data.ByteString.Internal (ByteString(..), memchr)
+import qualified Data.CaseInsensitive as CI
+import Data.Word (Word8)
+import Foreign.ForeignPtr (withForeignPtr)
+import Foreign.Ptr (Ptr, plusPtr, minusPtr, nullPtr)
+import Foreign.Storable (peek)
+import qualified Network.HTTP.Types as H
+-- import Network.Wai.Handler.Warp.Types
+import qualified Network.HTTP.Types.Header as HH
+-- $setup
+-- >>> :set -XOverloadedStrings
+
+data InvalidRequest = NotEnoughLines [String]
+                    | BadFirstLine String
+                    | NonHttp
+                    | IncompleteHeaders
+                    | ConnectionClosedByPeer
+                    | OverLargeHeader
+                    deriving (Eq, Typeable, Show)
+
+instance Exception InvalidRequest
+
+----------------------------------------------------------------
+
+parseHeaderLines :: [ByteString]
+                 -> IO (H.Method
+                       ,ByteString  --  Path
+                       ,ByteString  --  Path, parsed
+                       ,ByteString  --  Query
+                       ,H.HttpVersion
+                       ,H.RequestHeaders
+                       )
+parseHeaderLines [] = throwIO $ NotEnoughLines []
+parseHeaderLines (firstLine:otherLines) = do
+    (method, path', query, httpversion) <- parseRequestLine firstLine
+    let path = H.extractPath path'
+        hdr = map parseHeader otherLines
+    return (method, path', path, query, httpversion, hdr)
+
+----------------------------------------------------------------
+
+-- |
+--
+-- >>> parseRequestLine "GET / HTTP/1.1"
+-- ("GET","/","",HTTP/1.1)
+-- >>> parseRequestLine "POST /cgi/search.cgi?key=foo HTTP/1.0"
+-- ("POST","/cgi/search.cgi","?key=foo",HTTP/1.0)
+-- >>> parseRequestLine "GET "
+-- *** Exception: Warp: Invalid first line of request: "GET "
+-- >>> parseRequestLine "GET /NotHTTP UNKNOWN/1.1"
+-- *** Exception: Warp: Request line specified a non-HTTP request
+parseRequestLine :: ByteString
+                 -> IO (H.Method
+                       ,ByteString -- Path
+                       ,ByteString -- Query
+                       ,H.HttpVersion)
+parseRequestLine requestLine@(PS fptr off len) = withForeignPtr fptr $ \ptr -> do
+    when (len < 14) $ throwIO baderr
+    let methodptr = ptr `plusPtr` off
+        limptr = methodptr `plusPtr` len
+        lim0 = fromIntegral len
+
+    pathptr0 <- memchr methodptr 32 lim0 -- ' '
+    when (pathptr0 == nullPtr || (limptr `minusPtr` pathptr0) < 11) $
+        throwIO baderr
+    let pathptr = pathptr0 `plusPtr` 1
+        lim1 = fromIntegral (limptr `minusPtr` pathptr0)
+
+    httpptr0 <- memchr pathptr 32 lim1 -- ' '
+    when (httpptr0 == nullPtr || (limptr `minusPtr` httpptr0) < 9) $
+        throwIO baderr
+    let httpptr = httpptr0 `plusPtr` 1
+        lim2 = fromIntegral (httpptr0 `minusPtr` pathptr)
+
+    checkHTTP httpptr
+    !hv <- httpVersion httpptr
+    queryptr <- memchr pathptr 63 lim2 -- '?'
+
+    let !method = bs ptr methodptr pathptr0
+        !path
+          | queryptr == nullPtr = bs ptr pathptr httpptr0
+          | otherwise           = bs ptr pathptr queryptr
+        !query
+          | queryptr == nullPtr = S.empty
+          | otherwise           = bs ptr queryptr httpptr0
+
+    return (method,path,query,hv)
+  where
+    baderr = BadFirstLine $ B.unpack requestLine
+    check :: Ptr Word8 -> Int -> Word8 -> IO ()
+    check p n w = do
+        w0 <- peek $ p `plusPtr` n
+        when (w0 /= w) $ throwIO NonHttp
+    checkHTTP httpptr = do
+        check httpptr 0 72 -- 'H'
+        check httpptr 1 84 -- 'T'
+        check httpptr 2 84 -- 'T'
+        check httpptr 3 80 -- 'P'
+        check httpptr 4 47 -- '/'
+        check httpptr 6 46 -- '.'
+    httpVersion httpptr = do
+        major <- peek $ httpptr `plusPtr` 5
+        minor <- peek $ httpptr `plusPtr` 7
+        return $ if major == (49 :: Word8) && minor == (49 :: Word8) then
+            H.http11
+          else
+            H.http10
+    bs ptr p0 p1 = PS fptr o l
+      where
+        o = p0 `minusPtr` ptr
+        l = p1 `minusPtr` p0
+
+----------------------------------------------------------------
+
+-- |
+--
+-- >>> parseHeader "Content-Length:47"
+-- ("Content-Length","47")
+-- >>> parseHeader "Accept-Ranges: bytes"
+-- ("Accept-Ranges","bytes")
+-- >>> parseHeader "Host:  example.com:8080"
+-- ("Host","example.com:8080")
+-- >>> parseHeader "NoSemiColon"
+-- ("NoSemiColon","")
+
+parseHeader :: ByteString -> H.Header
+parseHeader s =
+    let (k, rest) = S.break (== 58) s -- ':'
+        rest' = S.dropWhile (\c -> c == 32 || c == 9) $ S.drop 1 rest
+     in (CI.mk k, rest')
+
+parseByteRanges :: S.ByteString -> Maybe HH.ByteRanges
+parseByteRanges bs1 = do
+    bs2 <- stripPrefix "bytes=" bs1
+    (r, bs3) <- range bs2
+    ranges (r:) bs3
+  where
+    range bs2 =
+        case stripPrefix "-" bs2 of
+            Just bs3 -> do
+                (i, bs4) <- B.readInteger bs3
+                Just (HH.ByteRangeSuffix i, bs4)
+            Nothing -> do
+                (i, bs3) <- B.readInteger bs2
+                bs4 <- stripPrefix "-" bs3
+                case B.readInteger bs4 of
+                    Nothing -> Just (HH.ByteRangeFrom i, bs4)
+                    Just (j, bs5) -> Just (HH.ByteRangeFromTo i j, bs5)
+    ranges front bs3 =
+        case stripPrefix "," bs3 of
+            Nothing -> Just (front [])
+            Just bs4 -> do
+                (r, bs5) <- range bs4
+                ranges (front . (r:)) bs5
+
+    stripPrefix x y
+        | x `S.isPrefixOf` y = Just (S.drop (S.length x) y)
+        | otherwise = Nothing
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,136 @@
+# 0.14.4
+
+* Fix a segmentation fault when built against `text-2.0`
+* Restructure project to allow more convenient usage of benchmark suite
+* Allow benchmarks to build with GHC 9.2
+
+# 0.14.3
+
+* Support for GHC 9.2.1
+
+# 0.14.2
+
+* Support for GHC 9.2.1
+
+# 0.14.1
+
+* Added `Data.Attoparsec.ByteString.getChunk`.
+
+# 0.14.0
+
+* Added `Data.Attoparsec.ByteString.takeWhileIncluding`.
+* Make `Data.Attoparsec.{Text,ByteString}.Lazy.parseOnly` accept lazy input.
+
+# 0.13.2.1
+
+* Improved performance of `Data.Attoparsec.Text.asciiCI`
+
+# 0.13.2.0
+
+* `pure` is now strict in `Position`
+
+# 0.13.1.0
+
+* `runScanner` now correctly returns the final state
+  (https://github.com/bos/attoparsec/issues/105).
+* `Parser`, `ZeptoT`, `Buffer`, and `More` now expose `Semigroup` instances.
+* `Parser`, and `ZeptoT` now expose `MonadFail` instances.
+
+# 0.13.0.2
+
+* Restore the fast specialised character set implementation for Text
+* Move testsuite from test-framework to tasty
+* Performance optimization of takeWhile and takeWhile1
+
+# 0.13.0.1
+
+* Fixed a bug in the implementations of inClass and notInClass for
+  Text (https://github.com/bos/attoparsec/issues/103)
+
+# 0.13.0.0
+
+* Made the parser type in the Zepto module a monad transformer
+  (needed by aeson's string unescaping parser).
+
+# 0.12.1.6
+
+* Fixed a case folding bug in the ByteString version of stringCI.
+
+# 0.12.1.5
+
+* Fixed an indexing bug in the new Text implementation of string,
+  reported by Michel Boucey.
+
+# 0.12.1.4
+
+* Fixed a case where the string parser would consume an unnecessary
+  amount of input before failing a match, when it could bail much
+  earlier (https://github.com/bos/attoparsec/issues/97)
+
+* Added more context to error messages
+  (https://github.com/bos/attoparsec/pull/79)
+
+# 0.12.1.3
+
+* Fixed incorrect tracking of Text lengths
+  (https://github.com/bos/attoparsec/issues/80)
+
+# 0.12.1.2
+
+* Fixed the incorrect tracking of capacity if the initial buffer was
+  empty (https://github.com/bos/attoparsec/issues/75)
+
+# 0.12.1.1
+
+* Fixed a data corruption bug that occurred under some circumstances
+  if a buffer grew after prompting for more input
+  (https://github.com/bos/attoparsec/issues/74)
+
+# 0.12.1.0
+
+* Now compatible with GHC 7.9
+
+* Reintroduced the Chunk class, used by the parsers package
+
+# 0.12.0.0
+
+* A new internal representation makes almost all real-world parsers
+  faster, sometimes by big margins.  For example, parsing JSON data
+  with aeson is now up to 70% faster.  These performance improvements
+  also come with reduced memory consumption and some new capabilities.
+
+* The new match combinator gives both the result of a parse and the
+  input that it matched.
+
+* The test suite has doubled in size.  This made it possible to switch
+  to the new internal representation with a decent degree of
+  confidence that everything was more or less working.
+
+* The benchmark suite now contains a small family of benchmarks taken
+  from real-world uses of attoparsec.
+
+* A few types that ought to have been private now are.
+
+* A few obsolete modules and functions have been marked as deprecated.
+  They will be removed from the next major release.
+
+# 0.11.3.0
+
+* New function scientific is compatible with rational, but parses
+  integers more efficiently (https://github.com/bos/aeson/issues/198)
+
+# 0.11.2.0
+
+* The new Chunk typeclass allows for some code sharing with Ed
+  Kmett's parsers package: http://hackage.haskell.org/package/parsers
+
+* New function runScanner generalises scan to return the final state
+  of the scanner as well as the input consumed.
+
+# 0.11.1.0
+
+* New dependency: the scientific package.  This allows us to parse
+  numbers much more efficiently.
+
+* peekWord8', peekChar': new primitive parsers that allow
+  single-character lookahead.
diff --git a/examples/Atto_RFC2616.hs b/examples/Atto_RFC2616.hs
new file mode 100644
--- /dev/null
+++ b/examples/Atto_RFC2616.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE BangPatterns #-}
+
+module Main (main) where
+
+import Control.Applicative
+import Control.Exception (bracket)
+import Control.Monad (forM_)
+import Data.Attoparsec.ByteString
+import RFC2616
+import System.Environment
+import System.IO
+import qualified Data.ByteString.Char8 as B
+
+refill :: Handle -> IO B.ByteString
+refill h = B.hGet h (80*1024)
+
+listy :: FilePath -> Handle -> IO ()
+listy file h = do
+  r <- parseWith (refill h) (many request) =<< refill h
+  case r of
+    Fail _ _ msg -> hPutStrLn stderr $ file ++ ": " ++ msg
+    Done _ reqs  -> print (length reqs)
+
+incrementy :: FilePath -> Handle -> IO ()
+incrementy file h = go (0::Int) =<< refill h
+ where
+   go !n is = do
+     r <- parseWith (refill h) request is
+     case r of
+       Fail _ _ msg -> hPutStrLn stderr $ file ++ ": " ++ msg
+       Done bs _req
+           | B.null bs -> do
+              s <- refill h
+              if B.null s
+                then print (n+1)
+                else go (n+1) s
+           | otherwise -> go (n+1) bs
+
+main :: IO ()
+main = do
+  args <- getArgs
+  forM_ args $ \arg ->
+    bracket (openFile arg ReadMode) hClose $
+      -- listy arg
+      incrementy arg
diff --git a/examples/Makefile b/examples/Makefile
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,4 +1,4 @@
-CC := gcc
+CC := cc
 CFLAGS := -O3 -Wall
 # To make the code about 6% faster:
 # CFLAGS += -fwhole-program --combine
@@ -12,4 +12,8 @@
 clean:
 	rm -f *.hi *.o c-http
 
-vpath %.c $(HOME)/hg/http-parser
+http_parser.c: http_parser.h
+	curl -O https://raw.githubusercontent.com/joyent/http-parser/master/http_parser.c
+
+http_parser.h:
+	curl -O https://raw.githubusercontent.com/joyent/http-parser/master/http_parser.h
diff --git a/examples/Parsec_RFC2616.hs b/examples/Parsec_RFC2616.hs
--- a/examples/Parsec_RFC2616.hs
+++ b/examples/Parsec_RFC2616.hs
@@ -23,15 +23,16 @@
 token = satisfy $ \c -> S.notMember (fromEnum c) set
   where set = S.fromList . map fromEnum $ ['\0'..'\31'] ++ "()<>@,;:\\\"/[]?={} \t" ++ ['\128'..'\255']
 
+isHorizontalSpace :: Char -> Bool
 isHorizontalSpace c = c == ' ' || c == '\t'
 
 skipHSpaces :: Stream s m Char => ParsecT s u m ()
 skipHSpaces = skipMany1 (satisfy isHorizontalSpace)
 
 data Request = Request {
-      requestMethod   :: String
-    , requestUri      :: String
-    , requestProtocol :: String
+      _requestMethod   :: String
+    , _requestUri      :: String
+    , _requestProtocol :: String
     } deriving (Eq, Ord, Show)
 
 requestLine :: Stream s m Char => ParsecT s u m Request
@@ -47,8 +48,8 @@
 endOfLine = (string "\r\n" *> pure ()) <|> (char '\n' *> pure ())
 
 data Header = Header {
-      headerName  :: String
-    , headerValue :: [String]
+      _headerName  :: String
+    , _headerValue :: [String]
     } deriving (Eq, Ord, Show)
 
 messageHeader :: Stream s m Char => ParsecT s u m Header
@@ -61,14 +62,16 @@
 request :: Stream s m Char => ParsecT s u m (Request, [Header])
 request = (,) <$> requestLine <*> many messageHeader <* endOfLine
 
+listy :: FilePath -> IO ()
 listy arg = do
   r <- parseFromFile (many request) arg
   case r of
     Left err -> putStrLn $ arg ++ ": " ++ show err
     Right rs -> print (length rs)
 
+chunky :: FilePath -> IO ()
 chunky arg = bracket (openFile arg ReadMode) hClose $ \h ->
-               loop 0 =<< B.hGetContents h
+               loop (0::Int) =<< B.hGetContents h
  where
   loop !n bs
       | B.null bs = print n
diff --git a/examples/RFC2616.hs b/examples/RFC2616.hs
--- a/examples/RFC2616.hs
+++ b/examples/RFC2616.hs
@@ -5,86 +5,61 @@
       Header(..)
     , Request(..)
     , Response(..)
-    , isToken
-    , messageHeader
     , request
-    , requestLine
     , response
-    , responseLine
-    , lowerHeader
-    , lookupHeader
     ) where
 
-import Control.Applicative hiding (many)
-import Data.Attoparsec as P
-import qualified Data.Attoparsec.Char8 as P8
-import Data.Attoparsec.Char8 (char8, endOfLine, isDigit_w8)
+import Control.Applicative
+import Data.Attoparsec.ByteString as P
+import Data.Attoparsec.ByteString.Char8 (char8, endOfLine, isDigit_w8)
+import Data.ByteString (ByteString)
 import Data.Word (Word8)
-import qualified Data.ByteString.Char8 as B hiding (map)
-import qualified Data.ByteString as B (map)
+import Data.Attoparsec.ByteString.Char8 (isEndOfLine, isHorizontalSpace)
 
 isToken :: Word8 -> Bool
 isToken w = w <= 127 && notInClass "\0-\31()<>@,;:\\\"/[]?={} \t" w
 
 skipSpaces :: Parser ()
-skipSpaces = satisfy P8.isHorizontalSpace *> skipWhile P8.isHorizontalSpace
+skipSpaces = satisfy isHorizontalSpace *> skipWhile isHorizontalSpace
 
 data Request = Request {
-      requestMethod  :: !B.ByteString
-    , requestUri     :: !B.ByteString
-    , requestVersion :: !B.ByteString
+      requestMethod  :: ByteString
+    , requestUri     :: ByteString
+    , requestVersion :: ByteString
     } deriving (Eq, Ord, Show)
 
-httpVersion :: Parser B.ByteString
-httpVersion = string "HTTP/" *> P.takeWhile (\c -> isDigit_w8 c || c == 46)
+httpVersion :: Parser ByteString
+httpVersion = "HTTP/" *> P.takeWhile (\c -> isDigit_w8 c || c == 46)
 
 requestLine :: Parser Request
-requestLine = do
-  method <- P.takeWhile1 isToken <* char8 ' '
-  uri <- P.takeWhile1 (/=32) <* char8 ' '
-  version <- httpVersion <* endOfLine
-  return $! Request method uri version
+requestLine = Request <$> (takeWhile1 isToken <* char8 ' ')
+                      <*> (takeWhile1 (/=32) <* char8 ' ')
+                      <*> (httpVersion <* endOfLine)
 
 data Header = Header {
-      headerName  :: !B.ByteString
-    , headerValue :: [B.ByteString]
+      headerName  :: ByteString
+    , headerValue :: [ByteString]
     } deriving (Eq, Ord, Show)
 
 messageHeader :: Parser Header
-messageHeader = do
-  header <- P.takeWhile isToken <* char8 ':' <* skipWhile P8.isHorizontalSpace
-  body <- takeTill P8.isEndOfLine <* endOfLine
-  bodies <- many $ skipSpaces *> takeTill P8.isEndOfLine <* endOfLine
-  return $! Header header (body:bodies)
+messageHeader = Header
+  <$> (P.takeWhile isToken <* char8 ':' <* skipWhile isHorizontalSpace)
+  <*> ((:) <$> (takeTill isEndOfLine <* endOfLine)
+           <*> (many $ skipSpaces *> takeTill isEndOfLine <* endOfLine))
 
 request :: Parser (Request, [Header])
 request = (,) <$> requestLine <*> many messageHeader <* endOfLine
 
 data Response = Response {
-      responseVersion :: !B.ByteString
-    , responseCode    :: !B.ByteString
-    , responseMsg     :: !B.ByteString
+      responseVersion :: ByteString
+    , responseCode    :: ByteString
+    , responseMsg     :: ByteString
     } deriving (Eq, Ord, Show)
 
 responseLine :: Parser Response
-responseLine = do
-  version <- httpVersion <* char8 ' '
-  code <- P.takeWhile isDigit_w8 <* char8 ' '
-  msg <- P.takeTill P8.isEndOfLine <* endOfLine
-  return $! Response version code msg
+responseLine = Response <$> (httpVersion <* char8 ' ')
+                        <*> (P.takeWhile isDigit_w8 <* char8 ' ')
+                        <*> (takeTill isEndOfLine <* endOfLine)
 
 response :: Parser (Response, [Header])
 response = (,) <$> responseLine <*> many messageHeader <* endOfLine
-
-lowerHeader :: Header -> Header
-lowerHeader (Header n v) = Header (B.map toLower n) (map (B.map toLower) v)
-  where toLower w | w >= 65 && w <= 90 = w + 32
-                  | otherwise          = w
-
-lookupHeader :: B.ByteString -> [Header] -> [B.ByteString]
-lookupHeader k = go
-  where
-    go (Header n v:hs)
-      | k == n    = v
-      | otherwise = go hs
-    go _          = []
diff --git a/examples/TestRFC2616.hs b/examples/TestRFC2616.hs
deleted file mode 100644
--- a/examples/TestRFC2616.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-{-# LANGUAGE BangPatterns #-}
-import RFC2616
-import Control.Monad (forM_)
-import System.IO
-import Control.Exception (bracket)
-import System.Environment
-import qualified Data.ByteString.Char8 as B
-import Data.Attoparsec
-
-refill h = B.hGet h (4*1024)
-
-listy file h = do
-  r <- parseWith (refill h) (many request) =<< refill h
-  case r of
-    Fail _ _ msg -> hPutStrLn stderr $ file ++ ": " ++ msg
-    Done _ reqs  -> print (length reqs)
-  
-incrementy file h = go 0 =<< refill h
- where
-   go !n is = do
-     r <- parseWith (refill h) request is
-     case r of
-       Fail _ _ msg -> hPutStrLn stderr $ file ++ ": " ++ msg
-       Done bs _req
-           | B.null bs -> do
-              s <- refill h
-              if B.null s
-                then print (n+1)
-                else go (n+1) s
-           | otherwise -> go (n+1) bs
-  
-main = do
-  args <- getArgs
-  forM_ args $ \arg ->
-    bracket (openFile arg ReadMode) hClose $
-      -- listy arg
-      incrementy arg
diff --git a/examples/rfc2616.c b/examples/rfc2616.c
--- a/examples/rfc2616.c
+++ b/examples/rfc2616.c
@@ -1,21 +1,22 @@
 /*
- * This is a simple driver for Ryan Dahl's hand-bummed C http-parser
- * package.  It is intended to read one HTTP request after another
- * from a file, nothing more.
+ * This is a simple driver for the http-parser package.  It is
+ * intended to read one HTTP request after another from a file,
+ * nothing more.
  *
  * For "feature parity" with the Haskell code in RFC2616.hs, we
  * allocate and populate a simple structure describing each request,
  * since that's the sort of thing that many real applications would
  * themselves do and the library doesn't do this for us.
  *
- * For the http-parser source, see http://github.com/ry/http-parser/
+ * For the http-parser source, see
+ * https://github.com/joyent/http-parser/blob/master/http_parser.c
  */
 
 /*
  * Turn off this preprocessor symbol to have the callbacks do nothing
  * at all, which "improves performance" by about 50%.
  */
-#define LOOK_BUSY
+/*#define LOOK_BUSY*/
 
 #include <assert.h>
 #include <fcntl.h>
@@ -27,18 +28,18 @@
 #include <unistd.h>
 
 #include "http_parser.h"
-    
+
 struct http_string {
     size_t len;
     char value[0];
 };
-    
+
 struct http_header {
     struct http_string *name;
     struct http_string *value;
     struct http_header *next;
 };
-    
+
 struct http_request {
     struct http_string *method;
     struct http_string *uri;
@@ -49,7 +50,7 @@
     size_t count;
     struct http_request req;
 };
-  
+
 static void *xmalloc(size_t size)
 {
     void *ptr;
@@ -78,7 +79,7 @@
 	*dst = xstrdup(src, len, 0);
 	return;
     }
-    
+
     p = xstrdup((*dst)->value, (*dst)->len, len);
     memcpy(p->value + (*dst)->len, src, len);
     p->len += len;
@@ -98,7 +99,7 @@
 static int url(http_parser *p, const char *at, size_t len)
 {
 #ifdef LOOK_BUSY
-    struct data *data = p->data;    
+    struct data *data = p->data;
 
     xstrcat(&data->req.uri, at, len);
 #endif
@@ -119,7 +120,7 @@
 	hdr->name = xstrdup(at, len, 0);
 	hdr->value = NULL;
 	hdr->next = NULL;
-    
+
 	if (data->req.last != NULL)
 	    data->req.last->next = hdr;
 	data->req.last = hdr;
@@ -150,7 +151,7 @@
 
     free(data->req.method);
     free(data->req.uri);
-	
+
     for (hdr = data->req.headers; hdr != NULL; hdr = next) {
 	next = hdr->next;
 	free(hdr->name);
@@ -164,7 +165,7 @@
     data->req.headers = NULL;
     data->req.last = NULL;
 #endif
-    
+
     /* Bludgeon http_parser into understanding that we really want to
      * keep parsing after a request that in principle ought to close
      * the "connection". */
@@ -180,16 +181,21 @@
 static void parse(const char *path, int fd)
 {
     struct data data;
+    http_parser_settings s;
     http_parser p;
     ssize_t nread;
 
-    http_parser_init(&p, HTTP_REQUEST);
-    p.on_message_begin = begin;
-    p.on_url = url;
-    p.on_header_field = header_field;
-    p.on_header_value = header_value;
-    p.on_message_complete = complete;
+    memset(&s, 0, sizeof(s));
+    s.on_message_begin = begin;
+    s.on_url = url;
+    s.on_header_field = header_field;
+    s.on_header_value = header_value;
+    s.on_message_complete = complete;
+
     p.data = &data;
+
+    http_parser_init(&p, HTTP_REQUEST);
+
     data.count = 0;
     data.req.method = NULL;
     data.req.uri = NULL;
@@ -202,7 +208,7 @@
 
 	nread = read(fd, buf, sizeof(buf));
 
-	np = http_parser_execute(&p, buf, nread);
+	np = http_parser_execute(&p, &s, buf, nread);
 	if (np != nread) {
 	    fprintf(stderr, "%s: parse failed\n", path);
 	    break;
diff --git a/internal/Data/Attoparsec/ByteString/Buffer.hs b/internal/Data/Attoparsec/ByteString/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/ByteString/Buffer.hs
@@ -0,0 +1,157 @@
+{-# LANGUAGE BangPatterns #-}
+-- |
+-- Module      :  Data.Attoparsec.ByteString.Buffer
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  GHC
+--
+-- 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.
+
+module Data.Attoparsec.ByteString.Buffer
+    (
+      Buffer
+    , buffer
+    , unbuffer
+    , pappend
+    , length
+    , unsafeIndex
+    , substring
+    , unsafeDrop
+    ) where
+
+import Control.Exception (assert)
+import Data.ByteString.Internal (ByteString(..), memcpy, nullForeignPtr)
+import Data.Attoparsec.Internal.Fhthagn (inlinePerformIO)
+import Data.Attoparsec.Internal.Compat
+import Data.List (foldl1')
+import Data.Monoid as Mon (Monoid(..))
+import Data.Semigroup (Semigroup(..))
+import Data.Word (Word8)
+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
+import Foreign.Ptr (castPtr, plusPtr)
+import Foreign.Storable (peek, peekByteOff, poke, sizeOf)
+import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
+import Prelude hiding (length)
+
+-- If _cap is zero, this buffer is empty.
+data Buffer = Buf {
+      _fp  :: {-# UNPACK #-} !(ForeignPtr Word8)
+    , _off :: {-# UNPACK #-} !Int
+    , _len :: {-# UNPACK #-} !Int
+    , _cap :: {-# UNPACK #-} !Int
+    , _gen :: {-# UNPACK #-} !Int
+    }
+
+instance Show Buffer where
+    showsPrec p = showsPrec p . unbuffer
+
+-- | 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.
+buffer :: ByteString -> Buffer
+buffer bs = withPS bs $ \fp off len -> Buf fp off len len 0
+
+unbuffer :: Buffer -> ByteString
+unbuffer (Buf fp off len _ _) = mkPS fp off len
+
+instance Semigroup Buffer where
+    (Buf _ _ _ 0 _) <> b                    = b
+    a               <> (Buf _ _ _ 0 _)      = a
+    buf             <> (Buf fp off len _ _) = append buf fp off len
+
+instance Monoid Buffer where
+    mempty = Buf nullForeignPtr 0 0 0 0
+
+    mappend = (<>)
+
+    mconcat [] = Mon.mempty
+    mconcat xs = foldl1' mappend xs
+
+pappend :: Buffer -> ByteString -> Buffer
+pappend (Buf _ _ _ 0 _) bs  = buffer bs
+pappend buf             bs  = withPS bs $ \fp off len -> append buf fp off len
+
+append :: Buffer -> ForeignPtr a -> Int -> Int -> Buffer
+append (Buf fp0 off0 len0 cap0 gen0) !fp1 !off1 !len1 =
+  inlinePerformIO . withForeignPtr fp0 $ \ptr0 ->
+    withForeignPtr fp1 $ \ptr1 -> do
+      let genSize = sizeOf (0::Int)
+          newlen  = len0 + len1
+      gen <- if gen0 == 0
+             then return 0
+             else peek (castPtr ptr0)
+      if gen == gen0 && newlen <= cap0
+        then do
+          let newgen = gen + 1
+          poke (castPtr ptr0) newgen
+          memcpy (ptr0 `plusPtr` (off0+len0))
+                 (ptr1 `plusPtr` off1)
+                 (fromIntegral len1)
+          return (Buf fp0 off0 newlen cap0 newgen)
+        else do
+          let newcap = newlen * 2
+          fp <- mallocPlainForeignPtrBytes (newcap + genSize)
+          withForeignPtr fp $ \ptr_ -> do
+            let ptr    = ptr_ `plusPtr` genSize
+                newgen = 1
+            poke (castPtr ptr_) newgen
+            memcpy ptr (ptr0 `plusPtr` off0) (fromIntegral len0)
+            memcpy (ptr `plusPtr` len0) (ptr1 `plusPtr` off1)
+                   (fromIntegral len1)
+            return (Buf fp genSize newlen newcap newgen)
+
+length :: Buffer -> Int
+length (Buf _ _ len _ _) = len
+{-# INLINE length #-}
+
+unsafeIndex :: Buffer -> Int -> Word8
+unsafeIndex (Buf fp off len _ _) i = assert (i >= 0 && i < len) .
+    inlinePerformIO . withForeignPtr fp $ flip peekByteOff (off+i)
+{-# INLINE unsafeIndex #-}
+
+substring :: Int -> Int -> Buffer -> ByteString
+substring s l (Buf fp off len _ _) =
+  assert (s >= 0 && s <= len) .
+  assert (l >= 0 && l <= len-s) $
+  mkPS fp (off+s) l
+{-# INLINE substring #-}
+
+unsafeDrop :: Int -> Buffer -> ByteString
+unsafeDrop s (Buf fp off len _ _) =
+  assert (s >= 0 && s <= len) $
+  mkPS fp (off+s) (len-s)
+{-# INLINE unsafeDrop #-}
diff --git a/internal/Data/Attoparsec/ByteString/FastSet.hs b/internal/Data/Attoparsec/ByteString/FastSet.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/ByteString/FastSet.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE BangPatterns, MagicHash #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Attoparsec.ByteString.FastSet
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Fast set membership tests for 'Word8' and 8-bit 'Char' values.  The
+-- set representation is unboxed for efficiency.  For small sets, we
+-- test for membership using a binary search.  For larger sets, we use
+-- a lookup table.
+--
+-----------------------------------------------------------------------------
+module Data.Attoparsec.ByteString.FastSet
+    (
+    -- * Data type
+      FastSet
+    -- * Construction
+    , fromList
+    , set
+    -- * Lookup
+    , memberChar
+    , memberWord8
+    -- * Debugging
+    , fromSet
+    -- * Handy interface
+    , charClass
+    ) where
+
+import Data.Bits ((.&.), (.|.), unsafeShiftL)
+import Foreign.Storable (peekByteOff, pokeByteOff)
+import GHC.Exts (Int(I#), iShiftRA#)
+import GHC.Word (Word8)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
+import qualified Data.ByteString.Internal as I
+import qualified Data.ByteString.Unsafe as U
+
+data FastSet = Sorted { fromSet :: !B.ByteString }
+             | Table  { fromSet :: !B.ByteString }
+    deriving (Eq, Ord)
+
+instance Show FastSet where
+    show (Sorted s) = "FastSet Sorted " ++ show (B8.unpack s)
+    show (Table _) = "FastSet Table"
+
+-- | The lower bound on the size of a lookup table.  We choose this to
+-- balance table density against performance.
+tableCutoff :: Int
+tableCutoff = 8
+
+-- | Create a set.
+set :: B.ByteString -> FastSet
+set s | B.length s < tableCutoff = Sorted . B.sort $ s
+      | otherwise                = Table . mkTable $ s
+
+fromList :: [Word8] -> FastSet
+fromList = set . B.pack
+
+data I = I {-# UNPACK #-} !Int {-# UNPACK #-} !Word8
+
+shiftR :: Int -> Int -> Int
+shiftR (I# x#) (I# i#) = I# (x# `iShiftRA#` i#)
+
+index :: Int -> I
+index i = I (i `shiftR` 3) (1 `unsafeShiftL` (i .&. 7))
+{-# INLINE index #-}
+
+-- | Check the set for membership.
+memberWord8 :: Word8 -> FastSet -> Bool
+memberWord8 w (Table t)  =
+    let I byte bit = index (fromIntegral w)
+    in  U.unsafeIndex t byte .&. bit /= 0
+memberWord8 w (Sorted s) = search 0 (B.length s - 1)
+    where search lo hi
+              | hi < lo = False
+              | otherwise =
+                  let mid = (lo + hi) `quot` 2
+                  in case compare w (U.unsafeIndex s mid) of
+                       GT -> search (mid + 1) hi
+                       LT -> search lo (mid - 1)
+                       _ -> True
+
+-- | Check the set for membership.  Only works with 8-bit characters:
+-- characters above code point 255 will give wrong answers.
+memberChar :: Char -> FastSet -> Bool
+memberChar c = memberWord8 (I.c2w c)
+{-# INLINE memberChar #-}
+
+mkTable :: B.ByteString -> B.ByteString
+mkTable s = I.unsafeCreate 32 $ \t -> do
+            _ <- I.memset t 0 32
+            U.unsafeUseAsCStringLen s $ \(p, l) ->
+              let loop n | n == l = return ()
+                         | otherwise = do
+                    c <- peekByteOff p n :: IO Word8
+                    let I byte bit = index (fromIntegral c)
+                    prev <- peekByteOff t byte :: IO Word8
+                    pokeByteOff t byte (prev .|. bit)
+                    loop (n + 1)
+              in loop 0
+
+charClass :: String -> FastSet
+charClass = set . B8.pack . go
+    where go (a:'-':b:xs) = [a..b] ++ go xs
+          go (x:xs) = x : go xs
+          go _ = ""
diff --git a/internal/Data/Attoparsec/Internal/Compat.hs b/internal/Data/Attoparsec/Internal/Compat.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/Internal/Compat.hs
@@ -0,0 +1,27 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE MagicHash #-}
+module Data.Attoparsec.Internal.Compat where
+
+import Data.ByteString.Internal (ByteString(..))
+import Data.Word (Word8)
+import Foreign.ForeignPtr (ForeignPtr)
+
+#if MIN_VERSION_bytestring(0,11,0)
+import Data.ByteString.Internal (plusForeignPtr)
+#endif
+
+withPS :: ByteString -> (ForeignPtr Word8 -> Int -> Int -> r) -> r
+#if MIN_VERSION_bytestring(0,11,0)
+withPS (BS fp len)     kont = kont fp 0   len
+#else
+withPS (PS fp off len) kont = kont fp off len
+#endif
+{-# INLINE withPS #-}
+
+mkPS :: ForeignPtr Word8 -> Int -> Int -> ByteString
+#if MIN_VERSION_bytestring(0,11,0)
+mkPS fp off len = BS (plusForeignPtr fp off) len
+#else
+mkPS fp off len = PS fp off len
+#endif
+{-# INLINE mkPS #-}
diff --git a/internal/Data/Attoparsec/Internal/Fhthagn.hs b/internal/Data/Attoparsec/Internal/Fhthagn.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/Internal/Fhthagn.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE BangPatterns, Rank2Types, OverloadedStrings,
+    RecordWildCards, MagicHash, UnboxedTuples #-}
+
+module Data.Attoparsec.Internal.Fhthagn
+    (
+      inlinePerformIO
+    ) where
+
+import GHC.Exts (realWorld#)
+import GHC.IO (IO(IO))
+
+-- | Just like unsafePerformIO, but we inline it. Big performance gains as
+-- it exposes lots of things to further inlining. /Very unsafe/. In
+-- particular, you should do no memory allocation inside an
+-- 'inlinePerformIO' block. On Hugs this is just @unsafePerformIO@.
+inlinePerformIO :: IO a -> a
+inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
+{-# INLINE inlinePerformIO #-}
diff --git a/internal/Data/Attoparsec/Text/Buffer.hs b/internal/Data/Attoparsec/Text/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/Text/Buffer.hs
@@ -0,0 +1,235 @@
+{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, RecordWildCards,
+    UnboxedTuples #-}
+
+-- |
+-- Module      :  Data.Attoparsec.Text.Buffer
+-- Copyright   :  Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  bos@serpentine.com
+-- Stability   :  experimental
+-- Portability :  GHC
+--
+-- 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.
+
+module Data.Attoparsec.Text.Buffer
+    (
+      Buffer
+    , buffer
+    , unbuffer
+    , unbufferAt
+    , length
+    , pappend
+    , iter
+    , iter_
+    , substring
+    , lengthCodeUnits
+    , dropCodeUnits
+    ) where
+
+import Control.Exception (assert)
+import Data.List (foldl1')
+import Data.Monoid as Mon (Monoid(..))
+import Data.Semigroup (Semigroup(..))
+import Data.Text ()
+import Data.Text.Internal (Text(..))
+#if MIN_VERSION_text(2,0,0)
+import Data.Text.Internal.Encoding.Utf8 (utf8LengthByLeader)
+import Data.Text.Unsafe (iterArray, lengthWord8)
+#else
+import Data.Bits (shiftR)
+import Data.Text.Internal.Encoding.Utf16 (chr2)
+import Data.Text.Internal.Unsafe.Char (unsafeChr)
+import Data.Text.Unsafe (lengthWord16)
+#endif
+import Data.Text.Unsafe (Iter(..))
+import Foreign.Storable (sizeOf)
+import GHC.Exts (Int(..), indexIntArray#, unsafeCoerce#, writeIntArray#)
+import GHC.ST (ST(..), runST)
+import Prelude hiding (length)
+import qualified Data.Text.Array as A
+
+-- If _cap is zero, this buffer is empty.
+data Buffer = Buf {
+      _arr :: {-# UNPACK #-} !A.Array
+    , _off :: {-# UNPACK #-} !Int
+    , _len :: {-# UNPACK #-} !Int
+    , _cap :: {-# UNPACK #-} !Int
+    , _gen :: {-# UNPACK #-} !Int
+    }
+
+instance Show Buffer where
+    showsPrec p = showsPrec p . unbuffer
+
+-- | 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.
+buffer :: Text -> Buffer
+buffer (Text arr off len) = Buf arr off len len 0
+
+unbuffer :: Buffer -> Text
+unbuffer (Buf arr off len _ _) = Text arr off len
+
+unbufferAt :: Int -> Buffer -> Text
+unbufferAt s (Buf arr off len _ _) =
+  assert (s >= 0 && s <= len) $
+  Text arr (off+s) (len-s)
+
+instance Semigroup Buffer where
+    (Buf _ _ _ 0 _) <> b                     = b
+    a               <> (Buf _ _ _ 0 _)       = a
+    buf             <> (Buf arr off len _ _) = append buf arr off len
+    {-# INLINE (<>) #-}
+
+instance Monoid Buffer where
+    mempty = Buf A.empty 0 0 0 0
+    {-# INLINE mempty #-}
+
+    mappend = (<>)
+
+    mconcat [] = Mon.mempty
+    mconcat xs = foldl1' (<>) xs
+
+pappend :: Buffer -> Text -> Buffer
+pappend (Buf _ _ _ 0 _) t      = buffer t
+pappend buf (Text arr off len) = append buf arr off len
+
+append :: Buffer -> A.Array -> Int -> Int -> Buffer
+append (Buf arr0 off0 len0 cap0 gen0) !arr1 !off1 !len1 = runST $ do
+#if MIN_VERSION_text(2,0,0)
+  let woff    = sizeOf (0::Int)
+#else
+  let woff    = sizeOf (0::Int) `shiftR` 1
+#endif
+      newlen  = len0 + len1
+      !gen    = if gen0 == 0 then 0 else readGen arr0
+  if gen == gen0 && newlen <= cap0
+    then do
+      let newgen = gen + 1
+      marr <- unsafeThaw arr0
+      writeGen marr newgen
+#if MIN_VERSION_text(2,0,0)
+      A.copyI len1 marr (off0+len0) arr1 off1
+#else
+      A.copyI marr (off0+len0) arr1 off1 (off0+newlen)
+#endif
+      arr2 <- A.unsafeFreeze marr
+      return (Buf arr2 off0 newlen cap0 newgen)
+    else do
+      let newcap = newlen * 2
+          newgen = 1
+      marr <- A.new (newcap + woff)
+      writeGen marr newgen
+#if MIN_VERSION_text(2,0,0)
+      A.copyI len0 marr woff arr0 off0
+      A.copyI len1 marr (woff+len0) arr1 off1
+#else
+      A.copyI marr woff arr0 off0 (woff+len0)
+      A.copyI marr (woff+len0) arr1 off1 (woff+newlen)
+#endif
+      arr2 <- A.unsafeFreeze marr
+      return (Buf arr2 woff newlen newcap newgen)
+
+length :: Buffer -> Int
+length (Buf _ _ len _ _) = len
+{-# INLINE length #-}
+
+substring :: Int -> Int -> Buffer -> Text
+substring s l (Buf arr off len _ _) =
+  assert (s >= 0 && s <= len) .
+  assert (l >= 0 && l <= len-s) $
+  Text arr (off+s) l
+{-# INLINE substring #-}
+
+#if MIN_VERSION_text(2,0,0)
+
+lengthCodeUnits :: Text -> Int
+lengthCodeUnits = lengthWord8
+
+dropCodeUnits :: Int -> Buffer -> Text
+dropCodeUnits s (Buf arr off len _ _) =
+  assert (s >= 0 && s <= len) $
+  Text arr (off+s) (len-s)
+{-# INLINE dropCodeUnits #-}
+
+-- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-8
+-- array, returning the current character and the delta to add to give
+-- the next offset to iterate at.
+iter :: Buffer -> Int -> Iter
+iter (Buf arr off _ _ _) i = iterArray arr (off + i)
+{-# INLINE iter #-}
+
+-- | /O(1)/ Iterate one step through a UTF-8 array, returning the
+-- delta to add to give the next offset to iterate at.
+iter_ :: Buffer -> Int -> Int
+iter_ (Buf arr off _ _ _) i = utf8LengthByLeader $ A.unsafeIndex arr (off+i)
+{-# INLINE iter_ #-}
+
+unsafeThaw :: A.Array -> ST s (A.MArray s)
+unsafeThaw (A.ByteArray a) = ST $ \s# ->
+                          (# s#, A.MutableByteArray (unsafeCoerce# a) #)
+
+readGen :: A.Array -> Int
+readGen (A.ByteArray a) = case indexIntArray# a 0# of r# -> I# r#
+
+writeGen :: A.MArray s -> Int -> ST s ()
+writeGen (A.MutableByteArray a) (I# gen#) = ST $ \s0# ->
+  case writeIntArray# a 0# gen# s0# of
+    s1# -> (# s1#, () #)
+
+#else
+
+lengthCodeUnits :: Text -> Int
+lengthCodeUnits = lengthWord16
+
+dropCodeUnits :: Int -> Buffer -> Text
+dropCodeUnits s (Buf arr off len _ _) =
+  assert (s >= 0 && s <= len) $
+  Text arr (off+s) (len-s)
+{-# INLINE dropCodeUnits #-}
+
+-- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-16
+-- array, returning the current character and the delta to add to give
+-- the next offset to iterate at.
+iter :: Buffer -> Int -> Iter
+iter (Buf arr off _ _ _) i
+    | m < 0xD800 || m > 0xDBFF = Iter (unsafeChr m) 1
+    | otherwise                = Iter (chr2 m n) 2
+  where m = A.unsafeIndex arr j
+        n = A.unsafeIndex arr k
+        j = off + i
+        k = j + 1
+{-# INLINE iter #-}
+
+-- | /O(1)/ Iterate one step through a UTF-16 array, returning the
+-- delta to add to give the next offset to iterate at.
+iter_ :: Buffer -> Int -> Int
+iter_ (Buf arr off _ _ _) i | m < 0xD800 || m > 0xDBFF = 1
+                                | otherwise                = 2
+  where m = A.unsafeIndex arr (off+i)
+{-# INLINE iter_ #-}
+
+unsafeThaw :: A.Array -> ST s (A.MArray s)
+unsafeThaw A.Array{..} = ST $ \s# ->
+                          (# s#, A.MArray (unsafeCoerce# aBA) #)
+
+readGen :: A.Array -> Int
+readGen a = case indexIntArray# (A.aBA a) 0# of r# -> I# r#
+
+writeGen :: A.MArray s -> Int -> ST s ()
+writeGen a (I# gen#) = ST $ \s0# ->
+  case writeIntArray# (A.maBA a) 0# gen# s0# of
+    s1# -> (# s1#, () #)
+
+#endif
diff --git a/internal/Data/Attoparsec/Text/FastSet.hs b/internal/Data/Attoparsec/Text/FastSet.hs
new file mode 100644
--- /dev/null
+++ b/internal/Data/Attoparsec/Text/FastSet.hs
@@ -0,0 +1,121 @@
+{-# LANGUAGE BangPatterns #-}
+
+------------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Attoparsec.FastSet
+-- Copyright   :  Felipe Lessa 2010, Bryan O'Sullivan 2007-2015
+-- License     :  BSD3
+--
+-- Maintainer  :  felipe.lessa@gmail.com
+-- Stability   :  experimental
+-- Portability :  unknown
+--
+-- Fast set membership tests for 'Char' values. We test for
+-- membership using a hashtable implemented with Robin Hood
+-- collision resolution. The set representation is unboxed,
+-- and the characters and hashes interleaved, for efficiency.
+--
+--
+-----------------------------------------------------------------------------
+module Data.Attoparsec.Text.FastSet
+    (
+    -- * Data type
+      FastSet
+    -- * Construction
+    , fromList
+    , set
+    -- * Lookup
+    , member
+    -- * Handy interface
+    , charClass
+    ) where
+
+import Data.Bits ((.|.), (.&.), shiftR)
+import Data.Function (on)
+import Data.List (sort, sortBy)
+import qualified Data.Array.Base as AB
+import qualified Data.Array.Unboxed as A
+import qualified Data.Text as T
+
+data FastSet = FastSet {
+    table :: {-# UNPACK #-} !(A.UArray Int Int)
+  , mask  :: {-# UNPACK #-} !Int
+  }
+
+data Entry = Entry {
+    key          :: {-# UNPACK #-} !Char
+  , initialIndex :: {-# UNPACK #-} !Int
+  , index        :: {-# UNPACK #-} !Int
+  }
+
+offset :: Entry -> Int
+offset e = index e - initialIndex e
+
+resolveCollisions :: [Entry] -> [Entry]
+resolveCollisions [] = []
+resolveCollisions [e] = [e]
+resolveCollisions (a:b:entries) = a' : resolveCollisions (b' : entries)
+  where (a', b')
+          | index a < index b   = (a, b)
+          | offset a < offset b = (b { index=index a }, a { index=index a + 1 })
+          | otherwise           = (a, b { index=index a + 1 })
+
+pad :: Int -> [Entry] -> [Entry]
+pad = go 0
+  where -- ensure that we pad enough so that lookups beyond the
+        -- last hash in the table fall within the array
+        go !_ !m []          = replicate (max 1 m + 1) empty
+        go  k  m (e:entries) = map (const empty) [k..i - 1] ++ e :
+                               go (i + 1) (m + i - k - 1) entries
+          where i            = index e
+        empty                = Entry '\0' maxBound 0
+
+nextPowerOf2 :: Int -> Int
+nextPowerOf2 0  = 1
+nextPowerOf2 x  = go (x - 1) 1
+  where go y 32 = y + 1
+        go y k  = go (y .|. (y `shiftR` k)) $ k * 2
+
+fastHash :: Char -> Int
+fastHash = fromEnum
+
+fromList :: String -> FastSet
+fromList s = FastSet (AB.listArray (0, length interleaved - 1) interleaved)
+             mask'
+  where s'      = ordNub (sort s)
+        l       = length s'
+        mask'   = nextPowerOf2 ((5 * l) `div` 4) - 1
+        entries = pad mask' .
+                  resolveCollisions .
+                  sortBy (compare `on` initialIndex) .
+                  zipWith (\c i -> Entry c i i) s' .
+                  map ((.&. mask') . fastHash) $ s'
+        interleaved = concatMap (\e -> [fromEnum $ key e, initialIndex e])
+                      entries
+
+ordNub :: Eq a => [a] -> [a]
+ordNub []     = []
+ordNub (y:ys) = go y ys
+  where go x (z:zs)
+          | x == z    = go x zs
+          | otherwise = x : go z zs
+        go x []       = [x]
+
+set :: T.Text -> FastSet
+set = fromList . T.unpack
+
+-- | Check the set for membership.
+member :: Char -> FastSet -> Bool
+member c a           = go (2 * i)
+  where i            = fastHash c .&. mask a
+        lookupAt j b = (i' <= i) && (c == c' || b)
+            where c' = toEnum $ AB.unsafeAt (table a) j
+                  i' = AB.unsafeAt (table a) $ j + 1
+        go j         = lookupAt j . lookupAt (j + 2) . lookupAt (j + 4) .
+                       lookupAt (j + 6) . go $ j + 8
+
+charClass :: String -> FastSet
+charClass = fromList . go
+  where go (a:'-':b:xs) = [a..b] ++ go xs
+        go (x:xs)       = x : go xs
+        go _            = ""
diff --git a/tests/Makefile b/tests/Makefile
deleted file mode 100644
--- a/tests/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-all: TestFastSet.out qc.out
-
-%.out: %.exe
-	./$< | tee $<.tmp
-	mv $<.tmp $@
-
-qc.exe: QC.hs
-	ghc -O -fno-warn-orphans --make -o $@ $<
-
-%.exe: %.hs
-	ghc -O -fno-warn-orphans --make -o $@ $<
-
-clean:
-	-rm -f *.hi *.o *.exe *.out
diff --git a/tests/QC.hs b/tests/QC.hs
--- a/tests/QC.hs
+++ b/tests/QC.hs
@@ -1,116 +1,19 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
 module Main (main) where
 
-import Control.Monad (forM_)
-import Data.Maybe (isJust)
-import Data.Word (Word8)
-import Prelude hiding (takeWhile)
-import QCSupport
-import Test.Framework (defaultMain, testGroup)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-import Test.QuickCheck hiding (NonEmpty)
-import qualified Data.Attoparsec as P
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as C
-
--- Make sure that structures whose types claim they are non-empty
--- really are.
-
-nonEmptyList l = length (nonEmpty l) > 0
-    where types = l :: NonEmpty [Int]
-nonEmptyBS l = B.length (nonEmpty l) > 0
-
--- Naming.
-
-{-
-label (NonEmpty s) = case parse (anyWord8 <?> s) B.empty of
-                            (_, Left err) -> s `isInfixOf` err
-                            _             -> False
--}
-
--- Basic byte-level combinators.
-
-maybeP p s = case P.parse p s `P.feed` B.empty of
-               P.Done _ i -> Just i
-               _          -> Nothing
-
-defP p s = P.parse p s `P.feed` B.empty
-
-satisfy w s = maybeP (P.satisfy (<=w)) (B.cons w s) == Just w
-
-word8 w s = maybeP (P.word8 w) (B.cons w s) == Just w
-
-anyWord8 s = maybeP P.anyWord8 s == if B.null s
-                                    then Nothing
-                                    else Just (B.head s)
-
-notWord8 w (NonEmpty s) = maybeP (P.notWord8 w) s == if v == w
-                                                      then Nothing
-                                                      else Just v
-    where v = B.head s
-
-string s = maybeP (P.string s) s == Just s
-
-skipWhile w s =
-    let t = B.dropWhile (<=w) s
-    in case defP (P.skipWhile (<=w)) s of
-         P.Done t' () -> t == t'
-         _            -> False
-
-takeCount (Positive k) s =
-    case maybeP (P.take k) s of
-      Nothing -> k > B.length s
-      Just s' -> k <= B.length s
-
-takeWhile w s =
-    let (h,t) = B.span (==w) s
-    in case defP (P.takeWhile (==w)) s of
-         P.Done t' h' -> t == t' && h == h'
-         _            -> False
-
-takeWhile1 w s =
-    let s'    = B.cons w s
-        (h,t) = B.span (<=w) s'
-    in case defP (P.takeWhile1 (<=w)) s' of
-         P.Done t' h' -> t == t' && h == h'
-         _            -> False
-
-takeTill w s =
-    let (h,t) = B.break (==w) s
-    in case defP (P.takeTill (==w)) s of
-         P.Done t' h' -> t == t' && h == h'
-         _            -> False
-
-ensure n s = case defP (P.ensure m) s of
-               P.Done _ () -> B.length s >= m
-               _           -> B.length s < m
-    where m = (n `mod` 220) - 20
-
-takeWhile1_empty = maybeP (P.takeWhile1 undefined) B.empty == Nothing
-
-endOfInput s = maybeP P.endOfInput s == if B.null s
-                                        then Just ()
-                                        else Nothing
+import qualified QC.Buffer as Buffer
+import qualified QC.ByteString as ByteString
+import qualified QC.Combinator as Combinator
+import qualified QC.Simple as Simple
+import qualified QC.Text as Text
+import Test.Tasty (defaultMain, testGroup)
 
 main = defaultMain tests
 
-tests = [
-  testGroup "fnord" [
-    testProperty "nonEmptyList" nonEmptyList,
-    testProperty "nonEmptyBS" nonEmptyBS,
-    testProperty "satisfy" satisfy,
-    testProperty "word8" word8,
-    testProperty "notWord8" notWord8,
-    testProperty "anyWord8" anyWord8,
-    testProperty "string" string,
-    testProperty "skipWhile" skipWhile,
-    testProperty "takeCount" takeCount,
-    testProperty "takeWhile" takeWhile,
-    testProperty "takeWhile1" takeWhile1,
-    testProperty "takeWhile1_empty" takeWhile1_empty,
-    testProperty "takeTill" takeTill,
-    testProperty "endOfInput" endOfInput,
-    testProperty "ensure" ensure
-    ]
-
+tests = testGroup "tests" [
+    testGroup "bs" ByteString.tests
+  , testGroup "buf" Buffer.tests
+  , testGroup "combinator" Combinator.tests
+  , testGroup "simple" Simple.tests
+  , testGroup "text" Text.tests
   ]
diff --git a/tests/QC/Buffer.hs b/tests/QC/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Buffer.hs
@@ -0,0 +1,111 @@
+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, OverloadedStrings,
+    TypeSynonymInstances #-}
+
+module QC.Buffer (tests) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+import Data.Monoid (Monoid(mconcat))
+#endif
+import QC.Common ()
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck
+import qualified Data.Attoparsec.ByteString.Buffer as BB
+import qualified Data.Attoparsec.Text.Buffer as BT
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Unsafe as B
+import qualified Data.Text as T
+import qualified Data.Text.Unsafe as T
+
+data BP t b = BP [t] !t !b
+            deriving (Eq, Show)
+
+type BPB = BP B.ByteString BB.Buffer
+type BPT = BP T.Text BT.Buffer
+
+instance Arbitrary BPB where
+  arbitrary = do
+    bss <- arbitrary
+    return $! toBP BB.buffer bss
+
+  shrink (BP bss _ _) = toBP BB.buffer <$> shrink bss
+
+instance Arbitrary BPT where
+  arbitrary = do
+    bss <- arbitrary
+    return $! toBP BT.buffer bss
+
+  shrink (BP bss _ _) = toBP BT.buffer <$> shrink bss
+
+toBP :: (Monoid a, Monoid b) => (a -> b) -> [a] -> BP a b
+toBP buf bss = BP bss (mconcat bss) (mconcat (map buf bss))
+
+b_unbuffer :: BPB -> Property
+b_unbuffer (BP _ts t buf) = t === BB.unbuffer buf
+
+t_unbuffer :: BPT -> Property
+t_unbuffer (BP _ts t buf) = t === BT.unbuffer buf
+
+-- This test triggers both branches in Data.Attoparsec.Text.Buffer.append
+-- and checks that Data.Text.Array.copyI manipulations are correct.
+t_unbuffer_three :: Property
+t_unbuffer_three = t_unbuffer $ toBP BT.buffer [t, t, t]
+  where
+    -- Make it long enough to increase chances of a segmentation fault
+    t = T.replicate 1000 "\0"
+
+b_length :: BPB -> Property
+b_length (BP _ts t buf) = B.length t === BB.length buf
+
+t_length :: BPT -> Property
+t_length (BP _ts t buf) = BT.lengthCodeUnits t === BT.length buf
+
+b_unsafeIndex :: BPB -> Gen Property
+b_unsafeIndex (BP _ts t buf) = do
+  let l = B.length t
+  i <- choose (0,l-1)
+  return $ l === 0 .||. B.unsafeIndex t i === BB.unsafeIndex buf i
+
+t_iter :: BPT -> Gen Property
+t_iter (BP _ts t buf) = do
+  let l = BT.lengthCodeUnits t
+  i <- choose (0,l-1)
+  let it (T.Iter c q) = (c,q)
+  return $ l === 0 .||. it (T.iter t i) === it (BT.iter buf i)
+
+t_iter_ :: BPT -> Gen Property
+t_iter_ (BP _ts t buf) = do
+  let l = BT.lengthCodeUnits t
+  i <- choose (0,l-1)
+  return $ l === 0 .||. T.iter_ t i === BT.iter_ buf i
+
+b_unsafeDrop :: BPB -> Gen Property
+b_unsafeDrop (BP _ts t buf) = do
+  i <- choose (0, B.length t)
+  return $ B.unsafeDrop i t === BB.unsafeDrop i buf
+
+t_dropCodeUnits :: BPT -> Gen Property
+t_dropCodeUnits (BP _ts t buf) = do
+  i <- choose (0, BT.lengthCodeUnits t)
+  return $ dropCodeUnits i t === BT.dropCodeUnits i buf
+  where
+#if MIN_VERSION_text(2,0,0)
+    dropCodeUnits = T.dropWord8
+#else
+    dropCodeUnits = T.dropWord16
+#endif
+
+tests :: [TestTree]
+tests = [
+    testProperty "b_unbuffer" b_unbuffer
+  , testProperty "t_unbuffer" t_unbuffer
+  , testProperty "t_unbuffer_three" t_unbuffer_three
+  , testProperty "b_length" b_length
+  , testProperty "t_length" t_length
+  , testProperty "b_unsafeIndex" b_unsafeIndex
+  , testProperty "t_iter" t_iter
+  , testProperty "t_iter_" t_iter_
+  , testProperty "b_unsafeDrop" b_unsafeDrop
+  , testProperty "t_dropCodeUnits" t_dropCodeUnits
+  ]
diff --git a/tests/QC/ByteString.hs b/tests/QC/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/ByteString.hs
@@ -0,0 +1,214 @@
+{-# LANGUAGE BangPatterns, CPP, OverloadedStrings #-}
+module QC.ByteString (tests) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), (<$>))
+#endif
+import Data.Char (chr, ord, toUpper)
+import Data.Int (Int64)
+import Data.Word (Word8)
+import Prelude hiding (take, takeWhile)
+import QC.Common (ASCII(..), liftOp, parseBS, toStrictBS)
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck
+import qualified Data.Attoparsec.ByteString as P
+import qualified Data.Attoparsec.ByteString.Char8 as P8
+import qualified Data.Attoparsec.ByteString.FastSet as S
+import qualified Data.Attoparsec.ByteString.Lazy as PL
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString.Lazy.Char8 as L8
+
+-- Basic byte-level combinators.
+
+satisfy :: Word8 -> L.ByteString -> Property
+satisfy w s = parseBS (P.satisfy (<=w)) (L.cons w s) === Just w
+
+satisfyWith :: Word8 -> L.ByteString -> Property
+satisfyWith w s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
+                         (L.cons (fromIntegral (ord c)) s) === Just c
+  where
+    c = chr (fromIntegral w)
+
+word8 :: Word8 -> L.ByteString -> Property
+word8 w s = parseBS (P.word8 w) (L.cons w s) === Just w
+
+skip :: Word8 -> L.ByteString -> Property
+skip w s =
+  case (parseBS (P.skip (<w)) s, L.uncons s) of
+    (Nothing, mcs) -> maybe (property True) (expectFailure . it) mcs
+    (Just _,  mcs) -> maybe (property False) it mcs
+  where it cs = liftOp "<" (<) (fst cs) w
+
+anyWord8 :: L.ByteString -> Property
+anyWord8 s
+    | L.null s  = p === Nothing
+    | otherwise = p === Just (L.head s)
+  where p = parseBS P.anyWord8 s
+
+notWord8 :: Word8 -> NonEmptyList Word8 -> Property
+notWord8 w (NonEmpty s) = parseBS (P.notWord8 w) bs === if v == w
+                                                        then Nothing
+                                                        else Just v
+    where v = L.head bs
+          bs = L.pack s
+
+peekWord8 :: L.ByteString -> Property
+peekWord8 s
+    | L.null s  = p === Just (Nothing, s)
+    | otherwise = p === Just (Just (L.head s), s)
+  where p = parseBS ((,) <$> P.peekWord8 <*> P.takeLazyByteString) s
+
+peekWord8' :: L.ByteString -> Property
+peekWord8' s = parseBS P.peekWord8' s === (fst <$> L.uncons s)
+
+string :: L.ByteString -> L.ByteString -> Property
+string s t = parseBS (P.string s') (s `L.append` t) === Just s'
+  where s' = toStrictBS s
+
+stringCI :: ASCII L.ByteString -> ASCII L.ByteString -> Property
+stringCI (ASCII s) (ASCII t) =
+    parseBS (P8.stringCI up) (s `L.append` t) === Just s'
+  where s' = toStrictBS s
+        up = B8.map toUpper s'
+
+strings :: L.ByteString -> L.ByteString -> L.ByteString -> Property
+strings s t u =
+    parseBS (P.string (toStrictBS s) >> P.string t') (L.concat [s,t,u])
+    === Just t'
+  where t' = toStrictBS t
+
+skipWhile :: Word8 -> L.ByteString -> Property
+skipWhile w s =
+    let t = L.dropWhile (<=w) s
+    in case PL.parse (P.skipWhile (<=w)) s of
+         PL.Done t' () -> t === t'
+         _             -> property False
+
+takeCount :: Positive Int -> L.ByteString -> Property
+takeCount (Positive k) s =
+    case parseBS (P.take k) s of
+      Nothing -> liftOp ">" (>) (fromIntegral k) (L.length s)
+      Just _s -> liftOp "<=" (<=) (fromIntegral k) (L.length s)
+
+takeWhile :: Word8 -> L.ByteString -> Property
+takeWhile w s =
+    let (h,t) = L.span (==w) s
+    in case PL.parse (P.takeWhile (==w)) s of
+         PL.Done t' h' -> t === t' .&&. toStrictBS h === h'
+         _             -> property False
+
+take :: Int -> L.ByteString -> Property
+take n s = maybe (property $ L.length s < fromIntegral n)
+           (=== B.take n (toStrictBS s)) $
+           parseBS (P.take n) s
+
+takeByteString :: L.ByteString -> Property
+takeByteString s = maybe (property False) (=== toStrictBS s) .
+                   parseBS P.takeByteString $ s
+
+takeLazyByteString :: L.ByteString -> Property
+takeLazyByteString s = maybe (property False) (=== s) .
+                       parseBS P.takeLazyByteString $ s
+
+takeWhile1 :: Word8 -> L.ByteString -> Property
+takeWhile1 w s =
+    let s'    = L.cons w s
+        (h,t) = L.span (<=w) s'
+    in case PL.parse (P.takeWhile1 (<=w)) s' of
+         PL.Done t' h' -> t === t' .&&. toStrictBS h === h'
+         _             -> property False
+
+takeWhileIncluding :: Word8 -> L.ByteString -> Property
+takeWhileIncluding w s =
+    let s'    = L.cons w $ L.snoc s (w+1)
+        (h_,t_) = L.span (<=w) s'
+        (h,t) =
+          case L.uncons t_ of
+            Nothing -> (h_, t_)
+            Just (n, nt) -> (h_ `L.snoc` n, nt)
+    in w < 255 ==> case PL.parse (P.takeWhileIncluding (<=w)) s' of
+         PL.Done t' h' -> t === t' .&&. toStrictBS h === h'
+         _             -> property False
+
+takeTill :: Word8 -> L.ByteString -> Property
+takeTill w s =
+    let (h,t) = L.break (==w) s
+    in case PL.parse (P.takeTill (==w)) s of
+         PL.Done t' h' -> t === t' .&&. toStrictBS h === h'
+         _             -> property False
+
+takeWhile1_empty :: Property
+takeWhile1_empty = parseBS (P.takeWhile1 undefined) L.empty === Nothing
+
+getChunk :: L.ByteString -> Property
+getChunk s =
+  maybe (property False) (=== L.toChunks s) $
+    parseBS getChunks s
+  where getChunks = go []
+        go res = do
+          mchunk <- P.getChunk
+          case mchunk of
+            Nothing -> return (reverse res)
+            Just chunk -> do
+              _ <- P.take (B.length chunk)
+              go (chunk:res)
+
+endOfInput :: L.ByteString -> Property
+endOfInput s = parseBS P.endOfInput s === if L.null s
+                                          then Just ()
+                                          else Nothing
+
+endOfLine :: L.ByteString -> Property
+endOfLine s =
+  case (parseBS P8.endOfLine s, L8.uncons s) of
+    (Nothing, mcs) -> maybe (property True) (expectFailure . eol) mcs
+    (Just _,  mcs) -> maybe (property False) eol mcs
+  where eol (c,s') = c === '\n' .||.
+                     (c, fst <$> L8.uncons s') === ('\r', Just '\n')
+
+scan :: L.ByteString -> Positive Int64 -> Property
+scan s (Positive k) = parseBS p s === Just (toStrictBS $ L.take k s)
+  where p = P.scan k $ \ n _ ->
+            if n > 0 then let !n' = n - 1 in Just n' else Nothing
+
+members :: [Word8] -> Property
+members s = property $ all (`S.memberWord8` set) s
+    where set = S.fromList s
+
+nonmembers :: [Word8] -> [Word8] -> Property
+nonmembers s s' = property . not . any (`S.memberWord8` set) $ filter (not . (`elem` s)) s'
+    where set = S.fromList s
+
+tests :: [TestTree]
+tests = [
+      testProperty "anyWord8" anyWord8
+    , testProperty "endOfInput" endOfInput
+    , testProperty "endOfLine" endOfLine
+    , testProperty "notWord8" notWord8
+    , testProperty "peekWord8" peekWord8
+    , testProperty "peekWord8'" peekWord8'
+    , testProperty "satisfy" satisfy
+    , testProperty "satisfyWith" satisfyWith
+    , testProperty "scan" scan
+    , testProperty "skip" skip
+    , testProperty "skipWhile" skipWhile
+    , testProperty "string" string
+    , testProperty "stringCI" stringCI
+    , testProperty "strings" strings
+    , testProperty "take" take
+    , testProperty "takeByteString" takeByteString
+    , testProperty "takeCount" takeCount
+    , testProperty "takeLazyByteString" takeLazyByteString
+    , testProperty "takeTill" takeTill
+    , testProperty "takeWhile" takeWhile
+    , testProperty "takeWhile1" takeWhile1
+    , testProperty "takeWhile1_empty" takeWhile1_empty
+    , testProperty "takeWhileIncluding" takeWhileIncluding
+    , testProperty "getChunk" getChunk
+    , testProperty "word8" word8
+    , testProperty "members" members
+    , testProperty "nonmembers" nonmembers
+  ]
diff --git a/tests/QC/Combinator.hs b/tests/QC/Combinator.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Combinator.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE CPP, OverloadedStrings #-}
+
+module QC.Combinator where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), (<$>), (<*), (*>))
+#endif
+import Data.Maybe (fromJust, isJust)
+import Data.Word (Word8)
+import QC.Common (Repack, parseBS, repackBS, toLazyBS)
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck
+import qualified Data.Attoparsec.ByteString.Char8 as P
+import qualified Data.Attoparsec.Combinator as C
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
+
+choice :: NonEmptyList (NonEmptyList Word8) -> Gen Property
+choice (NonEmpty xs) = do
+  let ys = map (B.pack . getNonEmpty) xs
+  return . forAll (repackBS <$> arbitrary <*> elements ys) $
+    maybe False (`elem` ys) . parseBS (C.choice (map P.string ys))
+
+count :: Positive (Small Int) -> Repack -> B.ByteString -> Bool
+count (Positive (Small n)) rs s =
+    (length <$> parseBS (C.count n (P.string s)) input) == Just n
+  where input = repackBS rs (B.concat (replicate (n+1) s))
+
+lookAhead :: NonEmptyList Word8 -> Bool
+lookAhead (NonEmpty xs) =
+  let ys = B.pack xs
+      withLookAheadThenConsume = (\x y -> (x, y)) <$> C.lookAhead (P.string ys) <*> P.string ys
+      mr = parseBS withLookAheadThenConsume $ toLazyBS ys
+  in isJust mr && fst (fromJust mr) == snd (fromJust mr)
+
+match :: Int -> NonNegative Int -> NonNegative Int -> Repack -> Bool
+match n (NonNegative x) (NonNegative y) rs =
+    parseBS (P.match parser) (repackBS rs input) == Just (input, n)
+  where parser = P.skipWhile (=='x') *> P.signed P.decimal <*
+                 P.skipWhile (=='y')
+        input = B.concat [
+            B8.replicate x 'x', B8.pack (show n), B8.replicate y 'y'
+          ]
+
+tests :: [TestTree]
+tests = [
+    testProperty "choice" choice
+  , testProperty "count" count
+  , testProperty "lookAhead" lookAhead
+  , testProperty "match" match
+  ]
diff --git a/tests/QC/Common.hs b/tests/QC/Common.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Common.hs
@@ -0,0 +1,113 @@
+{-# LANGUAGE CPP, FlexibleInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module QC.Common
+    (
+      ASCII(..)
+    , parseBS
+    , parseT
+    , toLazyBS
+    , toStrictBS
+    , Repack
+    , repackBS
+    , repackBS_
+    , repackT
+    , repackT_
+    , liftOp
+    ) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), (<$>))
+#endif
+import Data.Char (isAlpha)
+import Test.QuickCheck
+import Test.QuickCheck.Unicode (shrinkChar, string)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Attoparsec.ByteString.Lazy as BL
+import qualified Data.Attoparsec.Text.Lazy as TL
+
+#if !MIN_VERSION_base(4,4,0)
+-- This should really be a dependency on the random package :-(
+instance Random Word8 where
+  randomR = integralRandomR
+  random = randomR (minBound,maxBound)
+
+instance Arbitrary Word8 where
+    arbitrary = choose (minBound, maxBound)
+#endif
+
+parseBS :: BL.Parser r -> BL.ByteString -> Maybe r
+parseBS p = BL.maybeResult . BL.parse p
+
+parseT :: TL.Parser r -> TL.Text -> Maybe r
+parseT p = TL.maybeResult . TL.parse p
+
+toStrictBS :: BL.ByteString -> B.ByteString
+toStrictBS = B.concat . BL.toChunks
+
+toLazyBS :: B.ByteString -> BL.ByteString
+toLazyBS = BL.fromChunks . (:[])
+
+instance Arbitrary B.ByteString where
+    arbitrary = B.pack <$> arbitrary
+    shrink = map B.pack . shrink . B.unpack
+
+instance Arbitrary BL.ByteString where
+    arbitrary = repackBS <$> arbitrary <*> arbitrary
+    shrink = map BL.pack . shrink . BL.unpack
+
+newtype ASCII a = ASCII { fromASCII :: a }
+                  deriving (Eq, Ord, Show)
+
+instance Arbitrary (ASCII B.ByteString) where
+    arbitrary = (ASCII . B.pack) <$> listOf (choose (0,127))
+    shrink = map (ASCII . B.pack) . shrink . B.unpack . fromASCII
+
+instance Arbitrary (ASCII BL.ByteString) where
+    arbitrary = ASCII <$> (repackBS <$> arbitrary <*> (fromASCII <$> arbitrary))
+    shrink = map (ASCII . BL.pack) . shrink . BL.unpack . fromASCII
+
+type Repack = NonEmptyList (Positive (Small Int))
+
+repackBS :: Repack -> B.ByteString -> BL.ByteString
+repackBS (NonEmpty bs) =
+    BL.fromChunks . repackBS_ (map (getSmall . getPositive) bs)
+
+repackBS_ :: [Int] -> B.ByteString -> [B.ByteString]
+repackBS_ = go . cycle
+  where go (b:bs) s
+          | B.null s = []
+          | otherwise = let (h,t) = B.splitAt b s
+                        in h : go bs t
+        go _ _ = error "unpossible"
+
+instance Arbitrary T.Text where
+    arbitrary = T.pack <$> string
+    shrink    = map T.pack . shrinkList shrinkChar . T.unpack
+
+instance Arbitrary TL.Text where
+    arbitrary = TL.pack <$> string
+    shrink    = map TL.pack . shrinkList shrinkChar . TL.unpack
+
+repackT :: Repack -> T.Text -> TL.Text
+repackT (NonEmpty bs) =
+    TL.fromChunks . repackT_ (map (getSmall . getPositive) bs)
+
+repackT_ :: [Int] -> T.Text -> [T.Text]
+repackT_ = go . cycle
+  where go (b:bs) s
+          | T.null s = []
+          | otherwise = let (h,t) = T.splitAt b s
+                        in h : go bs t
+        go _ _ = error "unpossible"
+
+liftOp :: (Show a, Testable prop) =>
+          String -> (a -> a -> prop) -> a -> a -> Property
+liftOp name f x y = counterexample desc (f x y)
+  where op = case name of
+               (c:_) | isAlpha c -> " `" ++ name ++ "` "
+                     | otherwise -> " " ++ name ++ " "
+               _ -> " ??? "
+        desc = "not (" ++ show x ++ op ++ show y ++ ")"
diff --git a/tests/QC/IPv6/Internal.hs b/tests/QC/IPv6/Internal.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/IPv6/Internal.hs
@@ -0,0 +1,316 @@
+-- -----------------------------------------------------------------------------
+
+-- |
+-- Module      :  Text.IPv6Addr
+-- Copyright   :  Copyright © Michel Boucey 2011-2015
+-- License     :  BSD-Style
+-- Maintainer  :  michel.boucey@gmail.com
+--
+-- Dealing with IPv6 address text representations, canonization and manipulations.
+--
+
+-- -----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module QC.IPv6.Internal where {-
+    ( expandTokens
+    , macAddr
+    , maybeIPv6AddrTokens
+    , ipv4AddrToIPv6AddrTokens
+    , ipv6TokensToText
+    , ipv6TokensToIPv6Addr
+    , isIPv6Addr
+    , maybeTokIPv6Addr
+    , maybeTokPureIPv6Addr
+    , fromDoubleColon
+    , fromIPv6Addr
+    , toDoubleColon
+    ) where -}
+
+import Debug.Trace
+import Control.Monad (replicateM)
+import Data.Attoparsec.Text
+import Data.Char (isDigit,isHexDigit,toLower)
+import Data.Monoid ((<>))
+import Control.Applicative ((<|>),(<*))
+import Data.List (group,isSuffixOf,elemIndex,elemIndices,intersperse)
+import Data.Word (Word32)
+import Numeric (showHex)
+import qualified Data.Text as T
+import qualified Data.Text.Read as R (decimal)
+import Data.Maybe (fromJust)
+
+import QC.IPv6.Types
+
+tok0 = "0"
+
+-- | Returns the 'T.Text' of an IPv6 address.
+fromIPv6Addr :: IPv6Addr -> T.Text
+fromIPv6Addr (IPv6Addr t) = t
+
+-- | Given an arbitrary list of 'IPv6AddrToken', returns the corresponding 'T.Text'.
+ipv6TokensToText :: [IPv6AddrToken] -> T.Text
+ipv6TokensToText l = T.concat $ map ipv6TokenToText l
+
+-- | Returns the corresponding 'T.Text' of an IPv6 address token.
+ipv6TokenToText :: IPv6AddrToken -> T.Text
+ipv6TokenToText (SixteenBit s) = s
+ipv6TokenToText Colon = ":"
+ipv6TokenToText DoubleColon = "::"
+ipv6TokenToText AllZeros = tok0 -- "A single 16-bit 0000 field MUST be represented as 0" (RFC 5952, 4.1)
+ipv6TokenToText (IPv4Addr a) = a
+
+-- | Returns 'True' if a list of 'IPv6AddrToken' constitutes a valid IPv6 Address.
+isIPv6Addr :: [IPv6AddrToken] -> Bool
+isIPv6Addr [] = False
+isIPv6Addr [DoubleColon] = True
+isIPv6Addr [DoubleColon,SixteenBit tok1] = True
+isIPv6Addr tks =
+    diffNext tks && (do
+        let cdctks = countDoubleColon tks
+        let lentks = length tks
+        let lasttk = last tks
+        let lenconst = (lentks == 15 && cdctks == 0) || (lentks < 15 && cdctks == 1)
+        firstValidToken tks &&
+            (case countIPv4Addr tks of
+                0 -> case lasttk of
+                         SixteenBit _ -> lenconst
+                         DoubleColon  -> lenconst
+                         AllZeros     -> lenconst
+                         _            -> False
+                1 -> case lasttk of
+                         IPv4Addr _ -> (lentks == 13 && cdctks == 0) || (lentks < 12 && cdctks == 1)
+                         _          -> False
+                otherwise -> False))
+          where diffNext [] = False
+                diffNext [_] = True
+                diffNext (t:ts) = do
+                    let h = head ts
+                    case t of
+                        SixteenBit _ -> case h of
+                                            SixteenBit _ -> False
+                                            AllZeros     -> False
+                                            _            -> diffNext ts
+                        AllZeros     -> case h of
+                                            SixteenBit _ -> False
+                                            AllZeros     -> False
+                                            _            -> diffNext ts
+                        _            -> diffNext ts
+                firstValidToken l =
+                    case head l of
+                        SixteenBit _ -> True
+                        DoubleColon  -> True
+                        AllZeros     -> True
+                        _            -> False
+                countDoubleColon l = length $ elemIndices DoubleColon l
+                tok1 = "1"
+
+countIPv4Addr = foldr oneMoreIPv4Addr 0
+  where
+    oneMoreIPv4Addr t c = case t of
+                              IPv4Addr _ -> c + 1
+                              otherwise  -> c
+
+-- | This is the main function which returns 'Just' the list of a tokenized IPv6
+-- address text representation validated against RFC 4291 and canonized
+-- in conformation with RFC 5952, or 'Nothing'.
+maybeTokIPv6Addr :: T.Text -> Maybe [IPv6AddrToken]
+maybeTokIPv6Addr t =
+    case maybeIPv6AddrTokens t of
+        Just ltks -> if isIPv6Addr ltks
+                         then Just $ (ipv4AddrReplacement . toDoubleColon . fromDoubleColon) ltks
+                         else Nothing
+        Nothing   -> Nothing
+  where
+    ipv4AddrReplacement ltks =
+        if ipv4AddrRewrite ltks
+            then init ltks ++ ipv4AddrToIPv6AddrTokens (last ltks)
+            else ltks
+
+-- | Returns 'Just' the list of tokenized pure IPv6 address, always rewriting an
+-- embedded IPv4 address if present.
+maybeTokPureIPv6Addr :: T.Text -> Maybe [IPv6AddrToken]
+maybeTokPureIPv6Addr t = do
+    ltks <- maybeIPv6AddrTokens t
+    if isIPv6Addr ltks
+        then Just $ (toDoubleColon . ipv4AddrReplacement . fromDoubleColon) ltks
+        else Nothing
+  where
+    ipv4AddrReplacement ltks' = init ltks' ++ ipv4AddrToIPv6AddrTokens (last ltks')
+
+-- | Tokenize a 'T.Text' into 'Just' a list of 'IPv6AddrToken', or 'Nothing'.
+maybeIPv6AddrTokens :: T.Text -> Maybe [IPv6AddrToken]
+maybeIPv6AddrTokens s =
+    case readText s of
+         Done r l -> traceShow (r,l) $ if r==T.empty then Just l else Nothing
+         Fail {}  -> Nothing
+  where
+    readText s = feed (parse (many1 $ ipv4Addr <|> sixteenBit <|> doubleColon <|> colon) s) T.empty
+
+-- | An embedded IPv4 address have to be rewritten to output a pure IPv6 Address
+-- text representation in hexadecimal digits. But some well-known prefixed IPv6
+-- addresses have to keep visible in their text representation the fact that
+-- they deals with IPv4 to IPv6 transition process (RFC 5952 Section 5):
+--
+-- IPv4-compatible IPv6 address like "::1.2.3.4"
+--
+-- IPv4-mapped IPv6 address like "::ffff:1.2.3.4"
+--
+-- IPv4-translated address like "::ffff:0:1.2.3.4"
+--
+-- IPv4-translatable address like "64:ff9b::1.2.3.4"
+--
+-- ISATAP address like "fe80::5efe:1.2.3.4"
+--
+ipv4AddrRewrite :: [IPv6AddrToken] -> Bool
+ipv4AddrRewrite tks =
+    case last tks of
+        IPv4Addr _ -> do
+            let itks = init tks
+            not (itks == [DoubleColon]
+                 || itks == [DoubleColon,SixteenBit tokffff,Colon]
+                 || itks == [DoubleColon,SixteenBit tokffff,Colon,AllZeros,Colon]
+                 || itks == [SixteenBit "64",Colon,SixteenBit "ff9b",DoubleColon]
+                 || [SixteenBit "200",Colon,SixteenBit tok5efe,Colon] `isSuffixOf` itks
+                 || [AllZeros,Colon,SixteenBit tok5efe,Colon] `isSuffixOf` itks
+                 || [DoubleColon,SixteenBit tok5efe,Colon] `isSuffixOf` itks)
+        _          -> False
+  where
+    tokffff = "ffff"
+    tok5efe = "5efe"
+
+-- | Rewrites an embedded 'IPv4Addr' into the corresponding list of pure 'IPv6Addr' tokens.
+--
+-- > ipv4AddrToIPv6AddrTokens (IPv4Addr "127.0.0.1") == [SixteenBits "7f0",Colon,SixteenBits "1"]
+--
+ipv4AddrToIPv6AddrTokens :: IPv6AddrToken -> [IPv6AddrToken]
+ipv4AddrToIPv6AddrTokens t =
+    case t of
+        IPv4Addr a -> do
+            let m = toHex a
+            [  SixteenBit ((!!) m 0 <> addZero ((!!) m 1))
+             , Colon
+             , SixteenBit ((!!) m 2 <> addZero ((!!) m 3)) ]
+        _          -> [t]
+      where
+        toHex a = map (\x -> T.pack $ showHex (read (T.unpack x)::Int) "") $ T.split (=='.') a
+        addZero d = if T.length d == 1 then tok0 <> d else d
+
+expandTokens :: [IPv6AddrToken] -> [IPv6AddrToken]
+expandTokens = map expandToken
+  where expandToken (SixteenBit s) = SixteenBit $ T.justifyRight 4 '0' s
+        expandToken AllZeros = SixteenBit "0000"
+        expandToken t = t
+
+fromDoubleColon :: [IPv6AddrToken] -> [IPv6AddrToken]
+fromDoubleColon tks =
+    if DoubleColon `notElem` tks
+        then tks
+        else do let s = splitAt (fromJust $ elemIndex DoubleColon tks) tks
+                let fsts = fst s
+                let snds = if not (null (snd s)) then tail(snd s) else []
+                let fste = if null fsts then [] else fsts ++ [Colon]
+                let snde = if null snds then [] else Colon : snds
+                fste ++ allZerosTokensReplacement(quantityOfAllZerosTokenToReplace tks) ++ snde
+      where
+        allZerosTokensReplacement x = intersperse Colon (replicate x AllZeros)
+        quantityOfAllZerosTokenToReplace x =
+            ntks tks - foldl (\c x -> if (x /= DoubleColon) && (x /= Colon) then c+1 else c) 0 x
+          where
+            ntks tks = if countIPv4Addr tks == 1 then 7 else 8
+
+toDoubleColon :: [IPv6AddrToken] -> [IPv6AddrToken]
+toDoubleColon tks =
+    zerosToDoubleColon tks (zerosRunToReplace $ zerosRunsList tks)
+  where
+    zerosToDoubleColon :: [IPv6AddrToken] -> (Int,Int) -> [IPv6AddrToken]
+    -- No all zeros token, so no double colon replacement...
+    zerosToDoubleColon ls (_,0) = ls
+    -- "The symbol '::' MUST NOT be used to shorten just one 16-bit 0 field" (RFC 5952 4.2.2)
+    zerosToDoubleColon ls (_,1) = ls
+    zerosToDoubleColon ls (i,l) =
+        let ls' = filter (/= Colon) ls
+        in intersperse Colon (Prelude.take i ls') ++ [DoubleColon] ++ intersperse Colon (drop (i+l) ls')
+    zerosRunToReplace t =
+        let l = longestLengthZerosRun t
+        in (firstLongestZerosRunIndex t l,l)
+      where
+        firstLongestZerosRunIndex x y = sum . snd . unzip $ Prelude.takeWhile (/=(True,y)) x
+        longestLengthZerosRun x =
+            maximum $ map longest x
+          where longest t = case t of
+                                (True,i)  -> i
+                                _         -> 0
+    zerosRunsList x = map helper $ groupZerosRuns x
+      where
+        helper h = (head h == AllZeros, lh) where lh = length h
+        groupZerosRuns = group . filter (/= Colon)
+
+ipv6TokensToIPv6Addr :: [IPv6AddrToken] -> Maybe IPv6Addr
+ipv6TokensToIPv6Addr l = Just $ IPv6Addr $ ipv6TokensToText l
+
+fullSixteenBit :: T.Text -> Maybe IPv6AddrToken
+fullSixteenBit t =
+    case parse ipv6AddrFullChunk t of
+        Done a b  -> if a==T.empty then Just $ SixteenBit $ T.pack b else Nothing
+        _         -> Nothing
+
+macAddr :: Parser (Maybe [IPv6AddrToken])
+macAddr = do
+    n1 <- count 2 hexaChar <* ":"
+    n2 <- count 2 hexaChar <* ":"
+    n3 <- count 2 hexaChar <* ":"
+    n4 <- count 2 hexaChar <* ":"
+    n5 <- count 2 hexaChar <* ":"
+    n6 <- count 2 hexaChar
+    return $ maybeIPv6AddrTokens $ T.pack $ concat [n1,n2,n3,n4,n5,n6]
+
+sixteenBit :: Parser IPv6AddrToken
+sixteenBit = do
+    r <- ipv6AddrFullChunk <|> count 3 hexaChar <|> count 2 hexaChar <|> count 1 hexaChar
+    -- "Leading zeros MUST be suppressed" (RFC 5952, 4.1)
+    let r' = T.dropWhile (=='0') $ T.pack r
+    return $ if T.null r'
+                 then AllZeros
+                 -- Hexadecimal digits MUST be in lowercase (RFC 5952 4.3)
+                 else SixteenBit $ T.toLower r'
+
+ipv4Addr :: Parser IPv6AddrToken
+ipv4Addr = do
+    n1 <- manyDigits <* "."
+    if n1 /= T.empty
+        then do n2 <- manyDigits <* "."
+                if n2 /= T.empty
+                    then do n3 <- manyDigits <* "."
+                            if n3 /= T.empty
+                                then do n4 <- manyDigits
+                                        if n4 /= T.empty
+                                            then return $ IPv4Addr $ T.intercalate "." [n1,n2,n3,n4]
+                                            else parserFailure
+                                else parserFailure
+                    else parserFailure
+        else parserFailure
+  where
+    parserFailure = fail "ipv4Addr parsing failure"
+    manyDigits = do
+      ds <- takeWhile1 isDigit
+      case R.decimal ds of
+          Right (n,_) -> return (if n < 256 then T.pack $ show n else T.empty)
+          Left  _     -> return T.empty
+
+doubleColon :: Parser IPv6AddrToken
+doubleColon = do
+    string "::"
+    return DoubleColon
+
+colon :: Parser IPv6AddrToken
+colon = do
+    string ":"
+    return Colon
+
+ipv6AddrFullChunk :: Parser String
+ipv6AddrFullChunk = count 4 hexaChar
+
+hexaChar :: Parser Char
+hexaChar = satisfy (inClass "0-9a-fA-F")
diff --git a/tests/QC/IPv6/Types.hs b/tests/QC/IPv6/Types.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/IPv6/Types.hs
@@ -0,0 +1,29 @@
+-- -----------------------------------------------------------------------------
+
+-- |
+-- Module      :  Text.IPv6Addr
+-- Copyright   :  Copyright © Michel Boucey 2011-2015
+-- License     :  BSD-Style
+-- Maintainer  :  michel.boucey@gmail.com
+--
+-- Dealing with IPv6 address text representations, canonization and manipulations.
+--
+
+-- -----------------------------------------------------------------------------
+
+module QC.IPv6.Types where
+
+import qualified Data.Text as T
+
+data IPv6Addr = IPv6Addr T.Text
+
+instance Show IPv6Addr where
+    show (IPv6Addr addr) = T.unpack addr
+
+data IPv6AddrToken
+    = SixteenBit T.Text  -- ^ A four hexadecimal digits group representing a 16-Bit chunk
+    | AllZeros           -- ^ An all zeros 16-Bit chunk
+    | Colon              -- ^ A separator between 16-Bit chunks
+    | DoubleColon        -- ^ A double-colon stands for a unique compression of many consecutive 16-Bit chunks
+    | IPv4Addr T.Text    -- ^ An embedded IPv4 address as representation of the last 32-Bit
+    deriving (Eq,Show)
diff --git a/tests/QC/Rechunked.hs b/tests/QC/Rechunked.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Rechunked.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE BangPatterns #-}
+
+module QC.Rechunked (
+      rechunkBS
+    , rechunkT
+    ) where
+
+import Control.Monad (forM, forM_)
+import Control.Monad.ST (ST, runST)
+import Data.List (unfoldr)
+import Test.QuickCheck (Gen, choose)
+import qualified Data.ByteString as B
+import qualified Data.Text as T
+import qualified Data.Vector as V
+import qualified Data.Vector.Generic as G
+import qualified Data.Vector.Generic.Mutable as M
+
+rechunkBS :: B.ByteString -> Gen [B.ByteString]
+rechunkBS = fmap (map B.copy) . rechunk_ B.splitAt B.length
+
+rechunkT :: T.Text -> Gen [T.Text]
+rechunkT = fmap (map T.copy) . rechunk_ T.splitAt T.length
+
+rechunk_ :: (Int -> a -> (a,a)) -> (a -> Int) -> a -> Gen [a]
+rechunk_ split len xs = (unfoldr go . (,) xs) `fmap` rechunkSizes (len xs)
+  where go (b,r:rs)   = Just (h, (t,rs))
+          where (h,t) = split r b
+        go (_,_)      = Nothing
+
+rechunkSizes :: Int -> Gen [Int]
+rechunkSizes n0 = shuffle =<< loop [] (0:repeat 1) n0
+  where loop _ [] _ = error "it's 2015, where's my Stream type?"
+        loop acc (lb:lbs) n
+          | n <= 0 = shuffle (reverse acc)
+          | otherwise = do
+            !i <- choose (lb,n)
+            loop (i:acc) lbs (n-i)
+
+shuffle :: [Int] -> Gen [Int]
+shuffle (0:xs) = (0:) `fmap` shuffle xs
+shuffle xs = fisherYates xs
+
+fisherYates :: [a] -> Gen [a]
+fisherYates xs = (V.toList . V.backpermute v) `fmap` swapIndices (G.length v)
+  where
+    v = V.fromList xs
+    swapIndices n0 = do
+        swaps <- forM [0..n] $ \i -> ((,) i) `fmap` choose (i,n)
+        return (runST (swapAll swaps))
+      where
+        n = n0 - 1
+        swapAll :: [(Int,Int)] -> ST s (V.Vector Int)
+        swapAll ijs = do
+          mv <- G.unsafeThaw (G.enumFromTo 0 n :: V.Vector Int)
+          forM_ ijs $ uncurry (M.swap mv)
+          G.unsafeFreeze mv
diff --git a/tests/QC/Simple.hs b/tests/QC/Simple.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Simple.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+module QC.Simple (
+      tests
+    ) where
+
+import Control.Applicative ((<|>))
+import Data.ByteString (ByteString)
+import Data.List (foldl')
+import Data.Maybe (fromMaybe)
+import QC.Rechunked (rechunkBS)
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck (Property, counterexample, forAll)
+import qualified Data.Attoparsec.ByteString.Char8 as A
+
+t_issue75 = expect issue75 "ab" (A.Done "" "b")
+
+issue75 :: A.Parser ByteString
+issue75 = "a" >> ("b" <|> "")
+
+expect :: (Show r, Eq r) => A.Parser r -> ByteString -> A.Result r -> Property
+expect p input wanted =
+  forAll (rechunkBS input) $ \in' ->
+    let result = parse p in'
+    in counterexample (show result ++ " /= " ++ show wanted) $
+       fromMaybe False (A.compareResults result wanted)
+
+parse :: A.Parser r -> [ByteString] -> A.Result r
+parse p (x:xs) = foldl' A.feed (A.parse p x) xs
+parse p []     = A.parse p ""
+
+tests :: [TestTree]
+tests = [
+      testProperty "issue75" t_issue75
+  ]
diff --git a/tests/QC/Text.hs b/tests/QC/Text.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Text.hs
@@ -0,0 +1,203 @@
+{-# LANGUAGE BangPatterns, CPP, OverloadedStrings #-}
+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+module QC.Text (tests) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), (<$>))
+#endif
+import Data.Int (Int64)
+import Data.Word (Word8)
+import Prelude hiding (take, takeWhile)
+import QC.Common (liftOp, parseT)
+import qualified QC.Text.FastSet as FastSet
+import qualified QC.Text.Regressions as Regressions
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck
+import qualified Data.Attoparsec.Text as P
+import qualified Data.Attoparsec.Text.Lazy as PL
+import qualified Data.Attoparsec.Text.FastSet as S
+import qualified Data.ByteString as BS
+import qualified Data.Char as Char
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import qualified Data.Text.Lazy as L
+
+-- Basic byte-level combinators.
+
+satisfy :: Char -> L.Text -> Property
+satisfy w s = parseT (P.satisfy (<=w)) (L.cons w s) === Just w
+
+satisfyWith :: Char -> L.Text -> Property
+satisfyWith c s = parseT (P.satisfyWith id (<=c)) (L.cons c s) === Just c
+
+char :: Char -> L.Text -> Property
+char w s = parseT (P.char w) (L.cons w s) === Just w
+
+skip :: Char -> L.Text -> Property
+skip w s =
+  case (parseT (P.skip (<w)) s, L.uncons s) of
+    (Nothing, mcs) -> maybe (property True) (expectFailure . it) mcs
+    (Just _,  mcs) -> maybe (property False) it mcs
+  where it cs = liftOp "<" (<) (fst cs) w
+
+anyChar :: L.Text -> Property
+anyChar s
+    | L.null s  = p === Nothing
+    | otherwise = p === Just (L.head s)
+  where p = parseT P.anyChar s
+
+notChar :: Char -> NonEmptyList Char -> Property
+notChar w (NonEmpty s) = parseT (P.notChar w) bs === if v == w
+                                                      then Nothing
+                                                      else Just v
+    where v = L.head bs
+          bs = L.pack s
+
+peekChar :: L.Text -> Property
+peekChar s
+    | L.null s  = p === Just (Nothing, s)
+    | otherwise = p === Just (Just (L.head s), s)
+  where p = parseT ((,) <$> P.peekChar <*> P.takeLazyText) s
+
+peekChar' :: L.Text -> Property
+peekChar' s = parseT P.peekChar' s === (fst <$> L.uncons s)
+
+string :: L.Text -> L.Text -> Property
+string s t = parseT (P.string s') (s `L.append` t) === Just s'
+  where s' = toStrict s
+
+strings :: L.Text -> L.Text -> L.Text -> Property
+strings s t u =
+    parseT (P.string (toStrict s) >> P.string t') (L.concat [s,t,u])
+    === Just t'
+  where t' = toStrict t
+
+-- | Note: "simple, and efficient" works for well formed input...
+-- i.e. e.g. Latin1 texts
+stringCI :: [Word8] -> Property
+stringCI ws = P.parseOnly (P.stringCI fs) s === Right s
+  where fs = T.toCaseFold s
+        s  = TE.decodeLatin1 (BS.pack ws)
+
+asciiCI :: T.Text -> Gen Bool
+asciiCI x =
+  (\s i -> P.parseOnly (P.asciiCI s) i == Right i)
+    <$> maybeModifyCase x
+    <*> maybeModifyCase x
+  where
+    maybeModifyCase s = elements [s, toLower s, toUpper s]
+    toLower = T.map (\c -> if c < Char.chr 127 then Char.toLower c else c)
+    toUpper = T.map (\c -> if c < Char.chr 127 then Char.toUpper c else c)
+
+toStrict :: L.Text -> T.Text
+toStrict = T.concat . L.toChunks
+
+skipWhile :: Char -> L.Text -> Property
+skipWhile w s =
+    let t = L.dropWhile (<=w) s
+    in case PL.parse (P.skipWhile (<=w)) s of
+         PL.Done t' () -> t === t'
+         _             -> property False
+
+take :: Int -> L.Text -> Property
+take n s = maybe (liftOp "<" (<) (L.length s) (fromIntegral n))
+           (=== T.take n (toStrict s)) $
+           parseT (P.take n) s
+
+takeText :: L.Text -> Property
+takeText s = maybe (property False) (=== toStrict s) . parseT P.takeText $ s
+
+takeLazyText :: L.Text -> Property
+takeLazyText s = maybe (property False) (=== s) . parseT P.takeLazyText $ s
+
+takeCount :: Positive Int -> L.Text -> Property
+takeCount (Positive k) s =
+    case parseT (P.take k) s of
+      Nothing -> liftOp ">" (>) (fromIntegral k) (L.length s)
+      Just _s -> liftOp "<=" (<=) (fromIntegral k) (L.length s)
+
+takeWhile :: Char -> L.Text -> Property
+takeWhile w s =
+    let (h,t) = L.span (==w) s
+    in case PL.parse (P.takeWhile (==w)) s of
+         PL.Done t' h' -> t === t' .&&. toStrict h === h'
+         _             -> property False
+
+takeWhile1 :: Char -> L.Text -> Property
+takeWhile1 w s =
+  let s'    = L.cons w s
+      (h,t) = L.span (<=w) s'
+    in case PL.parse (P.takeWhile1 (<=w)) s' of
+         PL.Done t' h' -> t === t' .&&. toStrict h === h'
+         _             -> property False
+
+takeTill :: Char -> L.Text -> Property
+takeTill w s =
+    let (h,t) = L.break (==w) s
+    in case PL.parse (P.takeTill (==w)) s of
+         PL.Done t' h' -> t === t' .&&. toStrict h === h'
+         _             -> property False
+
+takeWhile1_empty :: Property
+takeWhile1_empty = parseT (P.takeWhile1 undefined) L.empty === Nothing
+
+endOfInput :: L.Text -> Property
+endOfInput s = parseT P.endOfInput s === if L.null s
+                                         then Just ()
+                                         else Nothing
+
+endOfLine :: L.Text -> Property
+endOfLine s =
+  case (parseT P.endOfLine s, L.uncons s) of
+    (Nothing, mcs) -> maybe (property True) (expectFailure . eol) mcs
+    (Just _,  mcs) -> maybe (property False) eol mcs
+  where eol (c,s') = c === '\n' .||.
+                     (c, fst <$> L.uncons s') === ('\r', Just '\n')
+
+scan :: L.Text -> Positive Int64 -> Property
+-- for some reason, if counterexample is removed, this test fails?
+scan s (Positive k) = counterexample (show s)
+                    $ parseT p s === Just (toStrict $ L.take k s)
+  where p = P.scan k $ \ n _ ->
+            if n > 0 then let !n' = n - 1 in Just n' else Nothing
+
+members :: String -> Property
+members s = property $ all (`S.member` set) s
+    where set = S.fromList s
+
+nonmembers :: String -> String -> Property
+nonmembers s s' = property . not . any (`S.member` set) $ filter (not . (`elem` s)) s'
+    where set = S.fromList s
+
+tests :: [TestTree]
+tests = [
+      testProperty "anyChar" anyChar
+    , testProperty "asciiCI" asciiCI
+    , testProperty "char" char
+    , testProperty "endOfInput" endOfInput
+    , testProperty "endOfLine" endOfLine
+    , testProperty "notChar" notChar
+    , testProperty "peekChar" peekChar
+    , testProperty "peekChar'" peekChar'
+    , testProperty "satisfy" satisfy
+    , testProperty "satisfyWith" satisfyWith
+    , testProperty "scan" scan
+    , testProperty "skip" skip
+    , testProperty "skipWhile" skipWhile
+    , testProperty "string" string
+    , testProperty "strings" strings
+    , testProperty "stringCI" stringCI
+    , testProperty "take" take
+    , testProperty "takeText" takeText
+    , testProperty "takeCount" takeCount
+    , testProperty "takeLazyText" takeLazyText
+    , testProperty "takeTill" takeTill
+    , testProperty "takeWhile" takeWhile
+    , testProperty "takeWhile1" takeWhile1
+    , testProperty "takeWhile1_empty" takeWhile1_empty
+    , testProperty "members" members
+    , testProperty "nonmembers" nonmembers
+    , testGroup "FastSet" FastSet.tests
+    , testGroup "Regressions" Regressions.tests
+  ]
diff --git a/tests/QC/Text/FastSet.hs b/tests/QC/Text/FastSet.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Text/FastSet.hs
@@ -0,0 +1,15 @@
+module QC.Text.FastSet where
+
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck
+import qualified Data.Attoparsec.Text.FastSet as FastSet
+
+membershipCorrect :: String -> String -> Property
+membershipCorrect members others =
+    let fs = FastSet.fromList members
+        correct c = (c `FastSet.member` fs) == (c `elem` members)
+    in property $ all correct (members ++ others)
+
+tests :: [TestTree]
+tests = [ testProperty "membership is correct" membershipCorrect ]
diff --git a/tests/QC/Text/Regressions.hs b/tests/QC/Text/Regressions.hs
new file mode 100644
--- /dev/null
+++ b/tests/QC/Text/Regressions.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module QC.Text.Regressions (
+      tests
+    ) where
+
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.List (foldl')
+import Data.Maybe (fromMaybe)
+import Data.Char (isLower)
+import Data.Monoid ((<>))
+import QC.Rechunked (rechunkT)
+import Test.Tasty (TestTree)
+import Test.Tasty.QuickCheck (testProperty)
+import Test.QuickCheck (Property, counterexample, forAll)
+import qualified Data.Attoparsec.Text as A
+
+
+--------------------------------------------------------------------------------
+-- 105 was about runScanner not always returning the final state. The result
+-- did depend on how the data was fed to the parser.
+
+t_issue105 :: Property
+t_issue105 = expect issue105 "lowER" (A.Done "ER" "low")
+
+issue105 :: A.Parser Text
+issue105 = do
+    (_, firstFourLowercaseLetters) <- A.runScanner "" f
+    return $ firstFourLowercaseLetters
+
+  where
+    f :: Text -> Char -> Maybe Text
+    f acc c = if T.length acc < 4 && isLower c
+        then Just $ acc <> T.singleton c
+        else Nothing
+
+
+expect :: (Show r, Eq r) => A.Parser r -> Text -> A.Result r -> Property
+expect p input wanted =
+  forAll (rechunkT input) $ \in' ->
+    let result = parse p in'
+    in counterexample (show result ++ " /= " ++ show wanted) $
+       fromMaybe False (A.compareResults result wanted)
+
+parse :: A.Parser r -> [Text] -> A.Result r
+parse p (x:xs) = foldl' A.feed (A.parse p x) xs
+parse p []     = A.parse p ""
+
+
+tests :: [TestTree]
+tests = [
+      testProperty "issue105" t_issue105
+  ]
diff --git a/tests/QCSupport.hs b/tests/QCSupport.hs
deleted file mode 100644
--- a/tests/QCSupport.hs
+++ /dev/null
@@ -1,52 +0,0 @@
-{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
-module QCSupport
-    (
-      NonEmpty(..)
-    ) where
-
-import Control.Applicative
-import Data.Attoparsec
-import Data.Word (Word8)
-import System.Random (RandomGen, Random(..))
-import Test.QuickCheck hiding (NonEmpty)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-
-integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
-integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
-                                        fromIntegral b :: Integer) g of
-                            (x,g') -> (fromIntegral x, g')
-
-newtype NonEmpty a = NonEmpty { nonEmpty :: a }
-    deriving (Eq, Ord, Read, Show)
-
-instance Functor NonEmpty where
-    fmap f (NonEmpty a) = NonEmpty (f a)
-
-instance Applicative NonEmpty where
-    NonEmpty f <*> NonEmpty a = NonEmpty (f a)
-    pure a                    = NonEmpty a
-
-instance Arbitrary a => Arbitrary (NonEmpty [a]) where
-    arbitrary   = NonEmpty <$> sized (\n -> choose (1,n+1) >>= vector)
-
-instance Arbitrary S.ByteString where
-    arbitrary   = S.pack <$> arbitrary
-
-instance Arbitrary (NonEmpty S.ByteString) where
-    arbitrary   = fmap S.pack <$> arbitrary
-
-instance Arbitrary L.ByteString where
-    arbitrary   = sized $ \n -> resize (round (sqrt (toEnum n :: Double)))
-                  ((L.fromChunks . map nonEmpty) <$> arbitrary)
-
-instance Arbitrary (NonEmpty L.ByteString) where
-    arbitrary   = sized $ \n -> resize (round (sqrt (toEnum n :: Double)))
-                  (fmap (L.fromChunks . map nonEmpty) <$> arbitrary)
-
-instance Random Word8 where
-    randomR = integralRandomR
-    random  = randomR (minBound,maxBound)
-
-instance Arbitrary Word8 where
-    arbitrary     = choose (minBound, maxBound)
diff --git a/tests/TestFastSet.hs b/tests/TestFastSet.hs
deleted file mode 100644
--- a/tests/TestFastSet.hs
+++ /dev/null
@@ -1,25 +0,0 @@
-module Main (main) where
-
-import Data.Word (Word8)
-import qualified Data.Attoparsec.FastSet as F
-import System.Random (Random(..), RandomGen)
-import Test.QuickCheck
-
-integralRandomR :: (Integral a, RandomGen g) => (a, a) -> g -> (a, g)
-integralRandomR (a,b) g = case randomR (fromIntegral a :: Int,
-                                        fromIntegral b :: Int) g
-                          of (x,g') -> (fromIntegral x, g')
-
-instance Random Word8 where
-  randomR = integralRandomR
-  random = randomR (minBound,maxBound)
-
-instance Arbitrary Word8 where
-    arbitrary = choose (minBound, maxBound)
-
-prop_AllMembers s =
-    let set = F.fromList s
-    in all (`F.memberWord8` set) s
-
-main = do
-  quickCheck prop_AllMembers
