@@ -0,0 +1,310 @@
1+{-# LANGUAGE EmptyDataDecls #-}
2+{-# LANGUAGE ForeignFunctionInterface #-}
4+{-# INCLUDE <yaml.h> #-}
5+{-# INCLUDE <helper.h> #-}
16+import qualified Data.ByteString.Internal as B
20+import Foreign.ForeignPtr
21+import Foreign.Marshal.Alloc
24+type Parser = Ptr ParserStruct
29+type EventRaw = Ptr EventRawStruct
33+foreign import ccall unsafe "yaml_parser_initialize"
34+ c_yaml_parser_initialize :: Parser -> IO CInt
36+foreign import ccall unsafe "yaml_parser_delete"
37+ c_yaml_parser_delete :: Parser -> IO ()
39+foreign import ccall unsafe "yaml_parser_set_input_string"
40+ c_yaml_parser_set_input_string :: Parser
45+withParser :: B.ByteString -> (Parser -> IO a) -> IO a
47+ allocaBytes parserSize $ \p ->
49+ _res <- c_yaml_parser_initialize p
51+ let (fptr, offset, len) = B.toForeignPtr bs
52+ ret <- withForeignPtr fptr $ \ptr ->
54+ let ptr' = castPtr ptr `plusPtr` offset
55+ len' = fromIntegral len
56+ c_yaml_parser_set_input_string p ptr' len'
58+ c_yaml_parser_delete p
61+withEventRaw :: (EventRaw -> IO a) -> IO a
62+withEventRaw f = allocaBytes eventSize $ f
64+foreign import ccall unsafe "yaml_parser_parse"
65+ c_yaml_parser_parse :: Parser -> EventRaw -> IO CInt
67+foreign import ccall unsafe "yaml_event_delete"
68+ c_yaml_event_delete :: EventRaw -> IO ()
70+foreign import ccall "print_parser_error"
71+ c_print_parser_error :: Parser -> IO ()
73+parserParseOne :: Parser -> IO Event
74+parserParseOne parser = withEventRaw $ \er -> do
75+ res <- c_yaml_parser_parse parser er
77+ c_print_parser_error parser >> fail "yaml_parser_parse failed"
79+ c_yaml_event_delete er
89+ | EventScalar B.ByteString
96+data EventType = YamlNoEvent
97+ | YamlStreamStartEvent
99+ | YamlDocumentStartEvent
100+ | YamlDocumentEndEvent
103+ | YamlSequenceStartEvent
104+ | YamlSequenceEndEvent
105+ | YamlMappingStartEvent
106+ | YamlMappingEndEvent
107+ deriving (Enum,Show)
109+foreign import ccall unsafe "get_event_type"
110+ c_get_event_type :: EventRaw -> IO CInt
112+foreign import ccall unsafe "get_scalar_value"
113+ c_get_scalar_value :: EventRaw -> IO (Ptr CUChar)
115+foreign import ccall unsafe "get_scalar_length"
116+ c_get_scalar_length :: EventRaw -> IO CULong
118+getEvent :: EventRaw -> IO Event
120+ et <- c_get_event_type er
121+ case toEnum $ fromEnum et of
122+ YamlNoEvent -> return EventNone
123+ YamlStreamStartEvent -> return EventStreamStart
124+ YamlStreamEndEvent -> return EventStreamEnd
125+ YamlDocumentStartEvent -> return EventDocumentStart
126+ YamlDocumentEndEvent -> return EventDocumentEnd
127+ YamlAliasEvent -> return EventAlias
128+ YamlScalarEvent -> do
129+ yvalue <- c_get_scalar_value er
130+ ylen <- c_get_scalar_length er
131+ let yvalue' = castPtr yvalue
132+ let ylen' = fromEnum ylen
133+ let ylen'' = toEnum $ fromEnum ylen
134+ bs <- B.create ylen' $ \dest -> B.memcpy dest yvalue' ylen''
135+ return $ EventScalar bs
136+ YamlSequenceStartEvent -> return EventSequenceStart
137+ YamlSequenceEndEvent -> return EventSequenceEnd
138+ YamlMappingStartEvent -> return EventMappingStart
139+ YamlMappingEndEvent -> return EventMappingEnd
141+parserParse :: Parser -> IO [Event]
142+parserParse parser = do
143+ event <- parserParseOne parser
145+ EventStreamEnd -> return [event]
147+ rest <- parserParse parser
148+ return $! event : rest
153+type Emitter = Ptr EmitterStruct
157+foreign import ccall unsafe "yaml_emitter_initialize"
158+ c_yaml_emitter_initialize :: Emitter -> IO CInt
160+foreign import ccall unsafe "yaml_emitter_delete"
161+ c_yaml_emitter_delete :: Emitter -> IO ()
164+type Buffer = Ptr BufferStruct
168+foreign import ccall unsafe "buffer_init"
169+ c_buffer_init :: Buffer -> IO ()
171+foreign import ccall unsafe "get_buffer_buff"
172+ c_get_buffer_buff :: Buffer -> IO (Ptr CUChar)
174+foreign import ccall unsafe "get_buffer_used"
175+ c_get_buffer_used :: Buffer -> IO CULong
177+withBuffer :: (Buffer -> IO ()) -> IO B.ByteString
179+ allocaBytes bufferSize $ \b -> do
182+ ptr' <- c_get_buffer_buff b
183+ len <- c_get_buffer_used b
184+ fptr <- newForeignPtr_ $ castPtr ptr'
185+ return $! B.fromForeignPtr fptr 0 $ fromIntegral len
187+foreign import ccall unsafe "my_emitter_set_output"
188+ c_my_emitter_set_output :: Emitter -> Buffer -> IO ()
190+withEmitter :: (Emitter -> IO ()) -> IO B.ByteString
192+ allocaBytes emitterSize $ \e -> do
193+ _res <- c_yaml_emitter_initialize e
195+ bs <- withBuffer $ \b -> do
196+ c_my_emitter_set_output e b
198+ c_yaml_emitter_delete e
201+foreign import ccall unsafe "yaml_emitter_emit"
202+ c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
204+foreign import ccall unsafe "print_emitter_error"
205+ c_print_emitter_error :: Emitter -> IO ()
207+emitEvents :: Emitter -> [Event] -> IO ()
208+emitEvents _ [] = return ()
209+emitEvents emitter (e:rest) = do
210+ res <- toEventRaw e $ c_yaml_emitter_emit emitter
212+ c_print_emitter_error emitter >> fail "yaml_emitter_emit failed"
213+ emitEvents emitter rest
215+foreign import ccall unsafe "yaml_stream_start_event_initialize"
216+ c_yaml_stream_start_event_initialize :: EventRaw -> CInt -> IO CInt
218+foreign import ccall unsafe "yaml_stream_end_event_initialize"
219+ c_yaml_stream_end_event_initialize :: EventRaw -> IO CInt
221+foreign import ccall unsafe "yaml_scalar_event_initialize"
222+ c_yaml_scalar_event_initialize
224+ -> Ptr CUChar -- anchor
225+ -> Ptr CUChar -- tag
226+ -> Ptr CUChar -- value
233+foreign import ccall unsafe "simple_document_start"
234+ c_simple_document_start :: EventRaw -> IO CInt
236+foreign import ccall unsafe "yaml_document_end_event_initialize"
237+ c_yaml_document_end_event_initialize :: EventRaw -> CInt -> IO CInt
239+foreign import ccall unsafe "yaml_sequence_start_event_initialize"
240+ c_yaml_sequence_start_event_initialize
248+foreign import ccall unsafe "yaml_sequence_end_event_initialize"
249+ c_yaml_sequence_end_event_initialize :: EventRaw -> IO CInt
251+foreign import ccall unsafe "yaml_mapping_start_event_initialize"
252+ c_yaml_mapping_start_event_initialize
260+foreign import ccall unsafe "yaml_mapping_end_event_initialize"
261+ c_yaml_mapping_end_event_initialize :: EventRaw -> IO CInt
263+toEventRaw :: Event -> (EventRaw -> IO a) -> IO a
264+toEventRaw e f = withEventRaw $ \er -> do
267+ c_yaml_stream_start_event_initialize
269+ 0 -- YAML_ANY_ENCODING
271+ c_yaml_stream_end_event_initialize er
272+ EventDocumentStart ->
273+ c_simple_document_start er
275+ c_yaml_document_end_event_initialize er 1
276+ EventScalar bs -> do
277+ let (fvalue, offset, len) = B.toForeignPtr bs
278+ withForeignPtr fvalue $ \value -> do
279+ let value' = value `plusPtr` offset
280+ len' = fromIntegral len
281+ c_yaml_scalar_event_initialize
289+ 0 -- YAML_ANY_SCALAR_STYLE
290+ EventSequenceStart ->
291+ c_yaml_sequence_start_event_initialize
296+ 0 -- YAML_ANY_SEQUENCE_STYLE
298+ c_yaml_sequence_end_event_initialize er
299+ EventMappingStart ->
300+ c_yaml_mapping_start_event_initialize
305+ 0 -- YAML_ANY_SEQUENCE_STYLE
307+ c_yaml_mapping_end_event_initialize er
308+ EventAlias -> error "toEventRaw: EventAlias not supported"
309+ EventNone -> error "toEventRaw: EventNone not supported"