yajl-enumerator 0.2.0.4 → 0.3
raw patch · 2 files changed
+61/−62 lines, 2 files
Files
- Text/JSON/YAJL/Enumerator.hs +60/−61
- yajl-enumerator.cabal +1/−1
Text/JSON/YAJL/Enumerator.hs view
@@ -13,9 +13,7 @@ -- * Parsing , parseBytesIO- , parseTextIO , parseBytesST- , parseTextST -- * Generating , Y.GeneratorConfig (..)@@ -51,21 +49,37 @@ | EventBeginObject | EventAttributeName T.Text | EventEndObject- deriving (Show)+ deriving (Show, Eq) -- Parser {{{ parseBytesIO :: MonadIO m => E.Enumeratee B.ByteString Event m b-parseBytesIO = parseIO Y.parseBytes--parseTextIO :: MonadIO m => E.Enumeratee T.Text Event m b-parseTextIO = parseIO Y.parseText+parseBytesIO s = do+ (p, eventRef) <- liftIO newParserIO+ + let withEvents io = liftIO $ do+ IO.writeIORef eventRef []+ status <- io+ events <- IO.readIORef eventRef+ return (reverse events, status)+ + let parseChunk bytes = withEvents (Y.parseBytes p bytes)+ let complete = withEvents (Y.parseComplete p)+ eneeParser (liftIO (Y.getBytesConsumed p)) parseChunk complete s parseBytesST :: E.Enumeratee B.ByteString Event (ST s) b-parseBytesST = parseST Y.parseBytes--parseTextST :: E.Enumeratee T.Text Event (ST s) b-parseTextST = parseST Y.parseText+parseBytesST s = do+ (p, eventRef) <- lift newParserST+ + let withEvents st = do+ ST.writeSTRef eventRef []+ status <- st+ events <- ST.readSTRef eventRef+ return (reverse events, status)+ + let parseChunk bytes = withEvents (Y.parseBytes p bytes)+ let complete = withEvents (Y.parseComplete p)+ eneeParser (Y.getBytesConsumed p) parseChunk complete s newParserIO :: IO (Y.Parser IO, IO.IORef [Event]) newParserIO = do@@ -97,64 +111,45 @@ set Y.parsedAttributeText (addEvent . EventAttributeName) set Y.parsedText (addEvent . EventText) -parseIO :: MonadIO m- => (Y.Parser IO -> a -> IO Y.ParseStatus)- -> E.Enumeratee a Event m b-parseIO parseFn s = do- (p, eventRef) <- liftIO newParserIO- - let withEvents io = liftIO $ do- IO.writeIORef eventRef []- status <- io- events <- IO.readIORef eventRef- return (reverse events, status)- - let parseChunk bytes = withEvents (parseFn p bytes)- let complete = withEvents (Y.parseComplete p)- eneeParser parseChunk complete s--parseST :: (Y.Parser (ST s) -> a -> ST s Y.ParseStatus)- -> E.Enumeratee a Event (ST s) b-parseST parseFn s = do- (p, eventRef) <- lift newParserST- - let withEvents st = do- ST.writeSTRef eventRef []- status <- st- events <- ST.readSTRef eventRef- return (reverse events, status)- - let parseChunk bytes = withEvents (parseFn p bytes)- let complete = withEvents (Y.parseComplete p)- eneeParser parseChunk complete s- eneeParser :: Monad m- => (a -> m ([Event], Y.ParseStatus))+ => m Integer+ -> (B.ByteString -> m ([Event], Y.ParseStatus)) -> m ([Event], Y.ParseStatus)- -> E.Enumeratee a Event m b-eneeParser parseChunk parseComplete = E.checkDone (E.continue . step) where+ -> E.Enumeratee B.ByteString Event m b+eneeParser getBytesConsumed parseChunk parseComplete = E.checkDone (E.continue . step) where step k (E.Chunks xs) = parseLoop k xs- step k E.EOF = checkEvents k E.EOF parseComplete- (\k' -> E.yield (E.Continue k') E.EOF)- (\_ -> throwError (T.pack "Unexpected EOF"))+ step k E.EOF = do+ (events, status) <- lift parseComplete+ checkStatus status events E.EOF k+ (\_ -> throwError "yajl-enumerator: Unexpected EOF while parsing") parseLoop k [] = E.continue (step k)- parseLoop k (x:xs) = checkEvents k (E.Chunks xs) (parseChunk x)- (\k' -> E.yield (E.Continue k') (E.Chunks xs))- (\k' -> parseLoop k' xs)+ parseLoop k (x:xs) = do+ (events, status) <- lift (parseChunk x)+ extra <- getExtra x xs status+ checkStatus status events extra k+ (\k' -> parseLoop k' xs) - checkEvents k extra getEvents onFinished onContinue = do- (events, status) <- lift getEvents- let checkError k' = case status of- Y.ParseError err -> throwError err- Y.ParseFinished -> onFinished k'+ getExtra x xs Y.ParseFinished = do+ consumed <- lift getBytesConsumed+ let extraX = B.drop (fromInteger consumed) x+ return . E.Chunks $ if null extraX+ then xs+ else extraX:xs+ getExtra _ _ _ = return (E.Chunks [])+ + checkStatus status events extra k onContinue = iter where+ checkError k' = case status of+ Y.ParseError err -> throwError (T.unpack err)+ Y.ParseFinished -> E.yield (E.Continue k') extra Y.ParseContinue -> onContinue k'- Y.ParseCancelled -> throwError (T.pack "Parse cancelled")- if null events+ Y.ParseCancelled -> throwError "Parse cancelled"+ + iter = if null events then checkError k else k (E.Chunks events) >>== E.checkDoneEx extra checkError - throwError = E.throwError . Exc.ErrorCall . T.unpack+ throwError = E.throwError . Exc.ErrorCall -- }}} @@ -227,11 +222,15 @@ eneeGenerator genEvent takeBuf = E.checkDone (E.continue . step) where step k (E.Chunks []) = E.continue (step k) step k (E.Chunks xs) = parseLoop k xs- step k E.EOF = E.yield (E.Continue k) E.EOF+ step k E.EOF = do+ maybeError <- lift (genEvent EventNull)+ case maybeError of+ Just Y.GenerationComplete -> E.yield (E.Continue k) E.EOF+ _ -> E.throwError (Exc.ErrorCall "yajl-enumerator: Unexpected EOF while generating") parseLoop k [] = checkBuf k [] (E.continue . step) parseLoop k (x:xs) = do- maybeError <- lift $ genEvent x+ maybeError <- lift (genEvent x) case maybeError of Just Y.GenerationComplete -> checkBuf k xs (\k' -> E.yield (E.Continue k') (E.Chunks (x:xs)))
yajl-enumerator.cabal view
@@ -1,5 +1,5 @@ name: yajl-enumerator-version: 0.2.0.4+version: 0.3 synopsis: Enumerator-based interface to YAJL, an event-based JSON implementation license: GPL-3 license-file: license.txt