@@ -1,4 +1,4 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
3-- Module: Data.Aeson.Encode
3-- Module: Data.Aeson.Encode
4-- Copyright: (c) 2011 MailRank, Inc.
4-- Copyright: (c) 2011 MailRank, Inc.
@@ -16,7 +16,6 @@ module Data.Aeson.Encode
18import Blaze.ByteString.Builder
18import Blaze.ByteString.Builder
19−import Blaze.ByteString.Builder.Internal.Write
20import Blaze.ByteString.Builder.Char.Utf8
19import Blaze.ByteString.Builder.Char.Utf8
21import Data.Aeson.Encode.Number (fromNumber)
20import Data.Aeson.Encode.Number (fromNumber)
22import Data.Aeson.Types (ToJSON(..), Value(..))
21import Data.Aeson.Types (ToJSON(..), Value(..))
@@ -26,6 +25,8 @@ import qualified Data.Map as M
26import qualified Data.Text as T
25import qualified Data.Text as T
27import qualified Data.Vector as V
26import qualified Data.Vector as V
28+import Blaze.ByteString.Builder.Internal
29+import qualified Data.Text.Fusion as F
29import Foreign
30import Foreign
31-- | Encode a JSON value to a 'Builder'.
32-- | Encode a JSON value to a 'Builder'.
@@ -60,7 +61,7 @@ encode = toLazyByteString . fromValue . toJSON
60-- unpacking to lists.
61-- unpacking to lists.
61string :: T.Text -> Builder
62string :: T.Text -> Builder
62string s =
63string s =
63− fromChar '"' `mappend` fromWriteList writeJSONChar (T.unpack s) `mappend` fromChar '"'
64+ fromChar '"' `mappend` fromWriteText writeJSONChar s `mappend` fromChar '"'
65{-# INLINE writeJSONChar #-}
66{-# INLINE writeJSONChar #-}
66writeJSONChar :: Char -> Write
67writeJSONChar :: Char -> Write
@@ -104,5 +105,55 @@ pokeWord16Hex x op = do
104 pokeWord8 :: Int -> Word8 -> IO ()
105 pokeWord8 :: Int -> Word8 -> IO ()
105 pokeWord8 off = poke (op `plusPtr` off)
106 pokeWord8 off = poke (op `plusPtr` off)
108+-- | Write a 'F.Stream' one element at a time to a builder using the given
110+{-# INLINE fromWriteStream #-}
111+fromWriteStream :: (a -> Write) -> F.Stream a -> Builder
112+fromWriteStream write =
115+ makeBuilder (F.Stream next s0 _) = fromBuildStepCont $ step s0
117+ step s1 k !(BufRange op0 ope0) = go s1 op0
119+ go s !op = case next s of
120+ F.Done -> do let !br' = BufRange op ope0
122+ F.Skip s' -> go s' op
124+ let maxSize = getBound (write x)
126+ | op `plusPtr` maxSize <= ope0 = do
127+ !op' <- runWrite (write x) op
129+ | otherwise = do return $ bufferFull maxSize op (step s k)
132+{-# INLINE fromWriteText #-}
133+fromWriteText :: (Char -> Write) -> T.Text -> Builder
134+fromWriteText w = fromWriteStream w . F.stream
137+fromWriteList :: (a -> Write) -> [a] -> Builder
138+fromWriteList write =
141+ makeBuilder xs0 = fromBuildStepCont $ step xs0
143+ step xs1 k !(BufRange op0 ope0) = go xs1 op0
146+ let !br' = BufRange op ope0
150+ | op `plusPtr` maxSize <= ope0 = do
151+ !op' <- runPoke wio op
153+ | otherwise = return $ bufferFull maxSize op (step xs k)
155+ Write maxSize wio = write x'
156+{-# INLINE fromWriteList #-}