@@ -66,6 +66,8 @@ import qualified Data.Iteratee.Base.StreamChunk as SC
66import Control.Applicative
66import Control.Applicative
67import Control.Monad.CatchIO (MonadCatchIO, finally)
67import Control.Monad.CatchIO (MonadCatchIO, finally)
69+import qualified Data.ListLike as LL
69data Event =
71data Event =
71 | EventStreamStart
73 | EventStreamStart
@@ -379,55 +381,12 @@ foreign import ccall unsafe "get_buffer_buff"
379foreign import ccall unsafe "get_buffer_used"
381foreign import ccall unsafe "get_buffer_used"
380 c_get_buffer_used :: Buffer -> IO CULong
382 c_get_buffer_used :: Buffer -> IO CULong
382−withBufferR :: (With m, MonadFailure YamlException m)
385−withBufferR f = allocaBytesR bufferSize $ \b -> do
386− liftIO $ c_buffer_init b
388− ptr' <- liftIO $ c_get_buffer_buff b
389− len <- liftIO $ c_get_buffer_used b
390− fptr <- liftIO $ newForeignPtr_ $ castPtr ptr'
391− return $ B.fromForeignPtr fptr 0 $ fromIntegral len
393foreign import ccall unsafe "my_emitter_set_output"
384foreign import ccall unsafe "my_emitter_set_output"
394 c_my_emitter_set_output :: Emitter -> Buffer -> IO ()
385 c_my_emitter_set_output :: Emitter -> Buffer -> IO ()
396−withEmitter :: (With m, MonadFailure YamlException m)
397− => (Emitter -> m ())
399−withEmitter f = allocaBytesR emitterSize $ \e -> do
400− res <- liftIO $ c_yaml_emitter_initialize e
401− when (res == 0) $ failure YamlOutOfMemory
402− bs <- withBufferR $ \b -> do
403− liftIO $ c_my_emitter_set_output e b
405− liftIO $ c_yaml_emitter_delete e -- FIXME finally
408foreign import ccall unsafe "yaml_emitter_set_output_file"
387foreign import ccall unsafe "yaml_emitter_set_output_file"
409 c_yaml_emitter_set_output_file :: Emitter -> File -> IO ()
388 c_yaml_emitter_set_output_file :: Emitter -> File -> IO ()
411−withEmitterFile :: (With m, MonadFailure YamlException m)
413− -> (Emitter -> m ())
415−withEmitterFile fp f = allocaBytesR emitterSize $ \e -> do
416− res <- liftIO $ c_yaml_emitter_initialize e
417− when (res == 0) $ failure YamlOutOfMemory
418− file <- withCStringR fp $ \fp' -> withCStringR "w" $ \w' ->
419− liftIO (c_fopen fp' w')
422− then failure $ YamlFileNotFound fp
424− liftIO $ c_yaml_emitter_set_output_file e file
426− liftIO $ c_yaml_emitter_delete e
428− liftIO $ c_fclose file -- FIXME use finally
431foreign import ccall unsafe "yaml_emitter_emit"
390foreign import ccall unsafe "yaml_emitter_emit"
432 c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
391 c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
@@ -625,17 +584,6 @@ newtype ToEventRawException = ToEventRawException CInt
625 deriving (Show, Typeable)
584 deriving (Show, Typeable)
626instance Exception ToEventRawException
585instance Exception ToEventRawException
628−encode :: (With m, MonadFailure YamlException m)
631−encode = withEmitter . runReaderT
633−encodeFile :: (With m, MonadFailure YamlException m)
637−encodeFile filePath = withEmitterFile filePath . runReaderT
639decode :: SC.StreamChunk c Event
587decode :: SC.StreamChunk c Event
640 => MonadCatchIO m
588 => MonadCatchIO m
641 => B.ByteString
589 => B.ByteString
@@ -709,3 +657,55 @@ parserParseOne' parser = allocaBytesR eventSize $ \er -> do
709 c_get_parser_error_offset parser
657 c_get_parser_error_offset parser
710 return $ Left $ YamlParserException problem context offset
658 return $ Left $ YamlParserException problem context offset
711 else liftIO $ Right <$> getEvent er
659 else liftIO $ Right <$> getEvent er
661+encode :: SC.StreamChunk c Event
663+ => IterateeG c Event m B.ByteString
664+encode = joinIM $ liftIO $ do
665+ fp <- mallocForeignPtrBytes emitterSize
666+ res <- withForeignPtr fp c_yaml_emitter_initialize
667+ when (res == 0) $ fail "c_yaml_emitter_initialize failed"
668+ buf <- mallocForeignPtrBytes bufferSize
669+ withForeignPtr buf c_buffer_init
671+ \emitter -> withForeignPtr buf $
672+ \b -> c_my_emitter_set_output emitter b
673+ return $ runEmitter (go buf) fp
675+ go buf = withForeignPtr buf $ \b -> do
676+ ptr' <- c_get_buffer_buff b
677+ len <- c_get_buffer_used b
678+ fptr <- newForeignPtr_ $ castPtr ptr'
679+ return $ B.fromForeignPtr fptr 0 $ fromIntegral len
682+encodeFile :: SC.StreamChunk c Event
685+ -> IterateeG c Event m ()
686+encodeFile filePath = joinIM $ liftIO $ do
687+ fp <- mallocForeignPtrBytes emitterSize
688+ res <- withForeignPtr fp c_yaml_emitter_initialize
689+ when (res == 0) $ fail "c_yaml_emitter_initialize failed"
690+ file <- withCStringR filePath $
691+ \filePath' -> withCStringR "w" $
692+ \w' -> c_fopen filePath' w'
693+ when (file == nullPtr) $ fail $ "could not open file for write: " ++ filePath
694+ withForeignPtr fp $ flip c_yaml_emitter_set_output_file file
695+ return $ runEmitter (c_fclose file) fp
697+runEmitter :: SC.StreamChunk c Event
700+ -> ForeignPtr EmitterStruct
701+ -> IterateeG c Event m a
702+runEmitter close fp = IterateeG go
705+ liftIO $ withForeignPtr fp c_yaml_emitter_delete
707+ return $ Done a $ EOF x
709+ liftIO $ withForeignPtr fp $ \emitter ->
710+ LL.mapM_ (\e -> toEventRaw e $ c_yaml_emitter_emit emitter) c
711+ return $ Cont (runEmitter close fp) Nothing