json-enumerator (empty) → 0.0.0
raw patch · 4 files changed
+214/−0 lines, 4 filesdep +basedep +blaze-builderdep +blaze-builder-enumeratorsetup-changed
Dependencies added: base, blaze-builder, blaze-builder-enumerator, bytestring, containers, enumerator, json-types, text, transformers
Files
- LICENSE +25/−0
- Setup.hs +2/−0
- Text/JSON/Enumerator.hs +156/−0
- json-enumerator.cabal +31/−0
+ LICENSE view
@@ -0,0 +1,25 @@+The following license covers this documentation, and the source code, except+where otherwise indicated.++Copyright 2010, Suite Solutions. All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Text/JSON/Enumerator.hs view
@@ -0,0 +1,156 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveDataTypeable #-}+module Text.JSON.Enumerator+ ( renderEvents+ , renderEventsToBytes+ , renderValue+ , renderAtom+ , JsonException (..)+ ) where++import qualified Data.Enumerator as E+import Data.Enumerator ((>>==), ($$))+import Blaze.ByteString.Builder (Builder, fromByteString)+import Blaze.ByteString.Builder.Char8 (fromChar, fromShow)+import Blaze.ByteString.Builder.Enumerator (builderToByteString)+import Data.Monoid (mappend, mconcat)+import Data.Text.Lazy (Text, unpack)+import Data.ByteString (ByteString)+import Data.ByteString.Char8 ()+import Control.Exception (Exception)+import Data.Typeable (Typeable)+import Blaze.ByteString.Builder.Internal (fromWriteList)+import Blaze.ByteString.Builder.Char.Utf8 (writeChar)+import Blaze.ByteString.Builder.ByteString (writeByteString)+import Data.Bits (shiftR, (.&.))+import Data.JSON.Types+import Control.Monad.IO.Class (MonadIO)+import Data.List (foldl')+import qualified Data.Map as Map++data GState = NoState+ | InArray GState+ | InArray1 GState+ | InObject GState+ | InObjectValue GState+ | InObject1 GState+ deriving Show++renderEvents :: Monad m => E.Enumeratee Event Builder m b+renderEvents =+ loop NoState+ where+ loop state = E.checkDone $ \k -> do+ me <- E.head+ case me of+ Nothing -> k E.EOF >>== return+ Just e -> do+ (bs, state') <- go e state+ k (E.Chunks [bs]) >>== loop state'++ go EventEndArray (InArray s) = return (fromChar ']', s)+ go EventEndArray (InArray1 s) = return (fromChar ']', s)+ go EventEndArray s = E.throwError $ UnexpectedEndArray s+ go EventEndObject (InObject s) = return (fromChar '}', s)+ go EventEndObject (InObject1 s) = return (fromChar '}', s)+ go EventEndObject s = E.throwError $ UnexpectedEndObject s+ go EventBeginArray s =+ let (b, s') = incrState s+ in return (b $ fromChar '[', InArray s')+ go EventBeginObject s =+ let (b, s') = incrState s+ in return (b $ fromChar '{', InObject s')+ go (EventAttributeName t) (InObject s) = return (escape t, InObjectValue s)+ go (EventAttributeName t) (InObject1 s) = return (fromChar ',' `mappend` escape t, InObjectValue s)+ go (EventAttributeName n) s = E.throwError $ UnexpectedAttributeName n s+ go (EventAtom a) s = scalar (renderAtom a) s++ incrState (InArray s) = (id, InArray1 s)+ incrState (InArray1 s) = (mappend $ fromChar ',', InArray1 s)+ incrState (InObject s) = (id, InObjectValue s)+ incrState (InObject1 s) = (mappend $ fromChar ',', InObjectValue s)+ incrState (InObjectValue s) = (mappend $ fromChar ':', InObject1 s)+ incrState NoState = (id, NoState)++ scalar _ (InObject s) = E.throwError $ ExpectedAttributeName s+ scalar _ (InObject1 s) = E.throwError $ ExpectedAttributeName s+ scalar b s =+ let (b', s') = incrState s+ in return (b' b, s')++data JsonException = UnexpectedEndArray GState+ | UnexpectedEndObject GState+ | UnexpectedAttributeName Text GState+ | ExpectedAttributeName GState+ deriving (Show, Typeable)+instance Exception JsonException++renderEventsToBytes :: MonadIO m => E.Enumeratee Event ByteString m b+renderEventsToBytes s = E.joinI $ renderEvents $$ builderToByteString s++renderValue :: Value -> Builder+renderValue (ValueAtom a) = renderAtom a+renderValue (ValueArray []) = fromByteString "[]"+renderValue (ValueArray (x:xs)) =+ foldl' go (fromChar '[' `mappend` renderValue x) xs+ `mappend` fromChar ']'+ where+ go y a = y `mappend` fromChar ',' `mappend` renderValue a+renderValue (ValueObject o) =+ case Map.toList o of+ [] -> fromByteString "{}"+ (x:xs) -> foldl' go (fromChar '{' `mappend` renderPair x) xs+ `mappend` fromChar '}'+ where+ renderPair (k, v) = escape k `mappend` fromChar ':' `mappend` renderValue v+ go y p = y `mappend` fromChar ',' `mappend` renderPair p++renderAtom :: Atom -> Builder+renderAtom AtomNull = fromByteString "null"+renderAtom (AtomBoolean True) = fromByteString "true"+renderAtom (AtomBoolean False) = fromByteString "false"+renderAtom (AtomNumber r) = fromShow (fromRational r :: Double)+renderAtom (AtomText t) = escape t++escape :: Text -> Builder+escape t = mconcat+ [ fromChar '"'+ , fromWriteList writeJChar $ unpack t+ , fromChar '"'+ ]+ where+ writeJChar '\"' = writeByteString "\\\""+ writeJChar '\\' = writeByteString "\\\\"+ writeJChar '/' = writeByteString "\\/"+ writeJChar '\b' = writeByteString "\\b"+ writeJChar '\f' = writeByteString "\\f"+ writeJChar '\n' = writeByteString "\\n"+ writeJChar '\r' = writeByteString "\\r"+ writeJChar '\t' = writeByteString "\\t"+ writeJChar c+ | c < '\x10' = writeByteString "\\u000"+ `mappend` writeChar (hex $ fromEnum c)+ | c < '\x20' = writeByteString "\\u00"+ `mappend` writeChar (hex i1)+ `mappend` writeChar (hex i2)+ where+ i = fromEnum c+ i1 = i `shiftR` 4+ i2 = i .&. 15+ hex 0 = '0'+ hex 1 = '1'+ hex 2 = '2'+ hex 3 = '3'+ hex 4 = '4'+ hex 5 = '5'+ hex 6 = '6'+ hex 7 = '7'+ hex 8 = '8'+ hex 9 = '9'+ hex 10 = 'A'+ hex 11 = 'B'+ hex 12 = 'C'+ hex 13 = 'D'+ hex 14 = 'E'+ hex 15 = 'F'+ writeJChar c = writeChar c
+ json-enumerator.cabal view
@@ -0,0 +1,31 @@+name: json-enumerator+version: 0.0.0+license: BSD3+license-file: LICENSE+author: Michael Snoyman <michaels@suite-sol.com>+maintainer: Michael Snoyman <michaels@suite-sol.com>+synopsis: Pure-Haskell utilities for dealing with JSON with the enumerator package.+description:+ Provides the ability to render JSON in a streaming manner using the enumerator package.+category: JSON, Enumerator+stability: Stable+cabal-version: >= 1.6+build-type: Simple+homepage: http://github.com/snoyberg/json-enumerator++library+ build-depends: base >= 4 && < 5+ , enumerator >= 0.4 && < 0.5+ , bytestring >= 0.9 && < 0.10+ , text >= 0.7 && < 0.12+ , containers >= 0.2 && < 0.5+ , json-types >= 0.1 && < 0.2+ , blaze-builder >= 0.2.1.0 && < 0.3+ , blaze-builder-enumerator >= 0.2 && < 0.3+ , transformers >= 0.2 && < 0.3+ exposed-modules: Text.JSON.Enumerator+ ghc-options: -Wall++source-repository head+ type: git+ location: git://github.com/snoyberg/json-enumerator.git