@@ -2,6 +2,7 @@
2{-# LANGUAGE ForeignFunctionInterface #-}
2{-# LANGUAGE ForeignFunctionInterface #-}
3{-# LANGUAGE DeriveDataTypeable #-}
3{-# LANGUAGE DeriveDataTypeable #-}
4{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE PackageImports #-}
7{-# LANGUAGE PackageImports #-}
7{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE TypeFamilies #-}
@@ -16,6 +17,9 @@ module Text.Libyaml
16 -- * Enumerator
17 -- * Enumerator
17 , EnumResult (..)
18 , EnumResult (..)
18 , RMonadIO (..)
19 , RMonadIO (..)
19 -- * Higher level functions
23 -- * Higher level functions
@@ -34,6 +38,7 @@ import Foreign.ForeignPtr
34import Foreign.Marshal.Alloc
38import Foreign.Marshal.Alloc
35import "transformers" Control.Monad.Trans
39import "transformers" Control.Monad.Trans
36import Control.Failure
40import Control.Failure
41+import Control.Applicative
38import Control.Exception (throwIO, Exception, SomeException)
43import Control.Exception (throwIO, Exception, SomeException)
39import Data.Typeable (Typeable)
44import Data.Typeable (Typeable)
@@ -160,20 +165,16 @@ foreign import ccall unsafe "fclose"
162class MonadIO m => RMonadIO m where
167class MonadIO m => RMonadIO m where
163− type Inside :: * -> *
168+ withR :: ((a -> IO b) -> IO b) -> (a -> m b) -> m b
164− ioOut :: m v -> IO (Inside v)
169+
165− ioIn :: IO (Inside v) -> m v
166−newtype SimpleIdent x = SimpleIdent { unSimpleIdent :: x }
167instance RMonadIO IO where
170instance RMonadIO IO where
168− type Inside = SimpleIdent
171+ withR = id
169− ioOut = fmap SimpleIdent
170− ioIn = fmap unSimpleIdent
172allocaBytesR :: RMonadIO m => Int -> (Ptr a -> m b) -> m b
173allocaBytesR :: RMonadIO m => Int -> (Ptr a -> m b) -> m b
173−allocaBytesR i f = ioIn $ allocaBytes i $ ioOut . f
174+allocaBytesR = withR . allocaBytes
175withCStringR :: RMonadIO m => String -> (Ptr CChar -> m a) -> m a
176withCStringR :: RMonadIO m => String -> (Ptr CChar -> m a) -> m a
176−withCStringR s f = ioIn $ withCString s $ ioOut . f
177+withCStringR = withR . withCString
178withFileParser :: (MonadFailure YamlException m, RMonadIO m)
179withFileParser :: (MonadFailure YamlException m, RMonadIO m)
179 => FilePath
180 => FilePath
@@ -207,11 +208,8 @@ withParser bs f = allocaBytesR parserSize $ \p -> do
207 liftIO $ c_yaml_parser_delete p -- FIXME use finally
208 liftIO $ c_yaml_parser_delete p -- FIXME use finally
208 return ret
209 return ret
210−withForeignPtrR :: RMonadIO m
211+withForeignPtrR :: RMonadIO m => ForeignPtr a -> (Ptr a -> m b) -> m b
214−withForeignPtrR fp f = ioIn $ withForeignPtr fp $ ioOut . f
212+withForeignPtrR = withR . withForeignPtr
216foreign import ccall unsafe "yaml_parser_parse"
214foreign import ccall unsafe "yaml_parser_parse"
217 c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
215 c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
@@ -359,7 +357,7 @@ withBufferR :: (RMonadIO m, MonadFailure YamlException m)
359 -> m B.ByteString
357 -> m B.ByteString
360withBufferR f = allocaBytesR bufferSize $ \b -> do
358withBufferR f = allocaBytesR bufferSize $ \b -> do
361 liftIO $ c_buffer_init b
359 liftIO $ c_buffer_init b
363 ptr' <- liftIO $ c_get_buffer_buff b
361 ptr' <- liftIO $ c_get_buffer_buff b
364 len <- liftIO $ c_get_buffer_used b
362 len <- liftIO $ c_get_buffer_used b
365 fptr <- liftIO $ newForeignPtr_ $ castPtr ptr'
363 fptr <- liftIO $ newForeignPtr_ $ castPtr ptr'
@@ -409,19 +407,39 @@ foreign import ccall unsafe "yaml_emitter_emit"
409foreign import ccall unsafe "get_emitter_error"
407foreign import ccall unsafe "get_emitter_error"
410 c_get_emitter_error :: Emitter -> IO (Ptr CUChar)
408 c_get_emitter_error :: Emitter -> IO (Ptr CUChar)
412−emitEvents :: (MonadFailure YamlException m, RMonadIO m)
410+emitEvent :: (MonadIO m, MonadFailure YamlException m)
413− => (a -> Maybe (Event, a))
411+ => Event
414− -> a
412+ -> YamlEncoder m ()
415− -> Emitter
413+emitEvent e = YamlEncoder $ \emitter -> do
417−emitEvents unfold src emitter = case unfold src of
418− Nothing -> return ()
419− Just (e, src') -> do
420− res <- liftIO $ toEventRaw e $ c_yaml_emitter_emit emitter
414+ res <- liftIO $ toEventRaw e $ c_yaml_emitter_emit emitter
421− when (res == 0) $ do
415+ when (res == 0) $ do
422− problem <- liftIO $ makeString c_get_emitter_error emitter
416+ problem <- liftIO $ makeString c_get_emitter_error emitter
423− failure $ YamlEmitterException e problem
417+ failure $ YamlEmitterException e problem
424− emitEvents unfold src' emitter
418+
419+data YamlEncoder m v = YamlEncoder { runYamlEncoder :: Emitter -> m v }
420+instance Monad m => Functor (YamlEncoder m) where
421+ fmap f (YamlEncoder e) = YamlEncoder $ \em -> f `liftM` e em
422+instance Monad m => Applicative (YamlEncoder m) where
423+ pure v = YamlEncoder $ const $ return v
424+ (YamlEncoder f') <*> (YamlEncoder v') = YamlEncoder $ \e -> do
428+instance Monad m => Monad (YamlEncoder m) where
430+ (YamlEncoder v') >>= f = YamlEncoder $ \e -> do
432+ (runYamlEncoder $ f v) e
433+instance MonadTrans YamlEncoder where
434+ lift = YamlEncoder . const
435+instance MonadIO m => MonadIO (YamlEncoder m) where
436+ liftIO = lift . liftIO
437+instance RMonadIO m => RMonadIO (YamlEncoder m) where
438+ withR orig f = YamlEncoder $ \e -> do
439+ let f' a = (runYamlEncoder $ f a) e
441+instance MonadFailure e m => Failure e (YamlEncoder m) where
442+ failure = lift . failure
426foreign import ccall unsafe "yaml_stream_start_event_initialize"
444foreign import ccall unsafe "yaml_stream_start_event_initialize"
427 c_yaml_stream_start_event_initialize :: EventRaw -> CInt -> IO CInt
445 c_yaml_stream_start_event_initialize :: EventRaw -> CInt -> IO CInt
@@ -537,18 +555,15 @@ data EnumResult a b = More a | Done b
537 deriving (Eq, Show)
555 deriving (Eq, Show)
539encode :: (RMonadIO m, MonadFailure YamlException m)
557encode :: (RMonadIO m, MonadFailure YamlException m)
540− => (a -> Maybe (Event, a))
558+ => YamlEncoder m ()
542 -> m B.ByteString
559 -> m B.ByteString
543−encode unfold src = withEmitter $ emitEvents unfold src
560+encode = withEmitter . runYamlEncoder
545encodeFile :: (RMonadIO m, MonadFailure YamlException m)
562encodeFile :: (RMonadIO m, MonadFailure YamlException m)
546 => FilePath
563 => FilePath
547− -> (a -> Maybe (Event, a))
564+ -> YamlEncoder m ()
550−encodeFile filePath unfold src =
551− withEmitterFile filePath $ emitEvents unfold src
566+encodeFile filePath enc = withEmitterFile filePath $ runYamlEncoder enc
553decode :: (RMonadIO m, MonadFailure YamlException m)
568decode :: (RMonadIO m, MonadFailure YamlException m)
554 => B.ByteString
569 => B.ByteString