@@ -12,7 +12,8 @@
1212-- "Data.Yaml".
1313module Text.Libyaml
1414 ( -- * The event stream
15− Event (..)
15+ MarkedEvent(..)
16+ , Event (..)
1617 , Style (..)
1718 , SequenceStyle (..)
1819 , MappingStyle (..)
@@ -23,8 +24,10 @@ module Text.Libyaml
2324 , encode
2425 , encodeWith
2526 , decode
27+ , decodeMarked
2628 , encodeFile
2729 , decodeFile
30+ , decodeFileMarked
2831 , encodeFileWith
2932 , FormatOptions
3033 , defaultFormatOptions
@@ -74,6 +77,15 @@ data Event =
7477 | EventMappingEnd
7578 deriving (Show, Eq)
7679
80+-- | Event with start and end marks.
81+--
82+-- @since 0.10.4.0
83+data MarkedEvent = MarkedEvent
84+ { yamlEvent :: Event
85+ , yamlStartMark :: YamlMark
86+ , yamlEndMark :: YamlMark
87+ }
88+
7789-- | Style for scalars - e.g. quoted / folded
7890--
7991data Style = Any
@@ -166,6 +178,24 @@ foreign import ccall unsafe "yaml_parser_set_input_file"
166178 -> File
167179 -> IO ()
168180
181+data MarkRawStruct
182+type MarkRaw = Ptr MarkRawStruct
183+
184+foreign import ccall unsafe "get_mark_index"
185+ c_get_mark_index :: MarkRaw -> IO CULong
186+
187+foreign import ccall unsafe "get_mark_line"
188+ c_get_mark_line :: MarkRaw -> IO CULong
189+
190+foreign import ccall unsafe "get_mark_column"
191+ c_get_mark_column :: MarkRaw -> IO CULong
192+
193+getMark :: MarkRaw -> IO YamlMark
194+getMark m = YamlMark
195+ <$> (fromIntegral <$> c_get_mark_index m)
196+ <*> (fromIntegral <$> c_get_mark_line m)
197+ <*> (fromIntegral <$> c_get_mark_column m)
198+
169199data FileStruct
170200type File = Ptr FileStruct
171201
@@ -196,14 +226,8 @@ foreign import ccall "get_parser_error_problem"
196226foreign import ccall "get_parser_error_context"
197227 c_get_parser_error_context :: Parser -> IO (Ptr CUChar)
198228
199−foreign import ccall unsafe "get_parser_error_index"
200− c_get_parser_error_index :: Parser -> IO CULong
201−
202−foreign import ccall unsafe "get_parser_error_line"
203− c_get_parser_error_line :: Parser -> IO CULong
204−
205−foreign import ccall unsafe "get_parser_error_column"
206− c_get_parser_error_column :: Parser -> IO CULong
229+foreign import ccall unsafe "get_parser_error_mark"
230+ c_get_parser_error_mark :: Parser -> IO MarkRaw
207231
208232makeString :: MonadIO m => (a -> m (Ptr CUChar)) -> a -> m String
209233makeString f a = do
@@ -228,6 +252,12 @@ data EventType = YamlNoEvent
228252foreign import ccall unsafe "get_event_type"
229253 c_get_event_type :: EventRaw -> IO CInt
230254
255+foreign import ccall unsafe "get_start_mark"
256+ c_get_start_mark :: EventRaw -> IO MarkRaw
257+
258+foreign import ccall unsafe "get_end_mark"
259+ c_get_end_mark :: EventRaw -> IO MarkRaw
260+
231261foreign import ccall unsafe "get_scalar_value"
232262 c_get_scalar_value :: EventRaw -> IO (Ptr CUChar)
233263
@@ -277,10 +307,12 @@ readStyle getStyle er = toEnum . fromEnum <$> getStyle er
277307readTag :: (EventRaw -> IO (Ptr CUChar)) -> EventRaw -> IO Tag
278308readTag getTag er = bsToTag <$> (getTag er >>= packCString . castPtr)
279309
280−getEvent :: EventRaw -> IO (Maybe Event)
310+getEvent :: EventRaw -> IO (Maybe MarkedEvent)
281311getEvent er = do
282312 et <- c_get_event_type er
283− case toEnum $ fromEnum et of
313+ startMark <- c_get_start_mark er >>= getMark
314+ endMark <- c_get_end_mark er >>= getMark
315+ event <- case toEnum $ fromEnum et of
284316 YamlNoEvent -> return Nothing
285317 YamlStreamStartEvent -> return $ Just EventStreamStart
286318 YamlStreamEndEvent -> return $ Just EventStreamEnd
@@ -314,6 +346,7 @@ getEvent er = do
314346 anchor <- readAnchor c_get_mapping_start_anchor er
315347 return $ Just $ EventMappingStart tag style anchor
316348 YamlMappingEndEvent -> return $ Just EventMappingEnd
349+ return $ (\e -> MarkedEvent e startMark endMark) <$> event
317350
318351-- Emitter
319352
@@ -519,9 +552,19 @@ newtype ToEventRawException = ToEventRawException CInt
519552 deriving (Show, Typeable)
520553instance Exception ToEventRawException
521554
555+-- | Create a conduit that yields events from a bytestring.
522556decode :: MonadResource m => B.ByteString -> ConduitM i Event m ()
523−decode bs | B8.null bs = return ()
524−decode bs =
557+decode = mapOutput yamlEvent . decodeMarked
558+
559+-- | Create a conduit that yields marked events from a bytestring.
560+--
561+-- This conduit will yield identical events to that of "decode", but also
562+-- includes start and end marks for each event.
563+--
564+-- @since 0.10.4.0
565+decodeMarked :: MonadResource m => B.ByteString -> ConduitM i MarkedEvent m ()
566+decodeMarked bs | B8.null bs = return ()
567+decodeMarked bs =
525568 bracketP alloc cleanup (runParser . fst)
526569 where
527570 alloc = mask_ $ do
@@ -561,8 +604,18 @@ openFile file rawOpenFlags openMode = do
561604 then withCString openMode $ \openMode' -> c_fdopen fd openMode'
562605 else return nullPtr
563606
607+-- | Creata a conduit that yields events from a file.
564608decodeFile :: MonadResource m => FilePath -> ConduitM i Event m ()
565−decodeFile file =
609+decodeFile = mapOutput yamlEvent . decodeFileMarked
610+
611+-- | Create a conduit that yields marked events from a file.
612+--
613+-- This conduit will yield identical events to that of "decodeFile", but also
614+-- includes start and end marks for each event.
615+--
616+-- @since 0.10.4.0
617+decodeFileMarked :: MonadResource m => FilePath -> ConduitM i MarkedEvent m ()
618+decodeFileMarked file =
566619 bracketP alloc cleanup (runParser . fst)
567620 where
568621 alloc = mask_ $ do
@@ -589,7 +642,7 @@ decodeFile file =
589642 c_yaml_parser_delete ptr
590643 free ptr
591644
592−runParser :: MonadResource m => Parser -> ConduitM i Event m ()
645+runParser :: MonadResource m => Parser -> ConduitM i MarkedEvent m ()
593646runParser parser = do
594647 e <- liftIO $ parserParseOne' parser
595648 case e of
@@ -598,7 +651,7 @@ runParser parser = do
598651 Right (Just ev) -> yield ev >> runParser parser
599652
600653parserParseOne' :: Parser
601− -> IO (Either YamlException (Maybe Event))
654+ -> IO (Either YamlException (Maybe MarkedEvent))
602655parserParseOne' parser = allocaBytes eventSize $ \er -> do
603656 res <- liftIO $ c_yaml_parser_parse parser er
604657 flip finally (c_yaml_event_delete er) $
@@ -606,10 +659,7 @@ parserParseOne' parser = allocaBytes eventSize $ \er -> do
606659 then do
607660 problem <- makeString c_get_parser_error_problem parser
608661 context <- makeString c_get_parser_error_context parser
609− index <- c_get_parser_error_index parser
610− line <- c_get_parser_error_line parser
611− column <- c_get_parser_error_column parser
612− let problemMark = YamlMark (fromIntegral index) (fromIntegral line) (fromIntegral column)
662+ problemMark <- c_get_parser_error_mark parser >>= getMark
613663 return $ Left $ YamlParseException problem context problemMark
614664 else Right <$> getEvent er
615665